More on PHP and MSSQL

So, I finally implemented by own Zend_Db_Adapter (I subclassed Zend_Db_Adapter_Sqlsrv) that contained additional methods to make it backwards compatible with our legacy database class. While we will utilize the Zend_Db_Adapter methods going forward, there is just way too much legacy code to attempt any sort of PHP 5.3 upgrade without having the backwards compatible piece in place. So, after I get everything set up, the first issue I encounter is related to the code that sets up various session attributes when a user logs in.

The value that would get returned from the database query was 0 (zero). In the 5.2 environment, the $id == DUMMY check would resolve to false, and go into the “do that” block. However, in the 5.3 environment, that same code resolved to true, and went into the “do this” block. I looked everywhere to see if I could find something indicating a change in comparison logic between 5.2 and 5.3. I thought maybe something changed in relation to type juggling. Nothing. I checked on IRC, where it was confirmed that nothing had changed. I looked for a possible INI setting that had it’s default value changed. Nothing. I ran the code through the debugger multiple times, and while it confirmed the behavior I was seeing, I couldn’t figure it out. Finally I realized that in the 5.2 environment, $id was “0” while on the 5.3 environment, $id was 0.

In PHP, “0” == “string” resolves to false, while 0 == “string” resolves to true. So, why was $id a string in the 5.2 environment and an integer in the 5.3 environment? Database libraries always return values as strings, so I figured it had to be something built into Zend_Db_Adapter to “help out” and convert to proper data types. Didn’t find anything. Finally I found where the sqlsrv libraries actually do the type conversion. While you can specify which type to return when fetching a single value, there is no way to disable the type conversions in any of the other fetch methods.

Not knowing how often code like that above might exist, the first thing I attempted was to update the legacy methods for fetching data (sql_fetchrow and sql_fetchrowset) to convert everything back to a string. This totally killed performance. I wasn’t surprised as a good deal of our legacy code contains “select *” style queries, which then fetch the entire result set (both numeric and associative keys) and then only use a single value from the first row returned. If a little more discipline had been practiced when that code was originally written, the “convert back to string” idea might have worked. But I digress…

Finally, I decided to just update the above method to use a === compare. The data type of returned data will just remain at the top of the list of things to check if we encounter additional errors. So far, we haven’t found anything else.

My next post will deal with the retrieval of identity column values when using the legacy methods for inserting data.