Persistable Classes - By PHP Expert


The following code snippet implements the above-mentioned persistable class in less than 50 lines of PHP code by using property overloading. The term persistable means that the class can represent an element from a data structure while keeping it synchronized with an underlying storage system. This rather scientific explanation means in practice that other code can use the class to select a row from a database table. Directly accessing the class properties during runtime manipulates the elements of this row (by both reading and writing). When the script ends, PHP will take care of writing the updated row data back to the database.

Look through the code now to get a first impression of what is happening. After the code is a walk-through of the relevant parts of the code. At the end, you\'ll have a solid understanding of property overloading.

<?php
// Load the PEAR DB package
require_once "DB.php";

class Persistable {

private $data = array();
private $table = "users";

public function __construct($user) {
$this->dbh = DB::Connect("mysql://user:password@localhost/database");

$query = "SELECT id, name, email, country FROM " .
$this->table . " WHERE name = ?";
$this->data = $this->dbh->getRow($query, array($user),
DB_FETCHMODE_ASSOC);
}

public function __get($member) {
if (isset($this->data[$member])) {
return $this->data[$member];
}
}

public function __set($member, $value) {
// The ID of the dataset is read-only
if ($member == "id") {
return;
}

if (isset($this->data[$member])) {
$this->data[$member] = $value;
}
}

public function __destruct() {
$query = "UPDATE " . $this->table . " SET name = ?,
email = ?, country = ? WHERE id = ?";
$this->dbh->query($query, $this->name, $this->email,
$this->country, $this->id);
}
}

$class = new Persistable("Martin Jansen");

$class->name = "John Doe";
$class->country = "United States";
$class->email = "john@example.com";
?>

The first item that you may have stumbled across is the method __construct(). This is the new constructor method in PHP 5. In the good old days of PHP 4, constructor names matched their classes. That changed with PHP 5. You don\'t need to know much about the constructor method except that it is called to create an instance of the class; that it takes one argument here; and that it executes a database query based on this argument. The constructor assigns the return value of this query to the class property $data.

Next, the code defines two special methods called __get() and __set(). They are already familiar to you from the introduction: __get() is called when reading the value of an undefined property, and __set() is called when changing the same property\'s value.

This means that whenever someone reads or writes an undefined property from the persistable class, the special methods manipulate the information in the $data property array instead of changing the class properties directly. (Remember: $data contains the row from the database!)

The last class method is the counterpart of __construct(). It is the destructor method __destruct(). PHP calls destructors during the "script shutdown phase," which is typically right before the execution of the PHP script finishes. The destructor writes the information from the $data property back into the database. This is what the term synchronization (see above) stands for.

You have surely noticed that the above code uses PEAR\'s database abstraction layer package. This is solely syntactic sugar--the script of course works the same when using other ways to speak to the database.

If you look closely, you\'ll notice that the persistable class is limited in its current form. It works only with exactly one database table and thus does not allow the use of more complex data models that employ LEFT JOINs or other fancy database features. The sky\'s the limit, though; using property overloading in no way limits the flexibility of the database model. With just a bit more code, you can easily use sophisticated features of the database inside the persistable class.

Another little issue is the fact that there is virtually no error handling when the query in the destructor fails. It is in the nature of destructors that it often turns out to be impossible to display an error message in this case, because constructing the HTML markup has usually finished before PHP calls the destructor.

In order to solve this problem, you might rename __destruct() to something such as saveData() and execute the method manually somewhere in the calling script. This doesn\'t change anything in the concept of persistable classes; it just requires a bit more typing when writing code that uses the class. Alternatively, you can use the error_log() function in the destructor to log the message that belongs to the error in the systemwide error log file.
That\'s all the code necessary for the use case of property overloading. Next up is method overloading.

No comments

Enter your email address:

Delivered by FeedBurner

OR

 Subscribe in a reader

 
jQuery UI provides a comprehen
 
Program Plan   I drafted a p
 
I present to you my skills, ac
 
Introduction One of the issue
 
If you are a PHP developer and
 
cURL is a great tool to help y
 
cformsII cforms is a powerful
 
  The lack of Unicode su
 
History PHP-GTK was origina
 
Performance on the web is stra
 
Listen t
 
What\'s the number one cost in
 
When you\'re discussing the In
 
Classe
 
A service-oriented architectur
 
Introduc
 
PHP Crons and Linux Linux has
 
Cross site scripting (XSS) is
 
What Makes a Web 2.0 Applicati
 
As you develop web application
 
Cryptogr
 
Posting
 
Have you
 
Resources The Google API - ht
 
Get Started
 
Output B
 
If you r
 
PHP has some really sweet new
 
There were some new php.ini di
 
In PHP 5 there are some new fu
 
The following code implements
 
The following code snippet imp
 
A fine implementation of the o
 
Exception handling PHP 5 adds
 
Support for dereferencing obje
 
Static members Classes defini
 
Explicit object cloning In or
 
final methods The final keywo
 
Interfaces Gives the ability
 
The new object oriented featur
 
Sometimes its the little thing
 
Consider your file is at locat
 
# If a method can be static, d