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.
<?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;
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
)
)