PHP modules for standardizing DB access

Por: Nediam <javier@nediam.com.mx>
Publication date: 2005-05-25
Last updated: 2006-03-26


Sometimes we require that some of our applications be able to run using different database management systems. This situation may arise either because the company where our application is running is in the process of migrating from its RDBMS and our programs still need to keep running, or because our different clients work with different DBMSs (one client may use MySQL for his company while another could only use Informix), which is highly likely to occur in real life. This is why there is the need for a mechanism that enables our applications to work in a 'transparent' way with relation to the database management system, regardless of which it is.

In order to achieve this, one posible solution could be to manually modify each of the scripts that make up our application with the appropriate functions to interact with the new DBMS. For example, if our application consists of 10 scripts that use access to DBs, we would have to modify each of the 10 files, one by one. Maybe it wouldn't be so difficult and it would not take too long to make these changes, but what happens if our application has 200 or 500 scripts that use access to DBs?

For medium or large applications many developers use a module for interaction with DBs. This is very useful because in this module the connection parameters are specified as well as other necessary configurations for establishing the connection with the DBMS, and in case some parameter related to the DB server had to be changed later (for example the IP address of the server or the DB user password), only this file would have to be changed and not all scripts.

Then what we would have to do is standardize the functions that conform the DB interaction modules so our application can work in a similar way no matter which DBMS is interacting with. In other words, if our application currently interacts with PostgreSQL and in our module we named the function to execute some SQL sentence execute_query, then, if we need that our application now use Informix, in the module we create to interact with Informix the function for executing SQL sentences must have the same exact name: execute_query. The same applies for the names of all functions in our module for DB interaction.

Let us suppose, for example, that our application currently uses Informix, and that we have a file named modules_lst.inc containing all the includes we need. It would look something like this:

<?php
        function add_requires($path='./')
        {
                require($path . 'functions/informix_fns.php');
                require($path . 'functions/output_fns.php');
                require($path . 'functions/misc_fns.php');
                require($path . 'functions/math_fns.php');
        }
?>


Continuing with the example, the scripts that make up the application would begin something similar to this:

<?php
require('./modules_lst.inc');
add_requires();
....
....
?>


So to in order for our application be able to work with another DBMS, instead of changing 200 or 500 scripts we simply have to change one line in one script! (supposing that there is already a module for interaction with the new DBMS. At the end of this article there are some modules for interaction with distinct DBMS available for downloading. Continuing with the example, to make our application now work with PostgreSQL instead of Informix, first we have to design or obtain a module for DB access in PostgreSQL. We need to verify that the new module meets the standardization of function names in our current module in Informix. We must also make sure both managers have the functionality required for the application. Then we need to do the corresponding tests to verify that our module is working correctly. Finally, we need to change the line of the require in the file modules_lst.inc to make our application now use PostgreSQL DB access module:

<?php
        function add_requires($path='./')
        {
                require($path . 'functions/postgresql_fns.php');
                require($path . 'functions/output_fns.php');
                require($path . 'functions/misc_fns.php');
                require($path . 'functions/math_fns.php');
        }
?>

That would be what it takes to get our application to start using PostgreSQL instead of Informix, without modifying a single line of the 200 or 500 scripts that make up our application :).

The following table shows the standard of names proposed for interacting with databases and the functions that would have to be used to be implemented in some DBMS:

Standard functionDescriptionPostgreSQL functionMySQL function Informix functionOracle function
fco_db_connect($db) Opens a DB connection pg_connect mysql_connect ifx_connect oci_connect
fco_db_pconnect($db) Opens a persistent DB connection pg_pconnect mysql_pconnect ifx_pconnect oci_pconnect
fco_db_close($db) Closes a DB connection pg_close mysql_close ifx_close oci_close
fco_db_query($db, $qry) Executes a SQL sentence pg_query mysql_query ifx_query oci_parse
oci_execute
fco_db_fetch_row($res) Returns an array containing the values of the next row of the result resource pg_fetch_row mysql_fetch_row N/A oci_fetch_row
fco_db_fetch_array($res) Returns an associative array with the values of the next row of the result resource pg_fetch_array mysql_fetch_assoc
mysql_fetch_array
ifx_fetch_row oci_fetch_array
fco_db_fetch_all($res) Returns and associative array with all the rows of the result resource pg_fetch_all N/A N/A oci_fetch_all
fco_db_num_rows($res) Returns the number of rows that contains a result resource pg_num_rows mysql_num_rows ifx_num_rows oci_num_rows
fco_db_num_fields($res) Returns the number of fields that contains a result resource pg_num_fields mysql_num_fields ifx_num_fields oci_num_fields
fco_db_table_types($db, $table) Returns an associative array with the names of the fields and data types of a table N/A N/A ifx_fieldtypes N/A
fco_db_last_error( ) Saves in a global variable the description of the last db error occurred pg_last_error mysql_error ifx_errormsg oci_error
fco_db_display_last_error( ) Displays the last db error ocurred and exits the script N/A N/A N/A N/A

Note: The prefix 'fco' in the names of the standard functions was used to avoid conflicts with the names of native PHP functions


Following this standard of names, the modules for interact with some DBMS would look like this:

Click on the corresponding link to view/download a module
DMBSVisualizeDownload
- PostgreSQL postgresql_fns postgresql_fns
- MySQL mysql_fns mysql_fns
- Informix informix_fns informix_fns
- Oracle oracle_fns oracle_fns


In order for these modules to work, the clients of the DBMS in question should have been installed already and properly configured. Also, PHP should have been compiled with support for these. If you have any question regarding clients' configuration (particularly Informix and Oracle, which are the most tedious) feel free to email me and we can sort it out.

The functions presented in this article are the basic ones required for interaction with databases. The important thing is to adapt the modules for each particular application. For example, a simple application could be well enough with the functions herein presented so it would be able to work with different DMBS. Yet, other applications may require more standardized functions. The particularities of each manager we are working with should also be considered (such as the fact that the array that returns the function ifx_fetch_row in Informix has no numerical indexes, or that in Oracle the names of the keys in associative arrays are in capitals). This is to avoid affecting the functionality of our application when we migrate to another DBMS.


I hope this article could be helpful for you. If you have any questions or comments, please send them to <javier@nediam.com.mx>


References:


The latest version of this document is available at: http://nediam.com.mx/en/source/db_modules/index.php

<< 0 comments >>



TOP