Do you OOP?

 

Recently I was asked to provide some sample code to demonstrate my knowledge of PHP OOP design.

After some thinking about what I wanted to create, I decided that I would try to write a set of classes that would be related, and could be the groundwork for something bigger (providing you are a busy building contractor, know how to write PHP, and have time to write another 10,000 lines of code :-)

I also wanted to pack in as many OOP language constructs and a couple of commonly used design patterns in, and in as close to 100 lines as I could. Here is that code, and feel free to send me your comments via the contact page.

Demo Code

<?php
/**
 * Set of related classes to demonstrate some commonly used PHP OOP constructs.
 * @author Blain Redwood
 * @copyright (c) 2014, Blain Redwood, www.pear-trade.com
*/

if (version_compare(PHP_VERSION, '5.4.0') < 0) {
    die('This PHP demo uses Traits and requires PHP version 5.4 or higher.');
}

abstract class cost {	
	
	abstract public function analyse();	/* must be declared in parent */
	final public function quote() { /* add some code here */ }
}

interface purchase {	

	public function send_purchase_order(); /* must be decalred in parent using implement */
	public function buy_materials(); /* must be decalred in parent using implement */
}

trait build {
	
	public function prepare_foundations() { /* add some code here */ }		
	public function inspect() { /* add some code here */ }	
}

class contractor extends cost implements purchase {
	use build;
	static private $contractor_objects = array();
	public $contractor_id = null;
	public $uuid = null;
		
	public function __construct($contractor_id) {
		$this->contractor_id = $contractor_id;
		$this->uuid = uniqid();
	}
	
	/**
	 * Example of Singleton Pattern, primarily used to restrict the access of a particular class to one instance.
	 * In this example, I am restricting it to one instance of any one contractor
	 */
	static public function &fetchContractor($contractor_id) {	
		
		if (false === key_exists($contractor_id, self::$contractor_objects)) {	
			self::$contractor_objects[$contractor_id] = new contractor($contractor_id);
		}
		return self::$contractor_objects[$contractor_id];
	}
	
	public function analyse() { /* add some code here */ }
	
	public function send_purchase_order() { /* add some code here */ }
	
	public function buy_materials() { /* add some code here */ }	
	
	public function invoice() { /* add some code here */ }
	
	private function update_books() { /* add some code here */ }
	
	public function __toString() {	
		return print_r(array('contractor_id' => $this->contractor_id,
					 'uuid' => $this->uuid,
					 'methods' => get_class_methods($this)), true);		
	}	
	
	public function __destruct() {	
		$this->update_books();
	}
}

/**
 * Factory Pattern class, responsible for setting up an object above and 
 * beyond what a constructor would normally be responsible for.
 */
class contractor_factory {
	
	public static function &getContractorById($contractor_id) {
		if (!empty($contractor_id)) {
			$contractor =& contractor::fetchContractor($contractor_id);
			/* 
			 * Being a factory class, you would normally setup any additional settings here, this is however
			 * a demo which demonstrate both factory and singleton, so you would have to their interaction, or separate them.
			 */
			return $contractor;
		}
	}
}

$building_contractor_q =& contractor_factory::getContractorById($contractor_id = '001'); // returns a new instance
echo '<pre>' . $building_contractor_q;

$building_contractor_q->analyse();
$building_contractor_q->quote();
$building_contractor_q->send_purchase_order();
$building_contractor_q->buy_materials();
$building_contractor_q->prepare_foundations();
$building_contractor_q->inspect();
$building_contractor_q->invoice();

$building_contractor_x =& contractor_factory::getContractorById($contractor_id = '001'); // returns the same instance and uuid as above
echo '<br />' . $building_contractor_x;

$building_contractor_x =& contractor_factory::getContractorById($contractor_id = '002'); // returns a new instance
echo '<br />' . $building_contractor_x;

Output (on my machine)

Array
(
[contractor_id] => 001
[uuid] => 53793ccbbad39
[methods] => Array
(
[0] => __construct
[1] => fetchContractor
[2] => analyse
[3] => send_purchase_order
[4] => buy_materials
[5] => invoice
[6] => update_books
[7] => __toString
[8] => __destruct
[9] => quote
[10] => prepare_foundations
[11] => inspect
)
)
Array
(
[contractor_id] => 001
[uuid] => 53793ccbbad39
[methods] => Array
(
[0] => __construct
[1] => fetchContractor
[2] => analyse
[3] => send_purchase_order
[4] => buy_materials
[5] => invoice
[6] => update_books
[7] => __toString
[8] => __destruct
[9] => quote
[10] => prepare_foundations
[11] => inspect
)
)
Array
(
[contractor_id] => 002
[uuid] => 53793ccbbaec8
[methods] => Array
(
[0] => __construct
[1] => fetchContractor
[2] => analyse
[3] => send_purchase_order
[4] => buy_materials
[5] => invoice
[6] => update_books
[7] => __toString
[8] => __destruct
[9] => quote
[10] => prepare_foundations
[11] => inspect
)
)