OK let me first start by saying, I absolutely love PHP, I tend to compile my PHP from source and for the most part have absolutely no issues with it whatsoever.
Now for work I needed to install PDO extensions to PHP with Microsoft SQL Server support (PDO_DBLIB). I shall also start off by saying that I currently use the standard sqlite extensions to PHP.
Now PDO is actually available on Linux as pdo.so in the modules directory usually by default so let’s actually just try to run
pecl install pdo_dblib
Can’t do that we get the error
“pear/PDO_DBLIB requires PHP extension “pdo” (version >= 1.0)”
OK well we had PDO installed but clearly the wrong version. First up I recompiled PHP adding in the following configuration lines
–with-zlib –enable-pdo=shared –with-pdo-sqlite=shared –with-sqlite=shared
I actually already had zlib compiled, I just reference it here as it’s required. That all worked great, without errors. So now let’s run
pecl install pdo
we should get the right version, correct? No we still get the same error. This led me to the following bug report. Note that this bug was opened in May 2006 and is still unsolved at the time of writing. What we have to do is manually download the package, edit package.xml and remove the PDO dependency line. Install as usual and restart apache!
These are the steps that work
pecl download pdo_dblib
This will download a tar ball of the extension. Extract the tar ball.
tar -xzvf PDO_DBLIB-*.tgz
That will uncompress the package in to a standalone file, package.xml
and a folder containing the extension, in my case it was, PDO_DBLIB-X.X.
Where X was the version number. Open package.xml using your favourite
command line editor. Find and remove the line,
<dep type=”ext” rel=”ge” version=”1.0″>pdo</dep>
Save the package.xml file, and move it in to the PDO_DBLIB directory.
mv package.xml ./PDO_DBLIB-X.X
Navigate to the PDO_DBLIB directory, then install the package from the
directory. You may need root access for this step.
cd ./PDO_DBLIB-XX
pecl install package.xml
After editing php.ini to load
extension=pdo.so
extension=pdo_dblib.so
phpinfo() reported that the DBLib driver was available as was PDO, all was great. Now I tried to run sqlite_open and it refused to work.
I thought maybe it was the pdo sqlite extension that was conflicting, as I don’t actually use the pdo version of sqlite, just the main function library I decided to reconfigure php without the sqlite options.
Then I get an error saying that I had configured PDO as a shared object but sqlite was static. Hmm the PHP manual tells me something different though and I quote
In PHP 5, the SQLite extension and the engine itself are bundled and compiled by default. However, since PHP 5.1.0 you need to manually activate the extension in php.ini (because it is now bundled as shared). Moreover, since PHP 5.1.0 SQLite depends on PDO it must be enabled too, by adding the following lines to php.ini (in order):
So this is telling me that SQLite is enabled by default and is installed as shared. Well the PHP installer just told me different, that it’s installed by default but as static!
OK so back to configure PHP again but this time with the sqlite shared options. Then we’ll reference sqlite.so in the php.ini extensions and restart apache!
Oh no we can’t load apache because the version of sqlite.so is incompatible with the version we need for pdo_dblib.so.
Let us run
pecl install sqlite
Running that gives us the following error
tmp/tmp8laqB1/SQLite-1.0.3/sqlite.c:125: warning: initialization from
incompatible pointer type
/tmp/tmp8laqB1/SQLite-1.0.3/sqlite.c:126: warning: initialization from
incompatible pointer type
*** Error code 1
make: Fatal error: Command failed for target `sqlite.lo’
ERROR: `make’ failed
The PHP bug report at http://pecl.php.net/bugs/bug.php?id=8181 that was opened in July 2006 tells us this has all been fixed, but with numerous responses telling the developers that it’s still broken. At the time of writing, this is still broken!
This then leads me to the following fix
$ pear download sqlite
then unpacked and began to compile it
$ tar zxvf SQLite-1.0.3.tgz
$ cd SQLite-1.0.3
$ phpize
$ ./configure
$ make
edit sqlite.c, comment out the following line:
/* static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; */
And then change these lines
function_entry sqlite_functions[] = {
PHP_FE(sqlite_open, arg3_force_ref)
PHP_FE(sqlite_popen, arg3_force_ref)
to:
function_entry sqlite_functions[] = {
PHP_FE(sqlite_open, third_arg_force_ref)
PHP_FE(sqlite_popen, third_arg_force_ref)
$ make
$ make install
$ cp modules/sqlite.so /usr/lib/php/modules
$ /sbin/service/httpd restart
Why oh why do I have to edit the c source code to get this working? Which by the way DOES actually fix the problem and now I have PDO, SQLite and PDO_DBLIB working on the same system.
This is why I’m starting to loose faith in the open source PHP community, not because they do a great job in the first place, but because bugs like this exist for well over 2 years!
The response from the Open Source community will be, fix it yourself. That simply isn’t the point, I’m not a C developer, nor do I have the inclination to be. I also do not know the inner C workings of PHP to easily fix these issues.
I’ve just wasted two days of my life researching, testing, debugging PHP extensions, I hope it helps anyone else with these issues!