About PHP Database API has different functions for different databases, and some people have tried to use PHP's object-oriented features to make some packages. Among them, there are more famous adoDBs, phplib. Later, Pear DB in the Pear project in the world is even more leaders. These packages with an object-oriented database API are generally referred to as database abstraction layers.
This article describes some excellent functions of PEAR DB to fuse the Metabase library in PEAR, and a very good introduction to MDB, which is easy to use, and very powerful. The author is the master of MDB.
I want to get the latest original and translation of my recent PHP / PEAR, please visit my homepage
Write overce - Run Anywhere Written - run everywhere
PEAR MDB Database Abstract Layerpear MDB Database Abstract Layer
Author: Lukas Smith Translator: taowen
While this is a Java marketing phrase it is also a key feature of PHP. Many business models depend on operation system independence to ensure that products can be sold to a wide range of customers. So why lock yourself in with a specific database vendor? Database abstraction layers allow you to develop your application independent of a database. but often they eat more performance than you are willing to give or they do not abstract enough to eliminate all database specific code. this is Java's a marketing slogan, but it is also One of the key features of PHP. Many business models depends on operating system independence to ensure that the product can be sold to a wide range of customer groups. Thus, why should you tie your own database manufacturers? The database abstraction layer allows you to develop your app independently. However, usually their impact of performance exceeds what you want, or they are not abstract to eliminate all code related to the specific database.
What Will this Article TEACH ME? What will this article teach me?
This article will give a good introduction to the database abstraction package PEAR MDB. The focus will be explaining the more advanced features of MDB like data type abstraction and the XML based schema management that go beyond what other similar packages offer. A basic level of understanding This article will have a good introduction to the database abstract package PEAR MDB. The focus of the article will be a more advanced feature provided by MDB transcending a similar package, such as data type abstraction, and XML-based SCHEMA management. The basic understanding of PHP and SQL is recommended.
Why Another Database Class? Why is another database class?
Often, web projects are added to existing IT infrastructures, where the client already made a choice of what RDBMS (relational database management system) to work with. Even if that is not the case different budgets might affect what database you chose for deployment. Finally , you as the developer simply might prefer not to lock yourself in with a specific vendor So far this meant to keep multiple versions for each supported database or giving up more performance and ease of use than necessary:.. Enter PEAR MDB usual, web project The customer has determined that the IT infrastructure that is already added after using the RDBMS (Relational Database Management System). Even if it is not because of the possible data you choose to deploy due to different budgets. In the end, you may be simple as a developer to tie yourself in a vendor. Since then, it means that each supported data remains version or sacrifices more performance but more than necessary, easy-to-use: walk into the PEAR MDB.
MDB is a database abstraction layer that aims to make writing RDBMS independent PHP application development a straightforward process. Most other so called database abstraction layers for PHP only provide a common API for all supported databases and only very limited abstraction (mostly only for sequences). MDB on the other hand can be used to abstract all data being send and received from the database. Even database schemas can be defined in a RDBMS independent format. But it does this while retaining a high level of performance and ease of use. This was achieved by closely examining two popular database abstraction layers, PEAR DB and Metabase, and merging them. But during the merging the opportunity was also used to clean up their merged APIs as well as any performance hindering design patterns. MDB is a focus on making the preparation of RDBMS The unrelated PHP program is a database abstraction layer for a simple process. Most of the other PHP's so-called database abstraction layers provide a public API and very limited abstraction (mostly for sequences). On the other hand, MDB can be used to abstract data from all databases to send and receive. Even database schema can be defined as RDBMS-independent format. But it provides these features while still maintaining high performance and easy to use. This is obtained by deeply observing the two popular database abstraction layers, Pear DB, and Metabase, and after they are fused. And during the fusion process, this opportunity cleans the API after they fuse and any design of the impact performance. How does the How Did MDB Come to Be? MDB appear?
Back in fall 2001, I was looking for a database abstraction package that would make my companies application framework RDBMS independent. The goal was to reduce database specific code to zero. The only package I found that offered such features was Metabase. But Metabase had a somewhat uncomfortable API that was partly a result of the compatibility to PHP3. This also made Metabase slower than it needed to be for our purposes, since we did not need PHP3 compatibility. Nonetheless, we decided that Metabase is our only option. But even after adding a performance enhancing patch to Metabase we felt that we were giving up too much performance. We met with the author of Metabase at the International PHP Conference 2001 and we talked about the benefits of having something like Metabase as part of the PEAR project. Shortly Afterwards a Discussion Began Once More In The Pear Mailing List About The Potential Benefits of a Merge of Pear DB and MEAR DB AND METABASE. AFTER MUCH Discussion At my company we deci Ded to take up this task. After SEVERAL MONTHS of HARD WORK WORK. As early as 2001, I am looking for a database abstraction that can be able to make my company's program frame with RDBMS. package. This goal is to reduce the number of code related to a particular database to zero. I found that a single package that provides such a function is Metabase. But Metabase has some parts because it is uncomfortable with PHP3 compatible API. Despite this, we decided that Metabase is our only choice. But even after adding a performance improvement to Metabase, we still feel that we give up too much performance. We met the author of Metabase at the 2001 PHP International Conference, and we talked about the benefits of making things like Metabase as part of the PEAR project. Soon, a discussion was started on the PEAR mail list on Pear DB and Metabase. After our company has conducted many discussions, we decided to assume this task. After several months of hard work, we now have the first stable release of MDB. What does mdb do for you? What did MDB give you?
MDB combines most of the features of PEAR DB and Metabase. Actually, the only feature that is missing is PEAR DB's feature of returning an object as a result set. This feature was dropped because the feature's usage never became abundant but the performance penalty was quite apparent. A lot of development time was spend on making the API as intuitive as possible as well. Finally, MDB provides this functionality at a very high level of performance that is at least as fast as PEAR DB and much faster than Metabase. Here is The List of the Most Important Features: MDB combines most of the features of Pear DB and Metabase. In fact, the only one in the Pear DB is no longer existing as a result set returns an object. We gave up this feature because this characteristic is not commonly used and is very obvious for performance loss. Many development time is used in making APIs as much as possible. Finally, MDB is very highly providing these features at least as fast as Pear DB and is much faster than Metabase. The most important characteristic of the list: OO-style APIprepared queries emulationfull data type abstraction for all data passed to and from the database (including LOB support) transaction supportdatabase / table / index / sequence creation / dropping / alteringRDBMS independent database schema managementIntegrated into the Pear Framework (Pear Installer, Pear Error Handling ETC.)
OO-style API pre-sub-query simulation to all data types that are passed and from the data removed (including LOB support) transaction support database / table / index / sequence creation / discard / change RDBMS-independent database SCHEMA Management inherits into the PEAR framework (PEAR installer, PEAR error handling, etc.)
So how does it work? So how do it use?
MDB provides some very advanced abstraction features. It is important to keep in mind that these features are optional. But using them is critical in writing RDBMS independent PHP applications. An example of how the basics of MDB work can be found under Links & Literature at the end of the article. As stated earlier, the focus of the article is to introduce the features that set MDB apart from other database abstraction layers for PHP. You can find example scripts for all code examples found in this article on the CD that is Packaged with this issu.mdb offers some very advanced abstract characteristics. Remember that these features are only important to choose from. But it is very important to use them when writing RDBMS-independent PHP programs. A display using MDB is a "link and literature" section of the end of the article. As mentioned earlier, the focus of the article describes those features that make MDB different from other PHP database abstraction layers. You can find the code for all of these example scripts in the CD packaging with this period. But first we will need to get MDB installed. This is actually quite easy using the PEAR installer. I can not cover the entire PEAR Installer within this article but I hear the next issue will talk about great details about all the ins and outs of the PEAR framework There is work going on to make the Installer work on Windows but the support is still a bit flaky For * nix systems you will need a CGI version of PHP installed on your system and simply run the following command:.. but first we You need to install the MDB. This is actually very easy to use the PEAR installer. I can't tell the PEAR installer in this article but I heard that the next phase will discuss the pear framework in the PEAR framework. Let the installer run in Windows work as but support still have a little quirky. For * NIX systems you need PHP CGI version installed in your system and simply run the command:
Lynx -Source Go-pear.org | PHP
After Completion The Installation Process You Simply Need To Type One More Command and You Are All Set. You only need to enter a line of command after the installation is complete.
Pear Install MDB
If The Above Does NOT Work for you there is always the option of getting the package................ If the previous process is not used by you, there is always a The PEAR MDB home page is directly obtained option. The URL is listed in the finals of the article. MAKING Uses of Data Type Abstract uses data types
Since most databases tend to have some specialities or quirks it is important for MDB to hide these differences from the developer MDB achieves this by defining its own internal data types:. Text, boolean, integer, decimal, float, date, time, time stamp , large objects (files). All data that is passed to and from the database may be converted from MDB's internal format to the databases internal format. The accompanying example scripts to this section can be found in the datatype directory. Let us look at the FOLLOWING Query: Because most databases tend to have some personality or quirks, it is very important to hide developers to developers for MDB. MDB achieves this: Text, Boolean, Integer, Decimal, Float, Date, Time, Time Stamp, Large Objects. All data passed to the database and the data obtained from the database can be converted into an internal format of MDB or transform from the internal format of the database. This section related example scripts can be found in the DATYPE directory. Let's take a look at the query below:
$ Session = '098f6bcd4621d373cade4e832627b4f6'; // set time out to 30 minutes $ timeout = time () 60 * 30; // SELECT query showing how the datatype conversion works $ query = 'SELECT createtime, user_id FROM sessions'; $ query = 'Where session ='. $ Session; $ query. = 'And lastaccess <'. $ Timeout;
This query will most likely fail if it were send to a database. The reason being that the value stored in $ name would need to be converted to the correct string format. This would mean the contents of $ name would have to have special characters escaped and quotes placed around PEAR DB provides the method DB:.... .quote () for this In MDB the method is called MDB :: getTextValue () The difference is that MDB offers such a method for every data type listed above So we CAN Also Convert Format. This query is to fail if it is sent to the database. The reason is that the value stored in the $ name needs to be converted to the correct string format. This may mean that the content of $ name may have a special escape character or surrounded by quotation marks. Pear DB provides this method DB: .quote (). This method is called MDB :: getTextValue () in MDB. The difference is that MDB provides such a function to each previously listed data. Therefore, we can also convert $ TIMEOUT to the correct format. // convert $ timeout to the MDB timestamp format $ timeout = MDB_date :: unix2Mdbstamp ($ timeout); // SELECT query showing how the datatype conversion works $ query = 'SELECT createtime, user_id FROM sessions'; $ query =' WHERE. Session = '. $ MDB-> GetTextValue ($ session); $ query. =' and lastaccess <'. $ mdb-> getTimeStampValue ($ timeout);
For the sake of the example let us assume that we only want to retrieve the first row. MDB :: queryRow () fetches the first row, he frees the result set and returns the content, so it is exactly what we want. In order to make A demo, let us assume that I just want to get the first line. MDB :: queryRow () gets the first line, it releases the result set and returns its content, so it is what we want.
$ result = $ mdb-> queryrow ($ query);
But different RDBMS return data like dates in different formats. So, if I then want to do some date arithmetic it is important that data is always returned in the same format regardless of the RDBMS chosen. This can be done semi-automatically by MDB. All you need to do is Tell MDB What Type Your Result Columns Will Have and MDB Handles The Conversion. The Easiest Way Is To Pass Such Information With The Query Method Call: But different RDBMS returns a format used in data such as a different date. different. Therefore, if we have to calculate some data, regardless of the selected RDBMS, it is important to return the data in the same format. This can be completed by MDB semi-automatic. All you need to do is telling your results that will be what types, MDB will process the work of the conversion. The easiest way is to pass such information to the query function. $ TYPES = Array ('TimeStamp', 'Integer'); $ Result = $ MDB-> QueryRow ($ query, $ types);
This tells MDB that the first column of the result set is of the type `timestamp 'and the second is of the type` integer'. All methods that allow querying can take such meta-information as an optional parameter. The data can also be set later using MDB :: setResultTypes (). Depending on the database that the data is retrieved from, it will then convert the returned data accordingly. The MDB internal data format for timestamps is the ISO 8601 standard. Other packages such as PEAR :: Date Can Handle This Format. MDB Also Provides A Small Number of Methods For Date Format Conversion In The MDB_DATE CLASS THAT CAN BE INCLUDED OPTIONALL. This tells the first column type of the MDB result set is 'TimeStamp' and the second column is 'INTEGER' . All query functions can accept such meta information as an optional parameter. Data can also be set with MDB :: SetResultTypes () after things. Depending on the database obtained, it will then return the data returned by the corresponding conversion. The data format of the TimeStamps inside the MDB is to follow the ISO 8601 standard. Other packages like Pear :: Date can handle this format. MDB also provides some data format conversion functions in the MDB_DATE class, which can be optionally included.
Since pretty much every RDBMS returns integer data the same way there is no need to convert integer data So, in order to gain a slight performance improvement you could do the following:. Because a considerable number of RDBMS returns the integer data in the same manner, no Necessary to convert integer data. Thus, in order to obtain a slight performance improvement you can do: $ TIMESTAMP '); $ Result = $ MDB-> QueryRow ($ query, $ typees);
This way only the first column of the result set would be converted. Of course this may become an issue if MDB would be used in conjunction with a database that does return integers differently. However unlikely, the slight performance increase might not be worth this risk This is used by the first column of the result set will be converted. Of course, if MDB is used to return a database of different numbers, this may become a problem. However, slight performance improvements may not be worthy of this risk. But once again, it shows the use of these features is only available.
Listing 1 shows an example use of prepared queries. These can be quite convenient if you have to run a number of queries where the only difference is in the data that is being passed to the database while the structure of the query remains the same. Advanced Databases CAN Store The Parsed Query In Memory TO OFFER A Performance Boost.Listing 1 shows an example of using pre-prepared queries. If you have to run a lot of queries and the only difference is that the data is passed to the database, but the structure of the query is still the same, these can be quite convenient. Advanced databases can save performance in memory in memory to accelerate performance.
Listing 1
$ alldata = array (array (1, 'one', 'un'), array (2, 'two', 'deux'), array (3, 'three', 'Trois'), Array (4,' FOUR ',' quatre '));
$ P_QUERY = $ MDB-> PREPAREQUERY ('INSERT INTO NUMBERS VALUES (?,?,?)'); $ param_types = array ('integer', 'Text', 'Text');
Foreach ($ ALDATA AS $ ROW) {$ MDB-> Execute ($ P_QUERY, NULL, $ ROW, $ Param_Types);
Each of the 4 arrays that are stored in $ alldata will be used in an execute statement. The data will automatically be converted to the correct format. Since this is an insert statement the second parameter for MDB :: execute () is set to NULL Because We Will Not Have Any Result Columns for Which We 10 NEED TO SET DATA TYPES. All four arrays stored in the AllData will be used for the Execute statement. The data will be automatically converted to the correct format. Because this is a plug-in statement, the second parameter of MDB :: execute () is set to NULL because we will need to set the data type if we will have any result. Among the supported data type are also LOB's (Large OBjects) which allow you to store files into a database. Binary files are stored in BLOBs (Binary Large OBject) and normal text files are stored on CLOBs (Character Large OBject). In MDB you can only store LOB's using prepared INSERT and UPDATE queries. Using either MDB :: setParamBlob () or MDB :: setParamClob () you can set the values of the LOB field in a prepared query. Both methods expect to be passed a LOB object however Which can be created using mdb :: CreateLob (). There is also a LOB (large object) in the supported data type, which makes we can save files in the database. Binary files are stored in the BLOB (binary large object) and the ordinary text file is stored in the Clob (character large object). In MDB, you can only store LOB using pre-pre-pre-pre-pre-pre-sub-INSERT and UPDATE query. Using MDBA :: SetParamblob () or MDB :: SetParamClob () You can set the value of the LOB domain that pre-prepares the query. Both functions are expected to deliver a LOB object, and it can be created using MDB :: CreateLob ().
$ binary_lob = array ('type' => 'INPUTFILE', 'filename' => './myfile.gif'); $ blob = $ mdb-> createlob ($ binary_lob);
$ Character_lob = array ('Type' => 'Data', 'Data' => 'This Would Be a Very Long String Container The Clob Data'); $ Clob = $ MDB-> CreateLob ($ Character_LOB);
As you can see MDB :: createLob () is passed an associative array The value for the Type key may be one of the following:.. Data, inputfile or outputfile The first two are used when you want to write a LOB into the database . If you have the LOB stored in a variable you should use data while inputfile should be used to read the LOB directly from a file. Finally, outputfile should be used when you want to retrieve a LOB from the database. Depending on if you are Using Data or InputFile You NEED TO SPECIFY A Value for the FileName Key or The Data Key As Seen In The Above Example. Now We Well Store The Above Lob's in The Database. If you can see, MDB :: CreateLob () Transfer a relationship array. The value of the TYPE key may be one of the following: Data, InputFile or OutputFile. The first two times for you want to write the LOB to the database. If you have a LOB stored in a variable, you should read the LOB directly from the file when you need to use InputFile. Finally, Outpufile should be used when you want to read LOBs from the database. Depending on whether you use data or inputfile you need to specify a value to specify a value, like the example above. Now, we will store the previous LOB to the database. $ P_QUERY = MDB-> PrepareQuery ('INSERT INTO FILES (ID, B_DATA, C_DATA) VALUES (1,?,?);
$ mdb-> setParamblob ($ P_QUERY, 1, $ BLOB, 'B_DATA'); $ MDB-> SetParamClob ($ P_QUERY, 2, $ Clob, 'C_Data');
$ results = $ mdb-> executeQuery; $ p_query;
In order to fetch the above file from the database we will need to first select the data from the database and create a LOB object using MDB :: createLob (). This time we will set `Type 'to` outputfile'. For the database Get the above file, we need to select data from the database and create a LOB object using MDB :: CreateLob (). This time we will set 'type' for 'OutputFile'
$ MDB-> Query ('SELECT B_DATA from files where id = 1');
$ binary_lob = array ('type' => 'outputfile', 'result' => $ results, 'Row' => 0, 'Field' => 'b_data', 'binary' => 1, 'filename' => './myfile2.gif'); $ binary_lob); Now We can read the lob from the result set using mdb :: readlob (). Passing a foreth of 0 to mdb :: readlob () means that the entire LOB is read and stored in the file we specified above. Once we are done we can free the resources. Alternatively, you can set any length larger than zero and read the LOB using a while loop checking MDB :: Endoflob (). Now we can use MDB :: readlob () to read LOBs from the result set. Passing length 0 Give MDB :: Readlob () means that the entire LOB is read and stored in the file you specified in front of it. Once the task is completed, we can release the resources. You can also set any length greater than zero and check MDB :: endOflob () using a while loop to read the LOB.
$ MDB-> Readlob ($ BLOB, $ DATA, 0);
It is important to note that you may not mix this method of fetching with the bulk fetching methods like MDB :: fetchAll () as this will cause problems in most PHP database extensions. At some point MDB may be able to retrieve LOB's using the bulk Fetching Methods. Note that you don't give this acquisition function and Bulk get functions like MDB :: fetchall () because it will cause problems in most PHP database extensions. At some time, MDB may be able to use the BULK acquisition function to get LOB.
As we have seen in this section MDB features its own set of native data types that are automatically mapped to native data types in the database. This ensures that no matter what data we send or retrieve from the database it will always be in the same format no matter what RDBMS is used. As I have mentioned in the opening paragraph of this section this obviously requires that the data types used in the database are what MDB expects. This requirement was made to ensure that the mapping is done with a minimal performance loss If we see this section, the Native Data Type Set of the MDB feature itself is automatically mapped in the native data type in the database. This guarantees what kind of data we send and receive from the database, it can use the same format with the useful RDBMS. As I mentioned in this section, this is clear that the data type used by the database is MDB expected. This requirement is used to ensure that the price takes place is small. The next section will teach us how MDB is assisted to use the correct data type in the database. Making Use of XML Schema Files Using XML Schema files
With the features described in the last paragraph you can write truly database independent applications But MDB tries to go one step further:. It allows you to define your schemas in XML A manager converts this schema into the necessary SQL statements for each RDBMS This.. Means That You can Use the Same Schema for any of the supported rdbms. The Examples for this section Section Can Be found in the xml_schema Directory. Using the features described in the previous paragraph, you can write a real database independent program. But MDB attempts to take a step forward: it allows you to define your schema with XML. A manager converts this SCHEMA to the necessary SQL statements for each RDBMS. This means you can use the same SCHEMA for all supported RDBMs. Examples of this section can be found in the XML_SChema directory.
We will now write an XML schema file from scratch. First we must define an XML document. The database definition is contained within a database tag. The name of the database is defined using the name tag. The create tag tells the manager if the database SHOULD BE CREATED IT DOES NOT YET EXST. IF you split Up Your Schema INTO Several Files You Will Only NEED TO SET CREATE TO 1 in The File You Will Submit First To The Manager. We will now write an XML Schema file from the head. First, we must define an XML document. The database definition is included in a Database tag. The name of the database is defined using the NAME tab. The CREATE tag tells the Manager database to be created when it does not exist. If you split your schema file into several files you first submit to the manager to 1. XML Version = "1.0" encoding = "ISO-8859-1"?>
As you may have guessed from the database name auth the purpose of this database is to store user data for a simple authentication application. Listing 2 defines a table in which we can store the user data. As you may have guessed from the name of the database auth The purpose of this database is to store user data for a simple verification program. Listing 2 defines a table we can store user data.
Listing 2