Home arrow PHP arrow Page 3 - Accessing Databases with Class

Extending classes - PHP

PHP offers a large number of native interfaces to databaseservers from different vendors. All of them are accessed in asimilar, but subtly different way, which has its reason in thedifferences of the underlying C API and in the historicdevelopment of PHP's database support. In this article, you willlearn how to create an easier interface to SQL databases byemploying the class and object features of PHP.

TABLE OF CONTENTS:
  1. Accessing Databases with Class
  2. A database access class as example
  3. Extending classes
By: Kristian Kohntopp
Rating: starstarstarstarstar / 10
June 14, 1999

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement
Our class is now useable, albeit not productively. We are able to establish a database link, but without query() and next_record() functions we are unable to make use of it. We are going to use the class anyway, to show how to set it up for a production environment. Example 5 shows a workable, but inconvenient method how you could deploy the class.

Example 5: A non-recommended method to configure and deploy DB_Sql.


<?php // The include file contains the definition of DB_Sql. require("db_mysql.inc"); // $db is our database object. $db = new DB_Sql; // Overwrite the connection parameters as needed. $db->Host = "localhost"; $db->User = "kris"; $db->Password = "" $db->Database = "sampleserv"; // Try to connect to the database server process. $db->connect(); ?>

This is not a recommended method to configure a class for use, because after creation of the object you have to set up all variables within that object manually and you have to do it over and over on each page where you are using it. It would be much nicer if we were able to define a class that is just like DB_Sql, but with different connect parameters. In fact we can easily do this: We can extend any given class and base the definition of a new class on any single existing class. Example 6 shows the definition of a class DB_Sample, which performs exactly the same connect as Example 5. Example 6b shows how to use this class.

Example 6: Definition of a new class DB_Sample, based on DB_Sql


// DB_Sample is just like DB_Sql, only different.. :-) class DB_Sample extends DB_Sql { var $Host = "localhost"; var $User = "kris"; var $Password = ""; var $Database = "sampleserv"; }

Example 6b: Using DB_Sample.


// This include file contains the definiton of DB_Sql require("db_mysql.inc"); // This include file contains the definition of DB_Sample require("local.inc"); // Create a database connection object $db = new DB_Sample; // Connection to database... $db->connect();

DB_Sample is not empty, but contains exactly the same variables and functions as DB_Sql, although these are not written down explicitly in the class definition. The magic is in the class definition: DB_Sample extends DB_Sql, that is, DB_Sample starts as a simple copy of DB_Sql. Within the class body of DB_Sample certain definitions of DB_Sql are overwritten, specifically we redefine the database connection parameters.

On use of DB_Sample as shown in Example 6b, the database connection will be created using these redefined parameters. Unlike Example 5 we do not have to mention these parameters on each page, but DB_Sample "automatically" knows the appropriate parameters and does the right thing. If we had to change the connection parameters, we could do so by editing a single file, local.inc. This is very convenient, especially in larger projects. {mospagebreak title=Queries and query results} Example 7: Adding the functions query(), next_record() and seek() to DB_Sql.


function query($Query_String) { $this->connect(); # printf("Debug: query = %s<br>n", $Query_String); $this->Query_ID = mysql_query($Query_String,$this->Link_ID); $this->Row = 0; $this->Errno = mysql_errno(); $this->Error = mysql_error(); if (!$this->Query_ID) { $this->halt("Invalid SQL: ".$Query_String); } return $this->Query_ID; } function next_record() { $this->Record = mysql_fetch_array($this->Query_ID); $this->Row += 1; $this->Errno = mysql_errno(); $this->Error = mysql_error(); $stat = is_array($this->Record); if (!$stat) { mysql_free_result($this->Query_ID); $this->Query_ID = 0; } return $stat; } function seek($pos) { $status = mysql_data_seek($this->Query_ID, $pos); if ($status) $this->Row = $pos; return; }

Example 7 adds three functions to our DB_Sql class which make the class actually useful: Finally we are able to make use of the database link for sending queries to the database and retrieving the results. For this purpose, query() calls connect() internally to create the database link. This saves you a manual call to connect if you are using the database class later in your pages.

If you activate the disabled printf() statement within query(), you get a list of all queries on a page as they are made on the page. This is very useful for debugging your SQL and to get a feeling how expensive the creation of a certain page actually is.

When you send a query, a new $Query_ID is being generated and the current row number is reset to zero. After that we check the error state to see if the query was legal. If not, we raise an error and halt the program. If the query was legal, we return the query id to the caller.

The next_record() function can be used to retrieve the query result. The function reads the current result row, increments the row counter and checks for errors. If the result set has been read completely, we call mysql_free_result() to save application memory. next_record() returns "true" as long as there are still result records so that you may use the function as the condition of a while()-loop.

Using seek() you may move within the current result set and read a single result multiple times (unless it has been freed) or skip certain records at the beginning of the result set. Example 8 shows how to use query() and next_record() to get data from a table. Example 8: Query to the table ad_customers within the database sampleserv.


<?php require("db_mysql.inc"); // DB_Sql require("local.inc"); // DB_Sample $db = new DB_Sample; $query = "select name, graphics, link, desc from ad_customers"; $db->query($query); ?> <html> <body bgcolor="#ffffff"> <table border=1 bgcolor="#eeeeee"> <tr> <th>ID</th> <th>Graphics</th> <th>Link</th> <th>Desc</th> </tr> <?php while($db->next_record()): ?> <tr> <td><?php print $db->Record["name"] ?></td> <td><?php print $db->Record["graphics"] ?></td> <td><?php print $db->Record["link"] ?></td> <td><?php print $db->Record["desc"] ?></td> </tr> <?php endwhile ?> </table> </body> </html>

Example 8b: Definition of table ad_customers.


CREATE TABLE ad_customers ( id int(11) DEFAULT '0' NOT NULL auto_increment, name varchar(127) DEFAULT '' NOT NULL, graphics varchar(127) DEFAULT '' NOT NULL, link varchar(127) DEFAULT '' NOT NULL, desc varchar(127) DEFAULT '' NOT NULL, PRIMARY KEY (id), KEY name (name), ); CREATE TABLE banner_rotate ( pos int(11) DEFAULT '0' NOT NULL, );

Many webservers keep rotating banner ads at the top or bottom of their pages. These banners are present as GIF images with known path names. In our sample database we keep a table named ad_customers, which lists information about each banner. We keep a banner name, the pathname to the GIF image on disk, a link target that is to be activated when the banner is clicked and a description text for the images alt-attribute.

Example 8 shows, how to read this table using the DB_Sample class. We are generating an HTML table with all banner names and related data. Example 8b shows the database table definitions involved. The second table, banner_rotate, contains just a single row with a single column with the currently active ad banner number. The rotation program uses this information to control the banner rotation.

The actual banner rotation program (Example 9) is just a single function banner_rotate(), which does nothing more than incrementing the pos counter from the banner_rotate table and produces the appropriate image tag. The locking shown in that function is specific to MySQL (MySQL does not do proper transactions).

The function is pretty linear: It locks the banner_rotate table and updates the counter using an SQL update statement. After that it uses a SQL select statement to read that counter value and unlocks the table. Using the counter value corrected modulo the number of actual ad customers the appropriate customer data from the ad_customers table is selected and an image tag is created which is embedded into a link. We do not directly jump into the customers presentation using this link, but we refer the user to another local program which registers the click and additional data about the users browser. It is that second program which generates a Location header to redirect the user to the final external destination. This is the only way to measure the efficiency of a banner and to get provable data for the customer. Example 9: Function banner_rotate() to rotate banner ads.


<?php function banner_rotate() { global $db; // Assumes that a global object with that name exists. $max_ads = 4; // CONFIGURE ME! $db->query("lock tables banner_rotate"); // Set lock. $db->query("update banner_rotate set pos = pos + 1"); // Increment counter. $db->query("select pos from banner_rotate"); // Read counter. $db->next_record(); $pos = $db->Record["pos"]; $db->query("unlock tables"); // Drop lock. // Find matching customer (mod $max_ads). $query = sprintf("select * from ad_customers where id = '%s'", $pos % $max_ads); $db->query($query); $db->next_record(); // Link and Image generation printf("<a href="jump.php3?name=%s"> <img src="%s" alt="%s" width=468 height=60 border=0></a>", $this->Record["name"], $this->Record["graphics"], $this->Record["desc"]); } ?>

The jump.php3 script is not shown. It receives a parameter name identifying the clicked banner. Using that parameter the script can extract the link information from ad_customers and create a Location header to redirect the users browser to the final location. Also, it does record the click in another table named banner. Example 10: More functions for DB_Sql


<?php function num_rows() { return mysql_num_rows($this->Query_ID); } function num_fields() { return mysql_num_fields($this->Query_ID); } function f($Name) { return $this->Record[$Name]; } function p($Name) { print $this->Record[$Name]; } function affected_rows() { return @mysql_affected_rows($this->Link_ID); } ?>

To complete DB_Sql, we add the functions shown in Example 10. These are intended to ease access to query results: num_rows() and num_fields() return the width and height of the result set. The functions f() and p() are useful to access single result set values. And affected_rows() can be used to test the success of SQL insert or update statments.

The class DB_Sql is a basic building part of PHPLIB The version of DB_Sql from PHPLIB contains some additional functions which are not relevant for this tutorial.



 
 
>>> More PHP Articles          >>> More By Kristian Kohntopp
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: