Having spent years writing procedural PHP (albeit with a moderate understanding of OOP from Java) I took the plunge and have attempted to write an autload class for my PHP applications.
abstract class AutoloadClass {
protected $_observers = array();
protected $structure;
protected $extension;
/**
* autoload()
* Includes files from specified structure
* @param String $class The class name and file name
* @param String $structure The location of this file
* @param String $extension The file extension
*/
protected function autoload($class, $structure, $extension) {
$filename = $structure . strtolower($class) . $extension;
if (!file_exists($filename)) {
return false;
}
require_once $filename;
return true;
}
/**
* attach()
* Attaches an Observer
*/
public function attach($observer) {
array_push($this->_observers, $observer);
}
/**
* detach()
* Removes an Observer
*/
public function detach($observer) {
foreach ($this->_observers as $key => $item) {
if ($observer == $item) {
unset($this->_observers[$key]);
}
}
}
/**
* update()
* Notify all observers of change in state
*/
public function update() {
foreach ($this->_observers as $key => $item) {
$item->update($this);
}
}
/**
* apply()
* Applys observers code. Some observers do not require this
*/
public function apply() {
foreach ($this->_observers as $key => $item) {
$item->apply();
}
}
}
/**
* LoadFolder
* Extends the AutoloadClass and adds observer functionality
* as well as implementing methods to set autload folder paths
* @see AutoloadClass
*
**/
class LoadFolder extends AutoloadClass {
protected $structure;
protected $extension;
private $state = ""; // String containing a current state message
/**
* __construct() {
* Attaches observers to be automatically included
*
**/
public function __construct() {
$this->attach(AutoloadObserver::getInstance());
//$this->attach(ConsoleLogger::getLogger());
}
/**
* setAttributes($structre,$extension)
* This method takes user input $structure and $extension
* e.g. $this->setAttributes("app/libs/",".app.libs.php")
* stores these attributes in class variables, and instantiates
* spl_autoload_register() using $this and customAutoloader() as its method
*
**/
public function setAttributes($structure, $extension) {
$this->structure = $structure;
$this->extension = $extension;
$this->state = "Attributes added";
$this->update($this);
spl_autoload_register(array($this, 'customAutoLoader'),true);
}
/**
* getAttributes()
* Returns an array of the current attributes
* @return Array ('structure','extension')
*
**/
public function getAttributes() {
return array('structure' => $this->structure, 'extension' => $this->extension);
}
/**
* getState()
* Returns the current state of the class. This is represented by $this->state
* @return String state
*
**/
public function getState() {
return $this->state;
}
/**
* customAutoloader($class)
* This method is only instantiated by spl_autoload_register()
* It checks the return value of the autoload() method (@see AutoloadClass)
* updates the current state and informs observers.
*
**/
private function customAutoloader($class) {
if (!$this->autoload($class, $this->structure, $this->extension)) {
$this->state = $class . " load failed";
$this->update($this);
} else {
$this->state = $class . " loaded";
$this->update($this);
}
}
}
/**
* AutoloadFactory
* Factory class to return new autload objects as required
* This class is a singleton.
**/
class AutoloadFactory {
private static $instance;
private function __construct() {}
public static function getInstance() {
if (!is_object(self::$instance))
self::$instance = new AutoloadFactory();
return self::$instance;
}
public function getObject() {
return new LoadFolder();
}
}
I aprreciate it's quite a lump of code to post up here, but thank you for taking time to review it!
A couple of questions:
a) I'm still slightly sketchy in some areas of OOP implementation, I've tried to stick to tried and tested patterns with some mofifications (i.e. Observers not just being notified of a change in state, but also being asked to perform certain tasks using AutoloadClass apply()
). Is this kind of tinkering with the pattern doing me any favours or should I be looking at other patterns to 'plugin' such objects?
b) Is this massive overkill? It works great locally for me but I am guessing will add considerable overhead on my remote servers. Any pointers how to make it more efficient would be great!
Please please let me know of any tweeks / changes you would make to this regardless of the questions I've asked any input bad / good is greatly appreciated.
Thanks in advance!