<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jeremy Cook &#187; PHP</title>
	<atom:link href="http://jeremycook.ca/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://jeremycook.ca</link>
	<description>Random musings on web development and PHP</description>
	<lastBuildDate>Thu, 10 May 2012 02:27:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Implementing IteratorAggregate and Iterator</title>
		<link>http://jeremycook.ca/2012/05/06/implementing-iteratoraggregate-and-iterator/</link>
		<comments>http://jeremycook.ca/2012/05/06/implementing-iteratoraggregate-and-iterator/#comments</comments>
		<pubDate>Mon, 07 May 2012 01:26:05 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[SPL]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=267</guid>
		<description><![CDATA[After a bit of a break I’m finally able to get back to writing about the predefined interfaces in PHP. PHP provides two interfaces that allow you to define how your objects behave in a foreach loop: IteratorAggregate and Iterator. Before taking a look at IteratorAggregate I’ll briefly discuss how we can iterate over objects [...]]]></description>
			<content:encoded><![CDATA[<p>After a bit of a break I’m finally able to get back to writing about the predefined interfaces in PHP. PHP provides two interfaces that allow you to define how your objects behave in a foreach loop: IteratorAggregate and Iterator. Before taking a look at IteratorAggregate I’ll briefly discuss how we can iterate over objects in PHP ‘natively’ and what it means to be Traversable.</p>
<h2>Iterating over Objects</h2>
<p>PHP natively allows us to iterate over objects in a foreach loop. However, this only works with public properties of the object. If your object has public properties these will be the values provided in each iteration. If you’re following the concept of encapsulation in your objects though you’ll probably be using private or protected properties with getters and setters. Obviously this presents a problem if you want to iterate through the properties of the object. This is where IteratorAggregate and Iterator come in. If you implement one of these interfaces in your class you can define your own logic which governs the values to return when an object is iterated over.</p>
<h2>On Being Traversable</h2>
<p>Before we have a look at implementing IteratorAggregate or Iterator I should briefly mention the Traversable interface. Traversable is a bit of an oddity. The PHP manual defines it as an ‘abstract base interface that cannot be implemented alone. Instead it must be implemented by either IteratorAggregate or Iterator’. The manual goes on to explain that internal classes can implement Traversable and these can be used in a foreach construct. If Traversable is an interface that you can’t implement yourself then what good is it? You can use it in type hinting or with the instanceof operator to detect if an object can be used in a foreach construct. If you simply need to find out if you can use an object in a foreach loop and are not too worries about the exact type of the object checking if Traversable is implemented is a quick and easy solution.</p>
<h2>Implementing IteratorAggregate</h2>
<p>Implementing IteratorAggreagate is extremely easy. You only need to implement one method, getIterator. This method has to return a data structure that can be iterated over and the PHP engine automatically calls this method when it detects an object implementing this interface being used in a foreach loop. Of course it’s up to you whether this is an array or an object that implements the Traversable interface. A simple, contrived example of implementing this interface is as follows:</p>
<pre class="brush: php; title: ; notranslate">

class Foo implements IteratorAggregate

{

protected $values = array();

//various methods here to work with the object and set values in $values

public function getIterator()

{

return $this-&gt;values;

}

}
</pre>
<p>IteratorAggregate is perfect for occasions when your object holds an array or Traversable object of values and all you want to do is to iterate over these. If you need to do anything more complicated, such as altering or examining values before they’re returned, you need to use it’s big brother, Iterator.</p>
<h2>Implementing Iterator</h2>
<p>The iterator interface is a bit more complicated that IteratorAggregate and requires that you implement five methods: current, key, next, rewind and valid. Current should return whatever the current value should be in the iteration while key should return a key value for it. Next is used to advance the Iterator forwards by one step while rewind should reset whatever pointer is being used to determine the iteration. Finally, valid should return a boolean value to indicate if a value exists for the current iteration. This seems like a lot but the PHP engine takes care of calling these methods for you at the appropriate times in a foreach loop. In most cases you’ll also find that next, rewind and valid can be pretty minimal methods. A (once again contrived) example of using Iterator is below.</p>
<pre class="brush: php; title: ; notranslate">

class Bar implements Iterator

{

protected $values;

protected $counter = 0;

//Various methods to set data and to work with the object

public function rewind()

{

$this-&gt;counter = 0;

}

public function next()

{

$this-&gt;counter++;

}

public function valid()

{

return array_key_exists($this-&gt;counter, $this-&gt;values);

}

public function current()

{

return $this-&gt;values[$this-&gt;counter];

}

public function key()

{

return $this-&gt;counter;

}

}
</pre>
<p>This example is obviously very simple and holds no real advantages over IteratorAggregate. The true advantage of Iterator over IteratorAggregate is that it allows you to manipulate the data in key and current before it is returned. One place that I’ve done this a lot recently is in working with the SalesNet CRM API. The API returns results as XML which I process using XPath. The result of this is an array of SimpleXML elements that I can iterate over. By using Iterator for this instead of IteratorAggregate I can transform the SimpleXMLElement objects into scalar values in the current method before they’re returned. I can also have the key method return account or deal id&#8217;s for the current result. This would not be possible with IteratorAggregate. For me this was an ideal way of working with the results of a web service call in a view layer. I would usually implement the countable interface too which would be used to return the number of results held by the object. A simple call to count() would check this, followed by iteration over the object and display of the results.</p>
<p>I&#8217;ll post another article in this series in the next few weeks looking at using Countable, ArrayAccess and Iterator/IteratorAggregate all together in one object. I&#8217;ll also take a brief spin through the ArrayObject class and when you might want to use it.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/05/06/implementing-iteratoraggregate-and-iterator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making PHPUnit, Doctrine &amp; MySQL Play Nicely</title>
		<link>http://jeremycook.ca/2012/02/27/making-phpunit-doctrine-mysql-play-nicely/</link>
		<comments>http://jeremycook.ca/2012/02/27/making-phpunit-doctrine-mysql-play-nicely/#comments</comments>
		<pubDate>Mon, 27 Feb 2012 21:46:30 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Unit Testing]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[PHPUnit]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=251</guid>
		<description><![CDATA[I’m currently using Doctrine for the first time and really enjoying it so far. One of the pain points for me though has been in getting Doctrine setup with PHPUnit for testing. One of the main Doctrine contributors, Benjamin Beberlei, has written a package called DoctrineExtensions which amongst other things adds a class called DoctrineExtensions\PHPUnit\OrmTestCase [...]]]></description>
			<content:encoded><![CDATA[<p>I’m currently using Doctrine for the first time and really enjoying it so far. One of the pain points for me though has been in getting Doctrine setup with PHPUnit for testing. One of the main Doctrine contributors, Benjamin Beberlei, has written a package called <a href="https://github.com/beberlei/DoctrineExtensions">DoctrineExtensions</a> which amongst other things adds a class called DoctrineExtensions\PHPUnit\OrmTestCase which extends PHPUnit’s DbUnit database test case class. This all works well in principle but hits a major snag in reality: MySQL doesn’t allow InnoDb tables with foreign keys to be truncated. PHUnit’s database extension truncates the database tables before each test run and inserts a fresh set of data to work with. By default Doctrine uses the InnoDb table type and creates foreign key constraints to enforce referential integrity. With this combination the test run errors out every time if you have Doctrine entities that reference other entities through foreign keys. There is a solution to this however which I’ll explain below.</p>
<h2>Solving this problem in PHPUnit</h2>
<p>This problem isn’t exclusive to unit testing with Doctrine. <a href="http://digitalsandwich.com/">Mike Lively</a>, the author of PHPUnit’s DbUnit extension, has provided a solution <a href="https://gist.github.com/1319731">in a Gist</a>. Basically, this extends the PHPUnit_Extensions_Database_Operation_Truncate class to suspend MySQL foreign key checks for the length of the truncate operation. The getSetUpOperation() method then needs to be overridden in the test class to use the custom MySQL truncate class. All in all a neat and elegant solution.</p>
<h2>Porting this Solution to Doctrine</h2>
<p>Porting this solution turned out to be fairly simple, with the exception of one issue which needed to be addressed. I started with the custom MySQL truncate class, which is almost an exact copy of the one Mike Lively wrote:</p>
<pre class="brush: php; title: ; notranslate">

&lt;?php

namespace Tests\Models\Db;

use PHPUnit_Extensions_Database_Operation_Truncate,
 PHPUnit_Extensions_Database_DB_IDatabaseConnection,
 PHPUnit_Extensions_Database_DataSet_IDataSet;
/**
 * MySQL truncate class that allows foreign key checks to be suspended for the duration of the truncate operation.
 * @author Mike Lively
 * @author Jeremy Cook
 * @version 1.0
 * @package Veridis
 * @see https://gist.github.com/1319731
 */
class MySQLTruncate extends PHPUnit_Extensions_Database_Operation_Truncate
{
 /**
 * Executes the truncate.
 * Note: the $connection variable here is an instance of DoctrineExtensions\PHPUnit\TestConnection
 * (non-PHPdoc)
 * @see PHPUnit_Extensions_Database_Operation_Truncate::execute()
 */
 public function execute(PHPUnit_Extensions_Database_DB_IDatabaseConnection $connection, PHPUnit_Extensions_Database_DataSet_IDataSet $dataSet)
 {
 $connection-&gt;getConnection()-&gt;exec(&quot;SET @PREVIOUS_foreign_key_checks = @@foreign_key_checks&quot;);
 $connection-&gt;getConnection()-&gt;exec(&quot;SET @@foreign_key_checks = 0&quot;);
 parent::execute($connection, $dataSet);
 $connection-&gt;getConnection()-&gt;exec(&quot;SET @@foreign_key_checks = @PREVIOUS_foreign_key_checks&quot;);
 }

}
</pre>
<p>This is pretty self explanatory and simply disables MySQL’s foreign key checks while the database tables are truncated and populated with data. I then created an abstract base class which extends the OrmTestCase class to set up the entity manager. This can then be extended by any class that needs to test against the database with an entity manager. To this class I added the code to register the custom MySQL truncate class, and a simplified version of the class looks like this:</p>
<pre class="brush: php; title: ; notranslate">

&lt;?php

use DoctrineExtensions\PHPUnit\OrmTestCase,
 Doctrine\ORM\Configuration,
 Doctrine\Common\Cache\ArrayCache,
 Doctrine\ORM\EntityManager,
 PHPUnit_Extensions_Database_Operation_Composite,
 PHPUnit_Extensions_Database_Operation_Factory;

/**
 * Base class for test cases that need an entity manager to work with.
 * Defines an entity manager for the tests to work with.
 * @author Jeremy Cook
 * @version 1.0
 */
 abstract class Base extends OrmTestCase
 {
 /**
 * Method to create the entity manager, used by parent methods.
 * @return \Doctrine\ORM\EntityManager
 * @see OrmTestCase::createEntityManager()
 */
 protected function createEntityManager ()
 {
 $config = new Configuration;
 $cache = new ArrayCache();
 //Set up config here.
 $conn = array();
 return EntityManager::create($conn, $config);
 }
 /**
 * Overrides the parent method to add a custom MySQL truncate operation.
 * This suspends foreign key checks for the duration of the truncate command.
 * (non-PHPdoc)
 * @see DoctrineExtensions\PHPUnit\DatabaseTestCase::getSetUpOperation()
 */
 public function getSetUpOperation()
 {
 $truncate = new MySQLTruncate();
 return new PHPUnit_Extensions_Database_Operation_Composite(array(
 $truncate,
 PHPUnit_Extensions_Database_Operation_Factory::INSERT()
 ));
 }
 }
</pre>
<p>The createEntityManager method is defined as abstract in OrmTestCase and needs to return an instance of Doctrine\ORM\EntityManager. The getSetUpOperation method is defined in PHPUnit_Extension_Database_TestCase and is overriden here to add the custom MySQL truncate class. There’s one final abstract method that needs to be implemented in a test class and that’s getDataSet. This is defined in PHPUnit_Extension_Database_TestCase and needs to return a PHPUnit_Extensions_Database_DataSet_IDataSet instance to populate the database with data. With this I created a test case extending this class, added data to populate the database, ran it and got an exception. What was going on?</p>
<h2>The Last Problem</h2>
<p>I traced the exception down to DoctrineExtensions\PHPUnit\TestConnection::getTruncateCommand(). This method was hard coded to throw an exception when called. I spoke to Benjamin Beberlei on IRC to ask him about this and he couldn’t remember why this code was added here. I made an edit so that the getTruncateCommand method looks as follows:</p>
<pre class="brush: php; title: ; notranslate">

&lt;?php

/**

* Returns the command used to truncate a table.
*
* @return string
*/
public function getTruncateCommand()
{
 return 'TRUNCATE';
}
</pre>
<p>With this everything seems to work. Doctrine’s PHPUnit test extension is able to truncate tables in a MySQL database that have foreign key constraints.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/02/27/making-phpunit-doctrine-mysql-play-nicely/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementing the ArrayAccess Interface</title>
		<link>http://jeremycook.ca/2012/01/22/implementing-the-arrayaccess-interface/</link>
		<comments>http://jeremycook.ca/2012/01/22/implementing-the-arrayaccess-interface/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 00:10:00 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ArrayAccess]]></category>
		<category><![CDATA[Countable]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=242</guid>
		<description><![CDATA[This is the second part of an occasional series looking at practical uses for the PHP SPL and predefined interfaces. The first post in the series looked at implementing the Countable interface, this one will examine the ArrayAccess interface. What is the ArrayAccess Interface? ArrayAccess allows you to treat an object that implements it as [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second part of an occasional series looking at practical uses for the <a href="http://ca2.php.net/manual/en/book.spl.php">PHP SPL</a> and <a href="http://ca2.php.net/manual/en/reserved.interfaces.php">predefined interfaces</a>. The first post in the series looked at implementing the <a href="http://jeremycook.ca/2012/01/01/using-the-countable-interface/">Countable</a> interface, this one will examine the <a href="http://ca2.php.net/manual/en/class.arrayaccess.php">ArrayAccess</a> interface.</p>
<h2>What is the ArrayAccess Interface?</h2>
<p>ArrayAccess allows you to treat an object that implements it as if it is an array <em>for the purposes of setting, unsetting and retrieving data from it</em>. Please note the emphasis in the last sentence! ArrayAccess does not make an object behave like an array in any other way. If you pass an object that implements ArrayAccess to a PHP array function such as in_array() you’ll still get an error. This will become a little clearer with some of the examples below.</p>
<p>To implement ArrayAccess you need to implement four methods: offsetExists, offsetGet, offsetSet and offsetUnset. ArrayAccess::offsetExists must return a boolean, offsetGet can return any valid PHP type while offsetSet and offsetUnset should not return any value. Once you implement these methods you can treat an object as if it is an array for the purposes of saving and retrieving properties. Here’s a brief example.</p>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  1: class Foo implements ArrayAccess {</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  2:</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  3: 	protected $_values = array();</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  4:</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100.27%; font-family: consolas,'Courier New',courier,monospace; height: 18px; font-size: 12px;">  5: 	public function offsetExists($offset)</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  6: 	{</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  7: 		return array_key_exists($offset, $this-&gt;_values);</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  8: 	}</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  9:</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 10: 	public function offsetGet($offset)</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 11: 	{</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 12: 		return $this-&gt;offsetExists($offset) ? $this-&gt;_values[$offset]:NULL;</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 13: 	}</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 14:</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 15: 	public function offsetSet($offset, $value)</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 16: 	{</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 17: 		$this-&gt;_values[$offset] = $value;</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 18: 	}</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 19:</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 20: 	public function offsetUnset($offset)</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 21: 	{</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 22: 		if ($this-&gt;offsetExists($offset)</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 23: 			unset($this-&gt;_values[$offset]);</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 24: 	}</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 25: }</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 26:</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 27: $bar = new Foo();</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 28: $baz = isset($bar['baz']); //Calls offsetExists and returns false</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 29: $bar['baz'] = 1; //Calls offsetSet and adds a new member to the _values array with the key of 'baz' and the value of 1</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 30: $baz = isset($bar['baz']); //true</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 31: echo $bar['baz']; //Calls offsetGet and prints 1.</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 32: unset($bar['baz']);//Calls offsetUnset and removes the value from the internal _values array</pre>
<p>Hopefully this should all be fairly self-explanatory and you can see how ArrayAccess can allow you to treat an object like an array. Once again, note that this only allows you to use the array notation to set, unset, retrieve and find out if values are set in the internal _values property. If you want to count the number of values set you’d need to implement Countable and if you wanted to be able to iterate over the object you’d need to implement Iterator or IteratorAggregate. Even then the object could not be passed to PHP array functions.</p>
<p>The above example is also incredibly simplistic. There’s nothing to say that the internal storage for the properties being set has to be an array. Likewise, the logic in your implementation of the ArrayAccess methods can be as simple or as complicated as you need.</p>
<h2>Hang on a minute…</h2>
<p>In reality the only thing that ArrayAccess gives you that can’t be achieved using PHP’s magic methods is the ability to use array notation. Apart from that there’s nothing here that can’t be achieved with the magic __get(), __set(), __isset() and __unset() methods. So, the question here has to be why bother with ArrayAccess at all when it only provides syntactic sugar? This is a hard one to answer and really comes down to a matter of personal preference. I personally quite like the syntax ArrayAccess gives, especially when coupled with the Countable and Iterator interfaces. For me as well it also gives me a different mindset. I’m used to my IDE providing me with code completion, which of course doesn’t work with magic methods. I always find it a little unnerving when the code completion doesn’t appear, even when I know that it’s not working because of PHP’s ‘magic’. This isn’t a problem with the array syntax that ArrayAccess provides. Of course this is a very subjective viewpoint and those of you reading this will I’m sure have or develop your own opinions on this.</p>
<h2>A practical example</h2>
<p>One place where ArrayAccess is very useful is in an object where you have a large number of arbitrary values that you need to store and retrieve. I’ve recently been doing a lot of work with the SalesNet CRM system for a client through their SOAP API. The SalesNet API exposes a massive amount of functionality and a lot of the methods can accept a large number of fields to set data for or retrieve data from. SalesNet also allows it’s customers to create custom defined fields and these can both be set and retrieved through the API.</p>
<p>Since there are so many possible values that can be set and retrieved this is a perfect case for using ArrayAccess. I simple pass the name of the SalesNet field that I’m setting or retrieving data from as the ‘array key’. If I’m storing the data in the object to be sent to SalesNet I can retrieve the key and value pairs and process them as needed before making the SOAP call.</p>
<p>Things can get a little more interesting when retrieving data from SalesNet. The response payload is a large lump of XML in most cases. I’ve often resorted to processing this with XPath to get to the nodes I interested in and storing these as an internal property of the object. I can then use offsetGet and offsetExists to work with the data, usually transforming it in some way before returning it. I also often implement the Countable interface to return the number of results. Consider the following (simplified) example:</p>
<pre></pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  1: class SalesNetDemo implements ArrayAccess, Countable</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  2: {</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  3: 	//Array of SimpleXML objects following processing of the response.</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  4: 	protected $_data = array();</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  5:</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  6: 	protected $_soap;</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  7:</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  8: 	public function __construct($soap)</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">  9: 	{</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 10: 		$this-&gt;_soap = $soap;</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 11: 	}</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 12:</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 13: 	public function doSoapCall()</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 14: 	{</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 15: 		//Code to do a Soap call and process the results here using XPath.</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 16: 	}</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 17:</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 18: 	public function count()</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 19: 	{</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 20: 		return count($this-&gt;_data);</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 21: 	}</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 22:</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 23: 	public function offsetExists($offset)</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 24: 	{</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 25: 		return (isset($this-&gt;_data-&gt;$offset) &amp;&amp;</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">                 '' !== (string) $this-&gt;_data-&gt;$offset);</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 26: 	}</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 27:</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 28: 	public function offsetGet($offset)</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 29: 	{</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 30: 		return (isset($this-&gt;_data-&gt;$offset) &amp;&amp;</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;">                 '' !== (string) $this-&gt;_data-&gt;$offset) ? (string) $this-&gt;_data-&gt;$offset : NULL;</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 31: 	}</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 32:</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 33:</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 34:     	public function offsetSet ($offset, $value)</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 35:     	{</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 36:         	throw new BadMethodCallException(sprintf(</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 37:             		'Values cannot be changed in this class, thrown in %s',</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 38:             		__METHOD__</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 39:         	));</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 40:     	}</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 41:</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 42:     	public function offsetUnset ($offset)</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 43:     	{</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 44:         	throw new BadMethodCallException(sprintf(</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 45:             		'Values cannot be changed in this class, thrown in %s',</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 46:             		__METHOD__</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 47:         	));</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 48:     	}</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 49: }</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 50:</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 51: $foo = new SalesNetDemo(new SalesNetSoapObject);</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 52: $foo-&gt;doSoapCall();</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 53: if(count($foo)) {</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 54: 	//Results retrieved from the API.</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 55: 	//Try to get a valueand echo it.</pre>
<pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 56: 	echo $foo['CDF12345'];</pre>
<pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px;"> 57: }</pre>
<p>Again, this is a pretty simple example. The object is only designed to allow data to be retrieved and read, which is why offsetSet and offsetUnset throw exceptions. A real world example might allow the same object to amend the data through the API. The real point of the example though is to show you how the data can be transformed before returning it from the object. Again, the example is deliberately simplistic but you can get the idea of the kinds of things that can be achieved. This is also an example as to how multiple predefined interfaces can be combined to achieve some pretty powerful results.</p>
<p>I hope you’ve enjoyed this brief, and simple, look at ArrayAccess. Let me know in your comments how you you’ve used ArrayAccess in your own code. I’ll add another post as soon as I have time looking at the Iterator and IteratorAggregate interfaces and I’ll also try to add an example that implements Countable, ArrayAccess and Iterator to show how they can work together.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/01/22/implementing-the-arrayaccess-interface/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using the Countable Interface</title>
		<link>http://jeremycook.ca/2012/01/01/using-the-countable-interface/</link>
		<comments>http://jeremycook.ca/2012/01/01/using-the-countable-interface/#comments</comments>
		<pubDate>Sun, 01 Jan 2012 17:14:43 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[SPL]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=230</guid>
		<description><![CDATA[PHP provides a number of predefined interfaces and classes that can really make your life as a developer easier but which are often overlooked. The functionality offered by the Standard PHP Library (SPL) and the predefined interfaces is extremely cool and very powerful but very underutilised. I&#8217;ve found myself reaching more and more for these features recently and [...]]]></description>
			<content:encoded><![CDATA[<p>PHP provides a number of predefined interfaces and classes that can really make your life as a developer easier but which are often overlooked. The functionality offered by the <a href="http://ca2.php.net/manual/en/book.spl.php">Standard PHP Library</a> (SPL) and the <a href="http://ca2.php.net/manual/en/reserved.interfaces.php">predefined interfaces</a> is extremely cool and very powerful but very underutilised. I&#8217;ve found myself reaching more and more for these features recently and it set me to thinking why are they not more widely used? After a little bit of thought I think I&#8217;ve worked it out. For the most part PHP extensions allow you to achieve some concrete action which is easy to grasp. In comparison it&#8217;s much harder to see what the SPL and predefined interfaces are going to do for you. While they let you hook into the core PHP engine in really powerful and useful ways it&#8217;s not easy to see at first glance how to use them. The problem is in a lack of &#8216;real-world&#8217; examples. While most of this functionality is well documented the examples are often somewhat dry and academic. This isn&#8217;t really the fault of the PHP manual: the functionality in the SPL or predefined interfaces can be applied to so many different ways that it&#8217;s hard to provide concrete uses for them. I thought I&#8217;d write a few articles with examples of how I&#8217;ve used these classes and interfaces in the hope that someone would find it useful. I&#8217;d love it if people felt like commenting with their own examples too. I&#8217;ll start with a quick look at the Countable interface.</p>
<h2>The Countable Interface</h2>
<p>The <a href="http://ca2.php.net/manual/en/class.countable.php">Countable interface</a> at it&#8217;s simplest level allows you to pass objects that implement it to PHP&#8217;s native count function. The interface is, on the surface, extremely easy to implement. You only need to add the Countable::count() method to implement the interface in your class and this method only needs to return an integer. If you pass an object that implements Countable to the PHP count function the PHP interpreter will automatically call the count method in the object, returning the value from it to you to use.</p>
<h2>Why is Countable so Useful?</h2>
<p>Like all of the predefined interfaces and SPL functionality the real power of countable comes from the ability to effectively override and re-implement core PHP functionality with your own logic. I&#8217;ll give three brief examples here of ways that I&#8217;ve personally used Countable recently.</p>
<h3>Accessing the State of a Private or Protected Property</h3>
<p>One of the simplest uses of countable is to return the count of an array that&#8217;s held as a protected or private property of an object. Take the following example:</p>
<pre class="brush: php; title: ; notranslate">

class SomeClass implements Countable {

 protected $_data = array();

 public function doSomething()
 {
//Code to change $_data here
 }

 public function count()
 {
return count($this-&gt;_data);
 }
}
</pre>
<p>In this example some data is stored in the object as an array and the Countable:Count method simply returns the count of that array. While this is obviously a very simple example it can be very powerful. I&#8217;ve been doing a lot of work with a web service in the last few weeks and have used code very much like this. After a web service call the resulting XML is processed using XPath and the resulting array is stored in a protected property. The count method would then return the number of results of the web services call. Using count in this way obviously makes a lot of sense when coupled with implementing Iterator or ArrayAccess to allow access to the data held in the protected property.</p>
<h3>Using Countable to Signal the State of an Object</h3>
<p>Countable can also be used to signal the state of an object. Imagine the above code, amended slightly to this:</p>
<pre class="brush: php; title: ; notranslate">

class SomeOtherClass implements Countable {

protected $_data;

public function doSomething()
{
//Code to change $_data here
}

public function count()
{
return is_null($this-&gt;_data) ? 0 : 1;
}
}
</pre>
<p>In this case count will only ever return 0 or 1, depending on whether the protected property $_data has a value set in it or not. Using this code could look something like this:</p>
<pre class="brush: php; title: ; notranslate">

$obj = new SomeOtherClass();

$obj-&gt;doSomething();

if (count($obj)) {

//$_data is not null, proceed accordingly.

}
</pre>
<p>I&#8217;ve also used this recently with a web service call. In this case the web service call was expected to return a single value, which is stored in $_data. Implementing countable like this simply signifies to the calling code if a value has been successfully retrieved or not.</p>
<h3>Using Countable with a Database Table</h3>
<p>Another interesting use of Countable is with a class that maps to a database table in some way. Imagine a case where you have a database table where values are only considered &#8216;live&#8217; if some condition is met. Implementing countable on an object that encapsulates the db table can then be used to flag if the table contains any &#8216;live&#8217; values. The following example uses Zend_Db_Table:</p>
<pre class="brush: php; title: ; notranslate">

class AnotherClass extends Zend_Db_Table implements Countable {

 public function count()
 {
$select = $this-&gt;select(Zend_Db_Table::SELECT_WITH_FROM_PART)
-&gt;from('some_table', array('Count' =&gt; 'COUNT(*)'))
-&gt;where('SomeCondition = SomeValue');
$row = $this-&gt;fetchRow($select);
return (int) $row-&gt;Count;
 }
}
</pre>
<p>In your calling code you would then simply do this:</p>
<pre class="brush: php; title: ; notranslate">

$obj = new AnotherClass();

if (count($obj)) {

//Table has 'live' values. Do something here

}
</pre>
<p>This can be a very useful way of working with a database table.</p>
<h2>A Word of Caution&#8230;</h2>
<p>The only limit to the way Countable can be used is the imagination of the developer, and this is also a danger. All developers are familiar with using the count() function to get hold of the number of values in an array. When implementing Countable the further you move the count() method away from this functionality the less intuitive the code becomes and the greater the chance that the developer using it might make a mistake. This is true of all of the predefined interfaces however. While they provide great power the further away from core PHP functionality you get while implementing them in your own code the less intuitive they become. However, don&#8217;t let this stop you! The next time you go to write a method called something like &#8216;getItemCount()&#8217; in a class don&#8217;t do it! Implement the Countable interface instead and start hooking into the power of the core PHP engine.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/01/01/using-the-countable-interface/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Using SalesNet Web Services from PHP</title>
		<link>http://jeremycook.ca/2011/12/06/using-salesnet-web-services-from-php/</link>
		<comments>http://jeremycook.ca/2011/12/06/using-salesnet-web-services-from-php/#comments</comments>
		<pubDate>Wed, 07 Dec 2011 02:05:56 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=223</guid>
		<description><![CDATA[I&#8217;ve been working on some projects recently where I&#8217;ve had to make heavy use of the SalesNet CRM API. I&#8217;ve written some code that makes basic access of the API easier and I thought I would write about it a little here. The SalesNet API is vast in scope (the documentation runs to 144 pages!) [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on some projects recently where I&#8217;ve had to make heavy use of the <a href="http://www.salesnet.com/">SalesNet CRM</a> API. I&#8217;ve written some code that makes basic access of the API easier and I thought I would write about it a little here. The SalesNet API is vast in scope (the documentation runs to 144 pages!) and very fully featured. However, it is not particularly easy to use at all and is somewhat frustrating. My aim in the code was to ease some of the basic frustrations in using the API. Full code and unit tests for the classes that I wrote can be found on <a href="https://github.com/JCook21/SalesNet">GitHub</a>.</p>
<h2>API Format</h2>
<p>The SalesNet API is SOAP based and consists of 8 separate endpoints, each of which allows you to operate on different parts of a companies data such as deals, accounts, contacts, etc. Before you can use any of these services it&#8217;s necessary to authenticate against a separate security endpoint. This returns a token which is valid for between 1-12 hours (depending on the account setup in SalesNet). This token must then be set in a SOAP header for use in requests to any of the main SalesNet endpoints. Each of the API methods accepts many arguments to control precisely the data that is returned and the only thing I can suggest to anyone looking to use the API is to refer to the documentation. One of the quirks of the API is that data is returned as XML, embedded in a stdClass object. For example, a call to the GetDeals method of the deals endpoint returns a stdClass object (say $obj), and to access the response data the following would be needed:</p>
<pre class="brush: php; title: ; notranslate">

$response = $obj-&gt;GetDealsResult-&gt;any;
</pre>
<p>In the above example $response would now include the XML data &#8216;payload&#8217;, which can then be parsed. It&#8217;s often not that easy to parse the XML returned as it seems to be an XML representation of a Microsoft ADODB recordset, which in some cases is not even properly formed XML. I&#8217;ve had luck using SimpleXML and Xpath to extract the nodes I&#8217;m after however.</p>
<h2>The Code</h2>
<p>To work with the various SalesNet API&#8217;s I created two classes, one of which handles authentication and the other of which acts as a proxy to catch and pass SOAP calls through to the API. Both of the classes make use of &#8216;lazy loading&#8217; and will only connect to SalesNet as and when a method is called that requires a SOAP call.</p>
<h3>The Authentication Class</h3>
<p>My goal in the authentication class was to simplify authenticating against the SalesNet security endpoint. The object accepts a company name, username and password and will retrieve a security token from SalesNet. This is then set in a PHP SoapHeader object and is returned for use whenever the doLogin() method is called. Internally the class will keep track of when the token expires and will automatically fetch a new token from SalesNet as and when required. My thought is that an object of this class can be serialized and cached to be stored and shared between many requests as a security token can be valid for up to 12 hours.</p>
<h3>The SoapProxy Class</h3>
<p>The SoapProxy class provides a proxy to trap calls to the many SalesNet API methods. Since there are so many methods cross so many endpoints it would be impossible to map these out to individual methods so I chose to use __call() instead to pass calls through to a PHP SoapClient object. The class stores the URL endpoints of the various services as constants and an API endpoint can be set when an object is instantiated or before any method is called. The object also accepts an instance of the Authentication class and uses this internally to set the security SoapHeader for API calls.</p>
<h2>A Brief Example</h2>
<p>So, enough talk! As I said earlier full code can be found on <a href="https://github.com/JCook21/SalesNet">GitHub</a> but here&#8217;s a brief example of how to use the classes to call the GetDeals method of the Deals endpoint.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
use WebServices\Soap\SalesNet\Authentication, WebServices\Soap\SalesNet\SoapProxy;

try {
    $auth = new Authentication();
    $auth-&gt;setCompanyLogin('COMPANY LOGIN HERE')
         -&gt;setUserName('USERNAME HERE')
         -&gt;setPassword('PASSWORD HERE');

    $soap = new SoapProxy(SoapProxy::DEALS, $auth);
    $args = array(
        //Set up method arguments here
    );
    $response = $soap-&gt;GetDeals($args);
} catch (BadMethodCallException $e) {
    /**
     * Errors will be caught here.
     * The BadMethodCallException can have a previous exception of a SoapFault if there is one.
     */
}
</pre>
<p>That&#8217;s all there is to it. To use other endpoints simply change the constant passed to the SoapProxy constructor and call another Soap method, with the correct arguments of course. Let me know of any comments on this code or improvements people can see. Enhancements and fixes on GitHub are welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2011/12/06/using-salesnet-web-services-from-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend_Form and Validating Values for Multiple Column DB Keys</title>
		<link>http://jeremycook.ca/2011/10/25/zend_form-and-validating-values-for-multiple-column-db-keys/</link>
		<comments>http://jeremycook.ca/2011/10/25/zend_form-and-validating-values-for-multiple-column-db-keys/#comments</comments>
		<pubDate>Wed, 26 Oct 2011 01:11:12 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=219</guid>
		<description><![CDATA[I&#8217;ve recently started developing my first project fully in Zend Framework and I&#8217;ve been loving it so far. There are so many components in the framework that make a developers life easier, among which is the combination of Zend_Filter, Zend_Validate and Zend_Form. I love how easy it is to create and validate forms using these [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently started developing my first project fully in Zend Framework and I&#8217;ve been loving it so far. There are so many components in the framework that make a developers life easier, among which is the combination of Zend_Filter, Zend_Validate and Zend_Form. I love how easy it is to create and validate forms using these components, although Zend Form decorators are still a black art to me. Today I came across a particular problem in validating values that I thought I would write about here.</p>
<p>Zend_Validate includes two classes to work with database columns: Zend_Validate_Db_NoRecordExists and  Zend_Validate_Db_RecordExists. As their names suggest these check that a value either does or doesn&#8217;t exist in a specified column in a database table. The classes work really well in a form when specified as a validator for a value but things can get a little trickier if you need to check two columns in a table. The problem I had was in creating a simple FAQ page for a site. The site owner gets to add FAQs to the site and each FAQ is contained in a category. As a little sanity check I wanted to make sure that the combination of category and question was unique. The database also has a multiple column unique key on these to enforce the integrity. My first attempt looked something like this in a class that extends Zend_Form:</p>
<p>&nbsp;</p>
<pre class="brush: php; title: ; notranslate">

public function init() {
//Category options are populated elsewhere.
$categories = new Zend_Form_Element_Select('category');
$categories-&gt;setAllowEmpty(FALSE)
	   -&gt;setAttrib('required', 'required')
	   -&gt;setLabel('FAQ Category:')
	   -&gt;addErrorMessage('Please choose a valid category from the list.')
	   -&gt;addMultiOption('', '--Please Choose--');
$question = new Zend_Form_Element_Text('question');
$question-&gt;setRequired(TRUE)
	 -&gt;setLabel('Question:')
	 -&gt;setAttrib('required', 'required')
	 -&gt;setAttrib('max', '100')
	 -&gt;addValidator('StringLength', FALSE, array(0,100))
	 -&gt;addErrorMessage('Enter a question of up to 100 characters in length.');
$validate = new Zend_Validate_Db_NoRecordExists(array('table' =&gt; 'faqs', 'field' =&gt; 'title'));
$validate-&gt;getSelect()-&gt;where('FaqCategoryId = ?', $this-&gt;getValue('category'), Zend_Db::PARAM_INT);
$question-&gt;addValidator($validate);
}
</pre>
<p>I thought that this would add the extra where clause to the select statement for the validation. This failed miserably though. The problem is that the value referenced in &#8216;$this-&gt;getValue(&#8216;category&#8217;)&#8217;  doesn&#8217;t exist when the init() method is called. Values are only added to the form when the isValid() method is called. The solution was to extend the isValid() method and to perform the extra check there.</p>
<pre class="brush: php; title: ; notranslate">
public function isValid($data) {
	$result = parent::isValid($data);
	if ($result) {
		$validate = new Zend_Validate_Db_NoRecordExists(array('table' =&gt; 'faqs', 'field' =&gt; 'question'));
		//Add a where clause to check the FaqCategoryId
	        $validate-&gt;getSelect()-&gt;where('FaqCategoryId = ?', $this-&gt;getValue('category'), Zend_Db::PARAM_INT);
	       	$result = $validate-&gt;isValid($this-&gt;getValue('question'));
	       	if (! $result)
	       		$this-&gt;getElement('question')-&gt;setErrors(array('The selected category already has an FAQ with that question. Please edit the question.'));
		}
		return $result;
	}
</pre>
<p>By extending the isValid() method I can call the parent method to do the majority of the work. If the form looks valid I then perform the extra check to make sure the combination of question and category is unique. If it isn&#8217;t an error message is set and the validation fails. I&#8217;ve also used this in another part of the site where the client is adding news articles to the site. In that instance the combination of published date and title needs to be unique as these are used in the url to uniquely reference the article. The same method in form validation checks that when the form is submitted. Using this method I&#8217;ve been able to clean up my controller and move all validation checks into the form, where they should be. I&#8217;d love to hear in the comments how other people approach this problem though.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2011/10/25/zend_form-and-validating-values-for-multiple-column-db-keys/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Guelph PHP Users Group</title>
		<link>http://jeremycook.ca/2011/08/01/guelph-php-users-group/</link>
		<comments>http://jeremycook.ca/2011/08/01/guelph-php-users-group/#comments</comments>
		<pubDate>Tue, 02 Aug 2011 01:09:06 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[GPUG]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=214</guid>
		<description><![CDATA[Colin DeCarlo and I have been working on a PHP users group for South Western Ontario for a while and we&#8217;re pleased to announce the first meeting of the Guelph PHP Users Group. The group will be meeting on the last Wednesday of every month, starting on September 28th, at the offices of Well.ca at [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://twitter.com/#!/colindecarlo">Colin DeCarlo</a> and I have been working on a PHP users group for South Western Ontario for a while and we&#8217;re pleased to announce the first meeting of the Guelph PHP Users Group. The group will be meeting on the last Wednesday of every month, starting on September 28th, at the offices of <a href="http://well.ca/">Well.ca</a> at 919 York Rd, Guelph, ON  N1E 6Y9 from 7.30pm-10pm. For the first meeting <a href="http://ilia.ws/">Ilia Alshanetsky</a>, chief software architect for Advanced Internet Designs Inc, will be talking about &#8216;Hidden Features of PHP&#8217;. For the second meeting Tony Thompson, Director of Technology for <a href="http://mrx.ca/">MRX</a> will be talking about the Varnish web application accelerator. We&#8217;re looking for speakers for other meetings so please get in touch if you have anything you&#8217;d like to speak about.</p>
<p>We&#8217;re hoping to have a discussion at the first meeting about the format people would like the meetings to take and what they would like to get out of it. We&#8217;re also hoping to have an &#8216;open mic&#8217; event at each meeting where people can get up and talk about any programming problems or issues they&#8217;re having or to simply ask for feedback on a site they&#8217;re working on. There will also be plenty of time for socialising.</p>
<p>A big thank you goes out to our sponsors, Well.ca, for providing the venue and other support for the event. Drop us a line if you have any ideas or questions for the group and if you want to attend let us know by registering on <a href="http://guestlistapp.com/events/66297">Guestlistapp</a>. Hope to see as many of you as possible on September 28th!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2011/08/01/guelph-php-users-group/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Easy File Encryption</title>
		<link>http://jeremycook.ca/2011/03/20/easy-file-encryption/</link>
		<comments>http://jeremycook.ca/2011/03/20/easy-file-encryption/#comments</comments>
		<pubDate>Sun, 20 Mar 2011 16:59:25 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ideasofmarch]]></category>
		<category><![CDATA[Streams]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=205</guid>
		<description><![CDATA[I&#8217;ve read in two different books that the streams extension of PHP is one of the most useful but least utilised parts of the language. I&#8217;ve always paid lip service to that idea but something I saw the other day really bought this home to me and I thought I&#8217;d write about it here. I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve read in two different books that the <a href="http://ca3.php.net/manual/en/book.stream.php">streams extension</a> of PHP is one of the most useful but least utilised parts of the language. I&#8217;ve always paid lip service to that idea but something I saw the other day really bought this home to me and I thought I&#8217;d write about it here.</p>
<p>I&#8217;m building an app where I need to encrypt files uploaded by a user to add an extra security layer. I was initially thinking of using <a href="http://ca3.php.net/manual/en/function.stream-filter-register.php">stream_filter_register()</a> to create my own stream filter as the files are read and written. If you&#8217;re not familiar with the concept of stream filters in PHP they&#8217;re a very powerful feature. By attaching a filter to a stream you can perform various operations to data as it is being read from or written to a stream. Once the filter is defined and attached to the stream this is done completely transparently. Anyway, coming back to my problem of encrypting files, I did a quick search on Google and there didn&#8217;t seem to be an easy way of doing this. I then came across <a href="http://www.php.net/manual/en/filters.encryption.php">this gem</a> in the PHP manual. PHP has a number of built in stream filters and one of them is an encryption filter. Providing you have the mcrypt extension installed encrypting and decrypting files is as easy as registering a stream filter on a stream! Pasted below is the example code from the PHP manual.</p>
<p>Here&#8217;s how to encrypt data as it&#8217;s written to a file:</p>
<pre class="brush: php; title: ; notranslate">

&lt;?php

$passphrase = 'My secret';

/* Turn a human readable passphrase

* into a reproducable iv/key pair

*/

$iv = substr(md5('iv'.$passphrase, true), 0, 8);

$key = substr(md5('pass1'.$passphrase, true) .

md5('pass2'.$passphrase, true), 0, 24);

$opts = array('iv'=&gt;$iv, 'key'=&gt;$key);

$fp = fopen('secret-file.enc', 'wb');

stream_filter_append($fp, 'mcrypt.tripledes', STREAM_FILTER_WRITE, $opts);

fwrite($fp, 'Secret secret secret data');

fclose($fp);
?&gt;
</pre>
<p>and here&#8217;s how to decrypt data read from a file:</p>
<pre class="brush: php; title: ; notranslate">

&lt;?php

$passphrase = 'My secret';

/* Turn a human readable passphrase

* into a reproducable iv/key pair

*/

$iv = substr(md5('iv'.$passphrase, true), 0, 8);

$key = substr(md5('pass1'.$passphrase, true) .

md5('pass2'.$passphrase, true), 0, 24);

$opts = array('iv'=&gt;$iv, 'key'=&gt;$key);

$fp = fopen('secret-file.enc', 'rb');

stream_filter_append($fp, 'mdecrypt.tripledes', STREAM_FILTER_READ, $opts);

$data = rtrim(stream_get_contents($fp));

fclose($fp);echo $data&lt;code&gt;;&lt;/code&gt;

?&gt;
</pre>
<p>It couldn&#8217;t be easier! The example in the manual uses tripledes but you can use any of the cyphers and modes available in mcrypt.</p>
<p>The next step for me is to put together an example for my application. I want to store the uploaded files in a database so I need to open the file for reading from its location in $_FILES, adding an encryption filter to the stream, and bind it as a LOB parameter to a PDO insert prepared statement. To read the information back out I need to bind the decryption stream filter to the stream returned from PDO on a select operation. Bearing in mind the <a href="http://jeremycook.ca/2010/02/21/handling-binary-data-with-pdo/">issues that PDO/MySQL has with returning streams from LOB fields </a>I&#8217;m hoping this should be fairly easy. Hopefully this post will help someone looking to do this task.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2011/03/20/easy-file-encryption/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ConFoo Round-Up</title>
		<link>http://jeremycook.ca/2011/03/12/confoo-round-up/</link>
		<comments>http://jeremycook.ca/2011/03/12/confoo-round-up/#comments</comments>
		<pubDate>Sun, 13 Mar 2011 03:38:50 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Random]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[ConFoo]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=196</guid>
		<description><![CDATA[I&#8217;ve just got home from attending the ConFoo conference in Montreal and I thought I&#8217;d write up a few of my thoughts about the conference. All of the talks I heard were good but some stood out more than others for me. I&#8217;ll discuss each day in turn along with a few of the highlights [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just got home from attending the ConFoo conference in Montreal and I thought I&#8217;d write up a few of my thoughts about the conference. All of the talks I heard were good but some stood out more than others for me. I&#8217;ll discuss each day in turn along with a few of the highlights for me.</p>
<h2>Pre-Conference Party and Day 1</h2>
<p>The conference unofficially opened with a pre-conference party on Tuesday evening. I spent much of the evening talking with <a href="http://blog.mageekbox.net/">Frédéric Hardy</a> and <a href="http://twitter.com/waxzce">Quentin Adam</a>, both of whom had come from France to speak at the conference. Not for the last time at the conference I felt guilty for making French speakers speak in English so that I could join in the conversation! Frédéric has been working on an alternative to PHPUnit called Atoum and we spent some time discussing the benefits he is hoping it will provide over PHPUnit. I&#8217;m looking forward to writing some tests using it when I have a chance and seeing how it is.</p>
<p>Day one for me was dominated by the <a href="http://confoo.ca/en/hackfest">YellowAPI ConFoo Hackfest</a>. The Yellow Pages in Canada is releasing an <a href="http://www.yellowapi.com/">API</a> that allows developers free access to all 1.5 million business listings they have in Canada. Each business is even geo-located with latitude and longitude to enable building geo-localised applications. As one of the sponsors of ConFoo they put together a hack day with prizes to allow developers to try out the API. While I didn&#8217;t win anything I spent the day putting together a very rough proof of concept for an app that I really think could be useful. It worked and there was a lot of interest in my idea from the YellowAPI people. I&#8217;m planning on spending some time to write the app properly when I get some time (probably in a few months) and I&#8217;ll write some more about it then. The standard was very high and the winning team deserved to win for their pub crawl application. After the hack was over I still had time to hear Andre Zmievski talk about <a href="http://elasticsearch.org/">Elastic Search</a>. This seems to be a very interesting technology and one I&#8217;ll definitely keep in mind for the future.</p>
<h2>Day 2</h2>
<p>In many ways Day 2 was my first &#8216;proper&#8217; day at the conference as I attended talks all day. The day had three real highlights for me: Michelangelo van Dam&#8217;s talk on &#8216;Improving QA on PHP development projects&#8217;, Antonio Fontes on &#8216;Threat Modelling: detecting threats before coding&#8217; and the conference keynote given by Christian Heilmann on &#8216;HTML5-Moving from hacks to solutions&#8217;.</p>
<p>Michelangelo&#8217;s talk introduced several new tools to me that help to ensure code quality in a project that I&#8217;m very much looking forward to integrating into my workflow. The first of these is <a href="https://github.com/sebastianbergmann/phpcpd">PHP Copy Paste Detector</a> by Sebastian Bergmann. As it&#8217;s name suggests it will analyse code looking for places where it is duplicated. This can indicate places where the duplication should be abstracted out into a function or method. <a href="http://pear.php.net/package/PHP_CodeSniffer/redirected">PHP Code Sniffer</a> can be used to analyse a code base to ensure that a pre-defined coding standard has been adhered to and <a href="http://pdepend.org/">PHP Depend</a> can be used to help analyse the overall quality of the code. <a href="http://phpmd.org/">PHP Mess Detector</a> is another tool that can look at a code base and helpt to highlight potential bugs and problems. Michelangelo wrapped up with talking about using <a href="http://phing.info/trac/">Phing</a> as a build tool and Phar to package up code libraries for use in production. A really great and thought provoking talk.</p>
<p>Antonio Fontes introduced an entirely new topic for me, Threat Analysis and Modelling. This approach aims to help look at the security risks in  building a web application before a single line of code is written. It does this by having one or more people describe the application that is to be created along with how critical the system is from a business perspective. It then moves on to model the various risks that could occur from having the application fail or hacked, the likely types of people who might try to hack it and techniques that can mitigate these risks. This talk was a real eye opener for me and outlined a technique that I&#8217;m very keen to use in the future.</p>
<p>The keynote, delivered by Christian Heilmann of Mozilla, was one of the most inspiring talks of the whole conference for me. His central theme was that we have lost our excitement for new technologies and the wonders that it can offer, becoming somewhat blase about the opportunities that we have available. He presented a passionate and often funny exhortation to all of us to go and create great things using the new possibilities that HTML5 and its related API&#8217;s offer us, allowing these to degrade gracefully for older browsers. A really inspiring session.</p>
<h2>Day 3</h2>
<p>The highlights of the final day of the conference for me were Sebastian Bergmann&#8217;s session on &#8216;Your tests are lying!&#8217; and Alia Alshanetsky&#8217;s talk on &#8216;Hidden features of PHP&#8217;. I also very much enjoyed hearing Arne Blankerts presenting on a new documentation generating tool he is writing which is currently in pre-alpha.</p>
<p>Sebastian Bergmann&#8217;s session discussed some of the problems associated with writing good unit tests. It was illustrated with samples he has seen (edited to protect the guilty!) and provided much practical advice about writing good tests. Alia Alshanetsky&#8217;s session was a great whistlestop tour through some of the lesser known features of PHP. These ranged from underused parts of the language to new features in PHP 5.3.  I made many notes in this session and took away a great many ideas to try.</p>
<p>I really enjoyed the conference and was very impressed with the whole  thing. What really struck me was the way that developers from all  different languages and areas came together to attend and share ideas with each  other. While it&#8217;s so easy to get on our soap boxes and proclaim our  chosen language as &#8216;the best&#8217; there was none of that at ConFoo, which I  found very refreshing. The conference was also a great networking opportunity and I made some new friends in the process. I&#8217;d really like to thank the organisers for putting on such a great event and my employer for recognising the value in having me attend. I&#8217;m already looking forward to ConFoo 2012.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2011/03/12/confoo-round-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some More PDO Weirdness</title>
		<link>http://jeremycook.ca/2010/11/22/some-more-pdo-weirdness/</link>
		<comments>http://jeremycook.ca/2010/11/22/some-more-pdo-weirdness/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 01:26:54 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PDO]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=187</guid>
		<description><![CDATA[I&#8217;ve said before that I&#8217;m a great fan of PDO and use it wherever possible. That said there are some annoying quirks in it, one of which I encountered today. I&#8217;ll outline what I was trying to do, what I expected to happen and what actually happened. I&#8217;m also curious as to what anyone else [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve said before that I&#8217;m a great fan of PDO and use it wherever possible. That said there are some annoying quirks in it, one of which I encountered today. I&#8217;ll outline what I was trying to do, what I expected to happen and what actually happened. I&#8217;m also curious as to what anyone else thinks of this problem and whether it&#8217;s something worth reporting as a bug or if it&#8217;s a &#8216;feature&#8217;.</p>
<h2>What I Was Trying to Do&#8230;</h2>
<p>I&#8217;m currently adding a clearance item section to a website. This will aggregate items from over 35 stores across Canada and allow a user to search for items in a number of ways. As part of this I&#8217;ve created a business object to represent a clearance item. This mainly consists of protected properties with accessors and mutators for setting and getting the properties. Since the site is in English and French the accessors allow the properties to be formatted accordingly before being returned. I use this clearance item class when importing information into the database (items are imported from Excel worksheets, but that&#8217;s a topic for another post) and when returning results from searches. I use data mappers to handle the CRUD operations in the database. What I wanted to do was to find a quick and easy way to transform a row from a resultset into an instance of a clearance item object without using a full ORM solution. I thought I had found this with PDO.</p>
<h2>The &#8216;Solution&#8217;</h2>
<p>PDO allows you to set the fetch mode to fetch an object of a user defined class for each row returned from the database. You can either use PDOStatement::fetchObject() or PDOStatement::setFetchMode() to define this behaviour. It will take the names of the columns and assume that these are properties of the object, setting the appropriate values for these properties. In theory this sounds great but unfortunately it&#8217;s not as easy as it sounds.</p>
<h2>The Problem</h2>
<p>The problem in my case is that all properties of my object are declared as protected and I use mutators to set them. I anticipated this and provided a __set() method to provide the needed property overloading. I thought that what would happen is that PDO would attempt to set an undefined public property, triggering the __set() method where there is logic to call the appropriate mutator. Unfortunately it doesn&#8217;t work like that at all. According to comments in the PHP manual it seems that PDO uses something called reflection injection to set the properties inside the object regardless of their visibility. This meant that I was getting back an instance of my clearance item class with the protected properties set directly by PDO. This may not seem like too much of a problem, but my mutators include logic to transform the properties being set to the correct data type. For instance, columns containing integers or floating point numbers come back as strings and the mutators make sure they are set as numeric data types. Worst of all for me was the information on stores. I&#8217;m using MySQL&#8217;s GROUP_CONCAT() function to &#8216;implode&#8217; information about stores and the inventory in each into a string, meaning that I can fetch all of the information I need in a single query. The logic in the mutator then splits that string apart into an array of information on stores and the inventory. PDO was bypassing this completely and setting the protected stores property as the string that came back from GROUP_CONCAT().</p>
<h2>A Partial Solution</h2>
<p>Once again the PHP manual was my partial saviour. There is a way to fetch a row from a resultset into an existing instance of a class. In this case the visibility of properties is honoured and the __set() function is called, in turn triggering the correct mutators. The code I came up with looks like this:</p>
<pre class="brush: php; title: ; notranslate">

//The statement is prepared before this.

$item = new ClearanceItem($this-&gt;lang);
 $st-&gt;setFetchMode(PDO::FETCH_INTO, $item);
 $st-&gt;bindParam(':ItemId', $id, PDO::PARAM_INT);
 $st-&gt;execute();
 foreach ($st as $result) {
//The query in this case only returns a single row.

return $result;
 }
</pre>
<p>While this works it&#8217;s a bit of a hack to say the least. It seems that PDOStatement::fetch() doesn&#8217;t work here to fetch the info into the object, necessitating the foreach loop and the immediate return. This is fine in this case but in other areas of the code I need to iterate over a resultset, getting a new instance of ClearanceItem each time. This wouldn&#8217;t work as the information is populated into the existing object bound to the statement. The best I could do is to clone the object each time through the loop and store the cloned copy.</p>
<p>There is another way out of this: return each row as an associative array and create a factory method to return instances of ClearanceItem from this. I actually coded this solution already when I intitially found the strangeness that PDO was doing in return instances of ClearanceItem. That solution works perfectly well but it seems strange that it&#8217;s not possible to loop over a record set, getting a new instance of a class each time.</p>
<h2>Conclusion</h2>
<p>It seems that it&#8217;s quite possible to return instances of a class from a PDOStatement providing that all of the properties are public or if you don&#8217;t mind PDO directly setting your private and protected properties. If you want to use mutators to control how your data is set and to make sure it&#8217;s of the correct type it seems that the options are far more limited and you may be out of luck. Of course there are other options, such as writing a factory method to create an object from an array or using a full blown ORM like Doctrine. In this instance, as I haven&#8217;t used Doctrine before and as time is of the essence I was hoping that PDO would give me what I need.</p>
<p>It seems very strange that PDO is allowed to directly set private and protected properties when all other code accessing instances of ClearanceItem have to use the accessors and mutators. It seems to me to drive a coach and horses through the concept of property visibility. Why should PDO (at least I&#8217;m assuming it&#8217;s just PDO) have the ability to bypass the visibility protections that OO code provides while everyone else has to work with it? Is there some good reason for doing this that I&#8217;m missing? I&#8217;d be really interested to hear what the possible advantages of this are.</p>
]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2010/11/22/some-more-pdo-weirdness/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

