PDA

View Full Version : A walk in the garden part 1.



kgun
08-13-2009, 10:10 AM
Ok let us start.

After a lot of frustration (http://www.sitepoint.com/forums/showthread.php?t=632038), I finally made up my mind to start this walk in the garden part 1 ... n threads.

The frustration is about database connection.

1. The problem

We have a lot of database platforms from the popular MySQL platform to the advanced Oracle enterprise database platform. And if you use the simple MySQL platform, there are more than one way to connect to the database. Here are 4 different ways to do it in PHP.


PHP: mysql_connect - Manual (http://www.php.net/manual/en/function.mysql-connect.php)
MySQLi (PHP MySQL improved) (http://www.php.net/manual/en/mysqli.connect.php)
PHP: PDO - Manual (http://www.php.net/pdo)
External libraries like pear DB_DataObject (http://pear.php.net/package/DB_DataObject/) and pear MDB2 (http://pear.php.net/package/MDB2)

2. The end result of this first thread.


Make a general MySQL database connection class
(that may be extended to other database platforms like PostgreSQL (http://www.postgresql.org/) and ... time will show)


3. Related links

A soft introduction to object oriented programming (http://www.webproworld.com/web-programming-discussion-forum/44914-soft-introduction-object-oriented-programming-2.html#post226176)

PHP 6 on the radar (http://www.webproworld.com/programming/88471-php-6-radar.html#post454371)

Building Object-Oriented Database Interfaces in PHP: Processing Data through Data Access Objects (http://www.devshed.com/c/a/PHP/Building-Object-Oriented-Database-Interfaces-in-PHP-Processing-Data-through-Data-Access-Objects/)

4. The first walk.

Here is the first walk without further comments, since the code is fairly well documented. Fine if you test the code and find any errors / bugs. I have found none so long.

File: DbConnect.php



<?php
/**
* PHP MySQL Database Connection Class
* @access public
*/
class DbConnect {
/**
* MySQL server hostname
* @access private
* @var string
*/
private $host;

/**
* MySQL username
* @access private
* @var string
*/
private $dbUser;

/**
* MySQL user's password
* @access private
* @var string
*/
private $dbPass;

/**
* Name of database to use
* @access private
* @var string
*/
private $dbName;

/**
* MySQL Resource link identifier stored here
* @access private
* @var string
*/
private $dbConn;

/**
* Stores error messages for connection errors
* @access private
* @var string
*/
private $connectError;

/**
* MySQL constructor
* @param string host (MySQL server hostname)
* @param string dbUser (MySQL User Name)
* @param string dbPass (MySQL User Password)
* @param string dbName (Database to select)
* @access public
*/
public function __construct($host,$dbUser,$dbPass,$dbName) {
$this->host=$host;
$this->dbUser=$dbUser;
$this->dbPass=$dbPass;
$this->dbName=$dbName;
$this->connectToDb();
}

/**
* Establishes connection to DbConnect.MySQL and selects a database
* @return void
* @access private
*/
private function connectToDb () {
// Make connection to MySQL server
if (!$this->dbConn = @mysql_connect($this->host,
$this->dbUser,
$this->dbPass)) {
trigger_error('Could not connect to server');
$this->connectError=true;
// Select database
} else if ( !@mysql_select_db($this->dbName,$this->dbConn) ) {
trigger_error('Could not select database');
$this->connectError=true;
}
}

/**
* Checks for MySQL errors
* @return boolean
* @access public
*/
public function isError () {
if ( $this->connectError )
return true;
$error=mysql_error ($this->dbConn);
if ( empty ($error) )
return false;
else
return true;
}
}
?>
5. Use



require_once('DbConnect.php');
$host='***'; // Hostname of MySQL server
$dbUser='***'; // Username for MySQL
$dbPass='***'; // Password for user
$dbName='***'; // Database name
// Instantiate MySQL connection
$db=new DbConnect($host,$dbUser,$dbPass,$dbName);

6. The next walk or exercise for you.

Test for MySQL PHP functions and improve connection.

Hint:



if (function_exists('mysqli_connect')) {
Code here.
}
But remember, conditional code like the one above, is a clear indication of code duplication and since minimalism is an essential part of good OOP design, it is an indication of


An (abstract) base (parent) class that extends functionality through
inheritance.
Last but not least. Don't forget to program to an interface and not to an implementation.

So try to solve the above problem yourself before I present my solution. I can not promise when.

kgun
08-14-2009, 07:31 AM
But remember, conditional code like the one above, is a clear indication of code duplication and since minimalism is an essential part of good OOP design, it is an indication of


An (abstract) base (parent) class that extends functionality through
inheritance.
Last but not least. Don't forget to program to an interface and not to an implementation.

So try to solve the above problem yourself before I present my solution. I can not promise when.

This will hopefully make the above statements more clear. Inheritance is indicated by the extends keyword.

PHP example code for illustrative purposes that will not function:



<?php
/**
* NOTE: Dont try to run this code. It will not work, since it needs implementation etc.
*
* Object interfaces allow you to create code which specifies which methods
* a class must implement, without having to define how these methods are handled.
* Interfaces are pure templates.
* An interface can can only define functionality, but never implement it.
* All methods declared in an interface must be public, this is the nature of an interface.
* FYI, interfaces can define constructors, destructors, and magic methods.
* This can be very helpful especially in the case of constructors when instantiating an
* implementing class via reflection in some sort of factory. Of course, it is not
* recommended to do such a thing since it goes against the nature of a true interface.
* Interfaces support multiple inheritance
* Source: http://www.php.net/manual/en/language.oop5.interfaces.php
*/

interface ElectricalDevice{
public function power_on();
public function power_off();
}

interface FrequencyTuner{
public function get_frequencey();
public function set_frequency($f);
}

class ElectricFan implements ElectricalDevice{
// define ElectricalDevice...
}

class MicrowaveOven implements ElectricalDevice{
// define ElectricalDevice...
}

class StereoReceiver implements ElectricalDevice, FrequencyTuner{
// define ElectricalDevice...
// define FrequencyTuner...
}

class CellPhone implements ElectricalDevice, FrequencyTuner{
// define ElectricalDevice...
// define FrequencyTuner...
}

/**
* Abstract classes
* It is not allowed to create an instance of a class that has been defined as abstract.
* Any class that contains at least one abstract method must also be abstract.
* Methods defined as abstract simply declare the method's signature they cannot define the implementation.
* Source: http://www.php.net/manual/en/language.oop5.abstract.php
*/

abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function getValue();
abstract protected function prefixValue($prefix);

// Common method
public function printOut() {
print $this->getValue() . "\n";
}
}

class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}

public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}

class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}

public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";

// Subclassing and interfaces.
class Person {
// Properties for Person objects.
}

interface IStudent {
// ...
}

interface IEmployee {
// ...
}

class Student implements IStudent extends Person {
// ...
}

class StudentEmployee implements IStudent, IEmployee extends Person {
// ...
}
?>
Why is it useful to define an interface and implement it in a class? The answer lies in type. An implementing class takes on the type of the class it extends and the interface it implements. So to know an objects type is to know its capabilities. An interface joins types that are otherwise unrelated.

Links:


PHP: Object Interfaces - Manual (http://www.php.net/manual/en/language.oop5.interfaces.php)
PHP: Class Abstraction - Manual (http://www.php.net/manual/en/language.oop5.abstract.php)
PHP: Classes and Objects (PHP 5) - Manual (http://www.php.net/manual/en/language.oop5.php)

"Object return value problems are well known in php 5.*. PHP does not enforce a unified return value. There is no return class hinting, so there is nothing to prevent us from returning an error flag in stead of the promised object or primitive. When we do this, we have to rely on the client coder to test for the return type every time our error-prone method is called. This can be risky business. Trust no one".

Source: Matt Zandstra "PHP 5 Objects, Patterns, and Practice" (http://www.apress.com/book/view/1590593804) chapter 4.

Example:

PHP Object return value (http://stackoverflow.com/questions/991066/php-object-return-value)

As far as I know this problem will be solved in PHP 6 that also introduces the important concept of name spaces to avoid class collisions (in different libraries).

kgun
08-16-2009, 05:48 AM
For those of you that want to use the pear MDB2 database abstraction layer (http://pear.php.net/package/MDB2)

Install pear:



Manual :: Installation (PEAR) (http://pear.php.net/manual/en/installation.php) (Note it is possible to install a local PEAR copy on a shared host). There may be some information in these old posts if you need additional information:

- PEAR for Beginners // Archives // Addicted To New by John Nunemaker (http://addictedtonew.com/archives/36/pear-for-beginners/)

- Application Development: Install PEAR on a shared Web host (http://articles.techrepublic.com.com/5100-10878_11-5163311.html) (Be selective when you read, but the article has general information of value)

- http://forums.hostmysite.com/about6509.html (Skim the article)

- PEAR on Shared Host - Codewalkers (http://forums.codewalkers.com/pear-packages-47/pear-on-shared-host-4768.html) (Enough explanation for you?)
User Guide: Manual :: User Guide (http://pear.php.net/manual/en/users.php)
Getting started: Manual :: Getting started (http://pear.php.net/manual/hu/package.html.html-css.tutorial.php)
Package Information: MDB2:


MDB2 (http://pear.php.net/package/MDB2/download/All)
Search query: pear mdb2 tutorial
Additional information:

Scroll down to the pear section of the last site in my signature.

Note: You can manipulate .htaccess with File_HtAccess (http://pear.php.net/package/File_HtAccess)

I will not promise to write more regarding database connection etc. You should have enough information above.

Related WPW thread: http://www.webproworld.com/web-programming-discussion-forum/81410-php-powerful-tool-2.html#post428376

kgun
08-16-2009, 08:53 AM
I could not edit my last post. Here


Manual :: What is PEAR? (http://pear.php.net/manual/en/about.pear.php)
Accounts (http://pear.php.net/accounts.php)
An overview of pear packages (http://pear.php.net/packages.php)

is two important links. Note the following sections in the first document:


Structured Libraries and Applications of PHP Code

"Packages are distributed as gzipped tar files with a description file inside, and installed on your local system using the PEAR installer" (http://pear.php.net/package/PEAR).
Code Distribution and Package Maintenance
pears relation to The PHP Extension Community Library (PECL)

kgun
08-17-2009, 05:07 AM
Not a single comment or reaction to this important subject.


2. The end result of this first thread.


Make a general MySQL database connection class
(that may be extended to other database platforms like PostgreSQL (http://www.postgresql.org/) and ... time will show)


No need to reinvent the wheel. That task is already solved for you if you have a php version with the PDO extension. Look at the drivers page:

PHP: PDO Drivers - Manual (http://www.php.net/manual/en/pdo.drivers.php)

to find out which database drivers that are supported. If you have php 5.0, you can download the extension here: PECL :: The PHP Extension Community Library (http://www.pecl.php.net/)

Finally, if you decide to use pear, you may register on the pear forum and vote here:

PEAR Forum - Forum for PHP Extension and Application Repository (http://www.pear-forum.org/viewtopic.php?p=5171#5171)

It is a never ending poll, so hopefully the installation of pear, at least on a shared host will become more user friendly in the future.

Note:


Your hoster may not support Mysqli or PDO.
Later versions of php 5.+ are by default compiled with central pear packages. So unless compiled with the

-without-pear

configuration flag

you can use some packages directly.

Conclusion:


Use the method in post #1 - #2 if you want to make your own database solution or the other options are not available because you are on a shared host etc.
If you don't want to write SQL, use the pear class library and its database solution.
If you want a general php object oriented database solution that functions on many platforms, use PDO.
If you sign up with a new hosting company, ask about which database solutions are available. This has made me a lot of frustration since I use three different hosters with different versions of PHP installed. One hoster only supports PDO with MySQLITE. PHP MySQL PDO and MySQLi is not supported. But their PHP version 5.2.4 is fortunately compiled with pear that may be the best solution if you only need php and MySQL:

include_path :/usr/local/share/pear (local and master value)

kgun
08-18-2009, 05:13 AM
More on installing pear on a shared host: Installing pear on a shared host. - SitePoint Forums (http://www.sitepoint.com/forums/showthread.php?t=632919)

Note The following two important cites from Matt Zandstra:

"PHP 5 Objects, Patterns, and Practice (http://www.apress.com/book/view/1590593804)" chapter 14. "An introduction to pear."

Page 310 in my version:

"The DB package is worth mastering. It provides a platform-agnostic interface to multiple databases. The idea is that you write code to work with the DB API, and it handles the database specific syntax.

..............

This is an excellent example of good object-oriented design - an abstract class DB_COMMON defines an interface that supports the operations we have illustrated (in particular query() and nextIndex()), and a set of children provide the implementation. In this way your application is ready to work with MySQL, SQLite, MSSQL or Oracle with no change in your code (as long as you use standard SQL syntax).
"
So it is worth learning pear for many different reason.