-
Another year has passed and PHP 6 is still not here…
But that’s not exactly news, is the 4-th year when this long awaited version is not released. Not for nothing is called the most awaited version.
But overall it was a good year for the community, even though we still don’t have native Unicode in a stable version now we have all other awaited features in PHP 5.3, which will probably need another few years to become used on a large scale.
Even though everyone was expecting last year for Oracle to enter in full force on medium and small database market by purchasing Sun, enlarging it’s already well established portfolio on the enterprise market. It seems that it was not to be, CE is still analyzing the deal.
However MySQL is not what it used to be 5-6 years ago, when nobody dared to use it for enterprise products. This days MySQL is a product ready to be used in both small and large products that require a lot of scalability.
But back to the year that just ended, it was a full year, even with this economic crises.
-
CodeIgniter is an open-source PHP framework, build for RAD development. This framework is continuously growing in popularity, probably especially since people realized that is much easier to use an open-source framework instead of developing an internal one, but that’s another story. The CodeIgniter 1.7 book from PacktPublishing, written by Jose Argudo Blanco and David Upton is building a big picture about the CodeIgniter 1.7 framework, as an addition to the reference manual.
After all every respectable framework has an detailed reference, with usability examples, more or less comprehensible. When it comes to learning an framework (and not only), an reference is usually not the best place to start from, because is hard to get the big picture when you can only receive atomic answers. That’s why we buy books this days, to have a general image with problems and solutions. And this is where the CodeIgniter 1.7 book comes in.
Initially, when I’ve seen that the title has the version number of the analyzed framework I was a little pessimistic, because usually when you buy a book you don’t want it to be tight up to particular version, isn’t it? Well, not exactly… I had a similar issue with Zend Framework, most books use “older versions” (ex: 1.5-1.6) and I wanted to see an approach using the new features from version 1.8 or greater. After all when you start learning something you usually want the latest version of the framework or what ever it is that you are learning, and when new features appear it will be much easier to simply look then in the reference guide since you already know the basics.
This book seams to start from the beginners level and progressively describe both basic elements as well as the most common problems the user may encounter when developing apps using the CodeIgniter framework. The sample chapter, looks pretty well structured and easy to understand, and from the table of contents it seams to approach all the important subjects. With the hope that the rest of the book will be just as well structured (I’m actually judging a book by the cover?) and a second part to this review will follow I can’t barely wait for the book.
To be continued…
-
Last week I was supposed to create a little project. Requirements were short: interoperability.Given the fact that I’ve never used Adobe AIR before, I thought it was a good opportunity to try it.
The result was a small project management app. For the server-size I’ve used PHP + SOAP + Zend Framework, and for the client I’ve used Adobe AIR with JavaScript.
I’ve created the server in a few lines:
1<?php 2// autoload class for Zend Framework 3include 'Zend/Loader/Autoloader.php'; 4 5// class that deals with SOAP requests 6include 'SOAP.class.php'; 7 8// initialize autloader 9Zend_Loader_Autoloader::getInstance(); 10 11// if it's a request for the WSDL descriptor file 12if(isset($_GET['wsdl'])) { 13 $autodiscover = new Zend_Soap_AutoDiscover(); 14 $autodiscover->setClass('test'); 15 $autodiscover->handle(); 16// if it's a SOAP request 17} else { 18 $soap = new Zend_Soap_Server("http://localhost/soap/index.php?wsdl"); 19 $soap->setClass('test'); 20 $soap->handle(); 21} 22 23?>
The descriptor is build automatically using PHP Documenter type comments from the class that handles SOAP requests, if this case it’s named “test”.
This was the easy part so I’ve moved on to the Adobe AIR client following this simple steps:
- Download and install Aptana Studio
- Install Adobe AIR plug-in
- New project -> Adobe AIR
- and voila! Coding can begin!
Adobe AIR is using for a JavaScript engine Webkit. Sounds familiar? Webkit is used by Safari and Google Chrome. So the JavaScript code should only be compatible with Webkit!
Of course there is a “but” and a plus. The “but” is that there are some restrictions, for instance “eval” can only be used to decode JSON, and the text introduced directly in an element (as text) can not be executed:
1div.innerHTML = "<a onclick=\"alert('ceva')\" href=\"#\">click</a>";
This link will get to the element by will not run anything on “onclick” because the parameter was send as text.
This was a pretty big disadvantage for me, but I’ve managed to figure out an alternative by building HTML elements using DOM and adding events using addEventListener.
Briefly Adobe AIR is using this formula:
1Adobe AIR = (Webkit)Web Development - security + air framework.
It seems very easy for a Web Developer to develop desktop apps with Adobe AIR.
Of course is not very fast and it’s not looking like a good idea for complex apps. But if your thinking about medium and small apps, if I had to choose between Adobe AIR and PHP GTK for instance, the first option seems a lot more viable and easy to use!
In the end the project was ready in less then 3 days and the graphics were gorgeous! It didn’t even look like it was build using only HTML and JavaScript!
-
Probably the most popular pattern form PHP and not only.
Motivation:
Restriction to a single instance of a resource across the app, accessible from anywhere.
Diagram:
Implementation:
The classic example for PHP is the database resource. The database connection must be unique across the app, not to establish multiple connections to the database and as a consequence resources to be wasted.
For a single instance to exist the constructor must only be accessible from a static method, and the resulting object must not have the posibillity to be cloned. Also the class must not be extensible.
Example:
1// db connection information 2define ( 'DB_HOST', 'localhost' ); 3define ( 'DB_USER', 'user' ); 4define ( 'DB_PASS', 'pass' ); 5define ( 'DB_DATABASE', 'db' ); 6 7/** 8 * Singleton class for database connection management using mysqli 9 */ 10final class SingletonDB { 11 12 /** 13 * Singleton instance 14 * 15 * @var SingletonDB 16 */ 17 protected static $_instance = null; 18 19 /** 20 * Connection resource 21 * 22 * @var resource 23 */ 24 protected $_connection = null; 25 26 /** 27 * Constructor which also connects to the database 28 * 29 */ 30 protected function __construct() { 31 // connection to database server 32 $this->_connection = new mysqli ( DB_HOST, DB_USER, DB_PASS ); 33 34 // in case of an error connection an exception is thrown 35 if ($this->_connection->connect_error) { 36 throw new Exception ( 'Error connection to mysql server' ); 37 } 38 39 // selecting the database 40 $this->_connection->select_db ( DB_DATABASE ); 41 42 // in case of an error selecting the database an exception is thrown 43 if ($this->_connection->error) { 44 throw new Exception ( 'Error selecting database' ); 45 } 46 47 } 48 49 /** 50 * Run SQL queries 51 * 52 * @param string $query SQL query 53 * @return mysqli_result 54 */ 55 public function query($query) { 56 return $this->_connection->query ( $query ); 57 } 58 59 /** 60 * Access for error messages 61 * 62 * @return string 63 */ 64 public function error() { 65 return $this->_connection->error; 66 } 67 68 /** 69 * Method that is called when cloning an object 70 * Is protected so is not possible to clone the object 71 * 72 */ 73 protected function __clone() { 74 } 75 76 /** 77 * Close connection and destroy the object 78 * 79 */ 80 public function __destruct() { 81 $this->_connection->close (); 82 } 83 84 /** 85 * Method that returns an SingletonDB instance 86 * 87 * @return SingletonDB 88 */ 89 public static function getInstance() { 90 if (self::$_instance == null) { 91 self::$_instance = new SingletonDB ( ); 92 } 93 94 return self::$_instance; 95 } 96} 97 98try { 99 // SingletonDB instance 100 $db = SingletonDB::getInstance (); 101 102 // Query to be run 103 $q = 'SELECT * FROM test'; 104 105 // the query will return an mysqli_result object 106 $result = $db->query ( $q ); 107 108 // check for errors and display them 109 if ($db->error ()) { 110 111 echo $db->error (); 112 113 } else { 114 // extract the result and display 115 while ( $row = $result->fetch_assoc () ) { 116 var_dump ( $row ); 117 } 118 // close mysqli_result object 119 $result->close (); 120 } 121// in case of exception there is displayed 122} catch ( Exception $e ) { 123 echo $e->getMessage (); 124}
-
Iterator patter is probably the most popular pattern from SPL. Is a very simple way to demonstrate the advantages of an interface and SPL.
Motivation:
The possibility of iterating object type structures, using functions like foreach(), var_dump(), print_r() etc.Diagram:
Iterator structure:
In SPL there are a lot of interfaces and classes for iteration.
Iterator interface base structure:
1/** 2 * Iterator interface from SPL 3 */ 4Iterator extends Traversable { 5 /** 6 * Returns the current element 7 */ 8 abstract public mixed current ( void ) 9 10 /** 11 * Returns the key of the current element 12 */ 13 abstract public scalar key ( void ) 14 15 /** 16 * Moves to the next element in the array 17 */ 18 abstract public void next ( void ) 19 20 /** 21 * Reset the iteration to the initial position 22 */ 23 abstract public void rewind ( void ) 24 25 /** 26 * Check to see if the current position is valid 27 */ 28 abstract public boolean valid ( void ) 29}
Example 1:
A simple iterator object.
1/** 2 * The class for the iterator object 3 */ 4class Iterabil implements Iterator { 5 6 /** 7 * The index for the iterated element 8 */ 9 private $_current = 0; 10 11 /** 12 * Array with elements to iterate 13 */ 14 private $_elements = array(); 15 16 /** 17 * Constructor 18 * 19 * @param array $elements Elements to iterate 20 */ 21 public function __construct($elements) { 22 $this->_elements = $elements; 23 } 24 25 /** 26 * Current element 27 * 28 * @return mixed Current element 29 */ 30 public function current() { 31 return $this->_elements[$this->_current]; 32 } 33 34 /** 35 * Current index 36 * 37 * @return integer Current index 38 */ 39 public function key() { 40 return $this->_current; 41 } 42 43 /** 44 * Move to the next index 45 */ 46 public function next() { 47 $this->_current++; 48 } 49 50 /** 51 * Reset index 52 */ 53 public function rewind() { 54 $this->_current = 0; 55 } 56 57 /** 58 * Check if the current element is set 59 * 60 * @return boolean If the current element is set 61 */ 62 public function valid() { 63 return isset($this->_elements[$this->_current]); 64 } 65} 66 67// class instance 68$obj = new Iterabil(array(1, 2, 3, 4, 5)); 69 70// iterate object 71foreach ($obj as $value) { 72 echo $value.PHP_EOL; 73} 74 75// output: 76// 1 77// 2 78// 3 79// 4 80// 5
Example 2:
Another example a little more complex, a class that allows to iterate through the public properties of a class which extends it. Iterator and Reflection are used.
1/** 2 * Class which iterates through the public properties of a class which extends it 3 */ 4class Iterabil implements Iterator { 5 6 /** 7 * The index for the iterated element 8 */ 9 private $_current = 0; 10 11 /** 12 * Array with elements to iterate 13 */ 14 private $_elements = array(); 15 16 /** 17 * Current element 18 * 19 * @return mixed Current element 20 */ 21 public function current() { 22 return $this->_elements[$this->_current]->name; 23 } 24 25 /** 26 * Current index 27 * 28 * @return integer Current index 29 */ 30 public function key() { 31 return $this->_current; 32 } 33 34 /** 35 * Move to next index 36 */ 37 public function next() { 38 $this->_current++; 39 } 40 41 /** 42 * Reset index and get the properties 43 */ 44 public function rewind() { 45 // rewind is the first to be called 46 // here the properties list should be obtained 47 // ReflectionClass is initialized 48 // with the current class name as a parameter 49 $reflection = new ReflectionClass(get_class($this)); 50 51 // we get the public properties 52 $this->_elements = $reflection->getProperties(ReflectionMethod::IS_PUBLIC); 53 54 // set the current index 55 $this->_current = 0; 56 } 57 58 /** 59 * Check if the current element is set 60 * 61 * @return boolean If the current element is set 62 */ 63 public function valid() { 64 return isset($this->_elements[$this->_current]); 65 } 66} 67 68/** 69 * A new class with public properties 70 * 71 */ 72class Testing extends Iterabil { 73 public $proprietate1; 74 public $proprietate2; 75} 76 77// class instance 78$obj = new Testing(); 79 80// iterate object 81foreach ($obj as $value) { 82 echo $value.PHP_EOL; 83} 84 85// output: 86// proprietate1 87// proprietate2
And if you what the above example to be accessible as an array you just have to implement ArrayAccess from SPL.
ArrayAccess structure:
1ArrayAccess { 2 /** 3 * Check if the offset exists 4 */ 5 abstract public boolean offsetExists ( string $offset ); 6 7 /** 8 * Returns the element of an offset or NULL if it does not exist 9 */ 10 abstract public mixed offsetGet ( string $offset ); 11 12 /** 13 * Set a value for an offset 14 */ 15 abstract public void offsetSet ( string $offset , string $value ); 16 17 /** 18 * Unset a value for an offset 19 */ 20 abstract public void offsetUnset ( string $offset ) 21}
Example 3:
An even more complicated example which shows the power of interfaces from SPL. Iterator object accessible like an array.
To simplify the array access logic I’ve used the php native functions for iterating an array (next(), reset()).
1/** 2 * The class for the iterator object 3 */ 4class Iterabil implements Iterator, ArrayAccess, Countable { 5 6 /** 7 * Array with elements to iterate 8 */ 9 private $_elements = array(); 10 11 /** 12 * Constructor 13 * 14 * @param array $elements Elementele de iterat 15 */ 16 public function __construct($elements) { 17 $this->_elements = $elements; 18 } 19 20 /** 21 * Current element 22 * 23 * @return mixed Current element 24 */ 25 public function current() { 26 return current($this->_elements); 27 } 28 29 /** 30 * Current index 31 * 32 * @return integer Current index 33 */ 34 public function key() { 35 return key($this->_elements); 36 } 37 38 /** 39 * Move to the next index 40 */ 41 public function next() { 42 next($this->_elements); 43 } 44 45 /** 46 * Reset index 47 */ 48 public function rewind() { 49 reset($this->_elements); 50 } 51 52 /** 53 * Check if the current element is set 54 * 55 * @return boolean If the current element is set 56 */ 57 public function valid() { 58 return current($this->_elements)?true:false; 59 } 60 /** 61 * Check if the offset exists 62 * 63 * @param string $offset Element key 64 * @return boolean If the element is set 65 */ 66 public function offsetExists($offset) { 67 return isset($this->_elements[$offset]); 68 } 69 70 /** 71 * Returns the element of an offset or NULL if it does not exist 72 * 73 * @param string $offset Array offset 74 * @return mixed Element or NULL 75 */ 76 public function offsetGet($offset) { 77 return $this->_elements[$offset]; 78 } 79 80 /** 81 * Set a value for an offset 82 * 83 * @param string $offset Element offset 84 * @param mixed $value Value of the element in the array 85 */ 86 public function offsetSet($offset, $value) { 87 $this->_elements[$offset] = $value; 88 } 89 90 /** 91 * Unset a value for an offset 92 * 93 * @param string $offset Element offset 94 */ 95 public function offsetUnset($offset) { 96 unset($this->_elements[$offset]); 97 } 98 99 /** 100 * Number of elements in the array 101 * 102 * @return integer Number of elements in array 103 */ 104 public function count() { 105 return count($this->_elements); 106 } 107} 108 109// Class instance 110$obj = new Iterabil(array(1, 2, 3, 4, 5)); 111 112echo 'Iteration using "for":'.PHP_EOL; 113 114// iterate the object like a simple array 115for($i = 0; $i < count($obj); $i++) { 116 echo $obj[$i].PHP_EOL; 117} 118 119echo 'Element to delete: '.$obj[1].PHP_EOL; 120 121unset($obj[1]); 122 123echo 'Iteration using "foreach":'.PHP_EOL; 124 125// iterate the object using foreach 126foreach ($obj as $element) { 127 echo $element.PHP_EOL; 128} 129 130// Output: 131//Iteration using "for": 132//1 133//2 134//3 135//4 136//5 137//Element to delete: 2 138//Iteration using "foreach": 139//1 140//3 141//4 142//5