The same old nightmare: objects being passed by value by default. You forget to put a sad ampersand (&) when assigning and you spend hours figuring out why the state of your instance has been lost.
It's been almost a year since PHP 5 was released last July. At first I was quite skeptical. I thought object orientation was something for Java purists (in fact, I already talked about how Java 1.4 added interesting little things), and that PHP should remain that fast language for making procedural scripts. But today I finally gathered the courage, downloaded version 5.0.4 and configured the module in my local Apache to tinker around a bit.
The leap the language has taken with the new Zend Engine II is abysmal.
The end of spaghetti code and the cursed ampersand
If you've written code in PHP 4, you know that object-oriented programming (OOP) was a duct-taped add-on. Classes were basically glorified associative arrays. Everything was public. If you wanted a property to be "private", you called it $_variable crossing your fingers that no one would modify it from the outside.
With PHP 5, OOP is really starting to mature. The wildest change, and the one that relieves me the most, is that now objects are passed by reference by default. No more accidental copies of entire objects in memory. Also, we finally have a real visibility model with public, private and protected.
The way to initiate and destroy objects has also been standardized with __construct and __destruct, leaving behind the habit of naming the constructor the same as the class. And the best part: they've added native exceptions with try/catch. Goodbye to cluttering the code with checks like if (!$resultado) { return false; }.
A practical example with mysqli
To put this into something useful, I started rewriting a small class to manage the data of my forums. In addition to the new object model, PHP 5 brings the mysqli (MySQL Improved) extension, which allows interacting with the database directly using objects instead of the classic mysql_connect.
Look how the code looks now. It's much cleaner and more robust:
<?php
class GestorForo {
private $db;
public function __construct() {
// The new marvel: object-oriented mysqli
$this->db = new mysqli('localhost', 'root', '1234', 'mi_proyecto');
if (mysqli_connect_error()) {
throw new Exception("MySQL connection error: " . mysqli_connect_error());
}
}
public function obtenerFirma($usuario_id) {
$id_seguro = (int)$usuario_id;
// Direct queries without cluttering the global code
$resultado = $this->db->query("SELECT firma FROM usuarios WHERE id = $id_seguro");
if (!$resultado) {
throw new Exception("SQL query failed");
}
$fila = $resultado->fetch_assoc();
$resultado->close();
return $fila['firma'];
}
public function __destruct() {
// We clean up the connection when destroying the object
$this->db->close();
}
}
// Testing the invention with real error handling
try {
$gestor = new GestorForo();
echo "<p>User signature: " . $gestor->obtenerFirma(1337) . "</p>";
} catch (Exception $e) {
die("Things got messy: " . $e->getMessage());
}
?>
In this simple block, I define my private variables so the connection is not exposed, I throw an exception if the connection or the query fails, and automatically, the destructor closes the MySQL session when the script finishes its execution. It's brilliant.
What awaits us
Seeing this code working on the first try gives me quite a bit of hope. Until now, doing anything moderately complex in PHP required a lot of discipline to avoid ending up with a procedural mess. With this new foundation, the language seems ready to support much larger and more serious projects.
The only real problem I see in the short term is adoption. Most of the cheap shared hostings I use are still anchored in PHP 4.3. It will take quite a while before we can freely deploy this code in production without having to pay for a very expensive dedicated server.
But the path is laid out and the future looks very bright for those of us who like coding websites. Now I'm going to bed, because the coffee isn't working anymore.