Joomla Asked by Irata on September 5, 2021
I have a need to connect to a data source on an old unix box via ODBC, but I don’t seem to be getting far and I can’t find any examples to help me.
I have started with https://docs.joomla.org/Connecting_to_an_external_database and set up the following details:
$option['driver'] = 'pdo'; // Database driver name
$option['host'] = 'nnn.nnn.nnn.nnn:nnnn'; // Database host name
$options['dsn'] = 'Fred';
$option['user'] = 'Barney'; // User for database authentication
$option['password'] = 'Wilma'; // Password for database authentication
$option['database'] = 'dbname'; // Database name
$option['prefix'] = ''; // Database prefix (may be empty)
$dbx = JDatabaseDriver::getInstance($option);
With that configuration, I get an error message of:
Cannot instantiate abstract class JDatabaseDriverPdo E:wwwbedrocklibrariesjoomladatabasedriver.php:313
This happens because driver.php
takes the value ‘pdo’ from $option['driver'] = 'pdo';
and appends it to a class of JDatabaseDriver to be found in librariesdatabasedriverpdo.php
which is an abstract class the extends JDatabaseDriver
hence the message. It is the only abstract class in /driver
. If I replace ‘pdo’ with ‘odbc’, I get a message to say it can’t load the database driver which will be because the class JDatabaseDriverOdbc is not found.
When I look at librariesdatabasedriverpdo.php
, I can see that ‘odbc’ is the default if no other driver is specified and further down I can see the connection string set up for ‘odbc’ so it looks like it is supported.
public function __construct($options)
{
// Get some basic values from the options.
$options['driver'] = (isset($options['driver'])) ? $options['driver'] : 'odbc';
$options['dsn'] = (isset($options['dsn'])) ? $options['dsn'] : '';
$options['host'] = (isset($options['host'])) ? $options['host'] : 'localhost';
...
// Find the correct PDO DSN Format to use:
switch ($this->options['driver'])
{
..
case 'odbc':
$format = 'odbc:DSN=#DSN#;UID:#USER#;PWD=#PASSWORD#';
$replace = array('#DSN#', '#USER#', '#PASSWORD#');
$with = array($this->options['dsn'], $this->options['user'], $this->options['password']);
It seems to me that $option['driver'] =
has two different uses depending on where it is used, as either a suffix to build a class name or as a switch to set the connection string.
I have also tried to use the class directly with
`$option['driver'] = 'odbc';
...
$dbx = JDatabaseDriverPdo::getInstance($option);
however that still tries to find a class of JDatabaseDriverOdbc
from driver.php
I really could use some pointers in the right direction or an example of ODBC in use.
Some hours later…
Looking at the code in driver.php and some of the data base formats in librariesdatabasedriver
it would appear I need to create a new class that extends JDatabaseDriverPdo, eg. class JDatabaseDriverOdbc extends JDatabaseDriverPdo
and make that available to my code. So I think the Joomla answer is yes you can do it if you write your own connector.
Although I have had to put this work aside for the time being I wanted to provide some closure to this question.
The last part of my original post is approximately what was required, I had to create a /joomla/database/odbc.php
which I created from copying from one of the existing drivers and change the relevant references to 'odbc', and that extended the JDatabaseDriverPdo class.
That got me past the error message in the original Question but then I hit a problem with the next line, $query = $dbx->getQuery(true);
due to either an error in the core code or my lack of understanding but it is worth mentioning here if anyone else finds this post.
The getQuery command calls this piece of code in /joomla/database/driver.php
public function getQuery($new = false)
{
if ($new)
{
// Derive the class name from the driver.
$class = 'JDatabaseQuery' . ucfirst($this->name);
// Make sure we have a query class for this driver.
if (!class_exists($class))
{
// If it doesn't exist we are at an impasse so throw an exception.
throw new JDatabaseExceptionUnsupported('Database Query Class not found.');
}
return new $class($this);
}
else
{
return $this->sql;
}
}
However $this->name
which creates the $class is not picking up the value set in the JDatabaseDriverXxxx for $this-name
therefore it always falls out the bottom returning a value of mysqli
.
My resolution was to copy this function into my joomla/database/odbc.php so that it would receive the correct value of $this->name
, odbc.
The lack of being able to find a suitable linux ODBC driver to work with the target has put this stage of the project on hold for the time being.
Correct answer by Irata on September 5, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP