So I wanted to have use singletons in php, but couldn't find any good tuts that didn't involve cake or zend. I did quite a bit research and asking around and here is what I came up with. I framed the findings around Coldspring which is a ColdFusion dependency injection tool, which basically means it handles your objects for you.
First I have an xml file where I define where my objects (classes) are. If you are not familiar with MVC, I would first suggest reading up on it. But anyways, below I define some objects paths so I don't have to worry about where they are. As you can see I have an objects controller, service, and gateway.
<?xml version="1.0" encoding="ISO-8859-1"?>
<objects>
<object name="objectsController" type="controller" address="app/controllers/objectsController.php"/>
<object name="objectsService" type="service" address="app/services/objectsService.php"/>
<object name="objectsGateway" type="model" address="app/models/objects/objectsGateway.php"/>
</objects>
The next step is to read in the xml nodes. So below is a function that I feed a path to my xml file (above) and it returns me the nodes in PHP.
public function loadSimpleXML($xmlPath){
if (file_exists($xmlPath)) {
$xml = simplexml_load_file($xmlPath);
return $xml;
}else{
exit('Failed to open '.$xmlPath);
}
}
The next step I loop the nodes with the name "object" and do stuff with it.
//create singletons array to hold objects in
$singletons = array();
//get the count of the nodes
$cnt = count($xml->object);
//loop object nodes
for($i = 0; $i < $cnt; $i++) { $object = $xml->object[$i];
//get object name and address
$name = $this->getAttribute($object,"name");
$address = $this->getAttribute($object,"address");
//include the file
$this->loadClass($address);
//create an instances of the object
$pointer = (string)$name[0];
$singletons[$pointer] = new $pointer;
}
Alot of stuff happened in the above function so I will break it down by a few lines. First we get the node by doing:
$object = $xml->object[$i];
After we get the node I call a function to get the attributes of the node. In my case I just want the name and where the object file is at.
$name = $this->getAttribute($object,"name");
$address = $this->getAttribute($object,"address");
public function getAttribute($node,$name){
$attrs = $node->attributes();
return $attrs[$name];
}
Next I have to include the file. In PHP I found out you need to include the file if you want to use it. To do this I created a function that does a require_once(). I know you don't need a function for it but I figure it didn't hurt and this way if I have to do anything before my include or after I have the ability to do it now. In case you don't $this is used to call a function within a object file. Also you notice I have a variable call $GLOBALS["siteroot"]. I actually load up an environment xml file that takes of these properties but to be straight...the variable just contains the site root of my project, so no biggie here.
$this->loadClass($address);
public function loadClass($classPath){
require_once($GLOBALS["siteroot"].$classPath);
}
The next part was the hard part...dynamically creating an instance of the object. I found out that I needed to use a pointer to use "new", which took forever to figure out, because me and pointers don't mix (I just wanna chain stuff together). Anyways here's what I got.
//create an instances of the object
$pointer = (string)$name[0];
//append object to an array objects so they can be used later.
$singletons[$pointer] = new $pointer;
Later I store the $singleton's array in the $GLOBAL scope because it's the only scope that I know is some what persistant...but it's not. I don't think PHP has a persistant scope without creating a session. If any one has any ideas on where I can put this $singletons array so I don't to have read it from the xml everytime (if you caught the globals...I am techinically not fully using the singleton's pattern because I have no scope to put it in) I would greatly appreciate it, but I have found this works pretty slick for now.
No comments:
Post a Comment