<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Jeremy Cook</title>
	
	<link>http://jeremycook.ca</link>
	<description>Random musings on web development and PHP</description>
	<lastBuildDate>Tue, 19 Feb 2013 11:34:36 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/JeremyCook" /><feedburner:info uri="jeremycook" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by-sa/2.0/</creativeCommons:license><item>
		<title>A few Vim Tricks</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/1zmsBIZop7o/</link>
		<comments>http://jeremycook.ca/2013/01/13/a-few-vim-tricks/#comments</comments>
		<pubDate>Mon, 14 Jan 2013 02:16:32 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=322</guid>
		<description><![CDATA[I&#8217;m a fairly recent convert to using Vim for development, having started using it last May. Having become somewhat proficient (or so I think) I wouldn&#8217;t swap it for any other editor. I recently discovered a few config settings that made my life as a developer a little easier and thought I&#8217;d share them here. [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m a fairly recent convert to using Vim for development, having started using it last May. Having become somewhat proficient (or so I think) I wouldn&#8217;t swap it for any other editor. I recently discovered a few config settings that made my life as a developer a little easier and thought I&#8217;d share them here. In this post we&#8217;ll find out how to configure Vim so that the gf (Goto File) command works with PHP namespaced classes. Along the way we&#8217;ll also enable the :find, :tabfind and :splitfind commands so that you can quickly search for any files in your project.</p>
<h2>Find your Path&#8230;</h2>
<p>The first thing that we need to configure is the path settings for your project. Vim uses the path setting to know where to look for files in projects and setting it correctly can save you from having to remember long file names. I use the <a href="https://github.com/embear/vim-localvimrc">localvimrc</a> plugin to configure settings for different projects that I&#8217;m working on and I add the path info to my .lvimrc file. Whether you use this plugin or just a global .vimrc file you simply need to add a setting line for each directory path that you would like Vim to include in searches. For example, I&#8217;m currently doing a lot of work with Symfony2. To add my src and vendor directories to my Vim path I simply need to add the following two lines:</p>
<p><script src="https://gist.github.com/4527261.js"></script><noscript><pre><code class="language-viml viml">set path+=/path/to/project/src/**
set path+=/path/to/project/vendor/**</code></pre></noscript><strong><br />
</strong></p>
<p>You can of course add as many directories as you like. With that setup to search for a file you can use the :find command or any of it&#8217;s siblings. For example to find the file fooBar.php simply type &#8220;:find foo&#8221; and hit tab. Vim will offer you a choice of all files in your path that match what you&#8217;ve typed. For more info type &#8220;:h find&#8221;.</p>
<h2>Getting gf to work with PHP</h2>
<p>Vim&#8217;s gf command opens the file name that is under the cursor to edit. This works well &#8216;out of the box&#8217; with files included or required in PHP but if you&#8217;re doing a lot of work with PHP frameworks you probably don&#8217;t have too many calls to include or require in your code. What you probably will have though is a lot of namespace declarations and use statements in your code. With a little tweaking you can make the gf command work with the namespaced classes though. Add the following two lines to your .vimrc file:</p>
<script src="https://gist.github.com/4527290.js"></script><noscript><pre><code class="language-viml viml">&quot; Allow gf to work with PHP namespaced classes.                                                                                                             
set includeexpr=substitute(v:fname,'\\\','/','g')                                                                                                           
set suffixesadd+=.php</code></pre></noscript>
<p>The first line replaces &#8216;\&#8217; with &#8216;/&#8217; whenever the gf command is using, assuming that your namespaces are PSR-0 compliant. The second makes sure that .php files are added to the list of file suffixes. With these two lines in your .vimrc, and assuming you&#8217;ve setup your path correctly, placing the cursor in a classname of a fully namespaced class and typing gf should result in the file with that class definition being opened. If you place the cursor in any other part of the namespace name and type gf you should find the directory that maps to that part of the namespace being opened in the netrw plugin. Two quick and easy adjustments to Vim config but that make day to day work much easier.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=1zmsBIZop7o:i_kpjgo5co8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/1zmsBIZop7o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2013/01/13/a-few-vim-tricks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2013/01/13/a-few-vim-tricks/</feedburner:origLink></item>
		<item>
		<title>Continuous Deployment with Symfony2, Jenkins and Capifony</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/ieZwaaLBQms/</link>
		<comments>http://jeremycook.ca/2012/11/04/continuous-deployment-with-symfony2-jenkins-and-capifony/#comments</comments>
		<pubDate>Mon, 05 Nov 2012 02:40:49 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[Continuous Deployment]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Symfony2]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=301</guid>
		<description><![CDATA[It seems that many people talk about setting up a continuous deployment system but few actually take the plunge and make it a reality. I’ve recently set up continuous deployment for an API project at work and thought I would blog about how I got it all to work. The Plan This project is relatively [...]]]></description>
				<content:encoded><![CDATA[<p>It seems that many people talk about setting up a continuous deployment system but few actually take the plunge and make it a reality. I’ve recently set up continuous deployment for an API project at work and thought I would blog about how I got it all to work.</p>
<h2>The Plan</h2>
<p>This project is relatively new and we’d setup the following process for it:</p>
<ol>
<li>We’re using Git and GitHub for the project. Every developer working on it uses a fork of the main repository.</li>
<li>When some work is ready to be merged we send a pull request. Another developer reviews the code before it is merged.</li>
<li>Once code is merged into the main repository GitHub notifies our Jenkins server, which then runs a build on the project. This performs many tasks including lint checking changed files, running our unit and functional test suite, checking that our database is in sync with our entities and performing various metrics against our code base.</li>
</ol>
<p>What we needed is for code to be automatically deployed at the end of a build only if the build succeeds, i.e. all tests are passing, there are no syntax errors and the entities are in sync with the database. Deployments should also be able to be quickly rolled back should anything go wrong with code in production.</p>
<h2>Enter Capifony</h2>
<p>To automate the deployment we chose to work with <a href="http://capifony.org/">Capifony</a>. This is a deployment solution for Symfony 1 and 2 apps that is a series of deployment recipes that is built on top of <a href="http://capifony.org/">Capistrano</a>. This does entail installing Ruby and Ruby Gems on the system from which you want to run the deployment but the advantages it offers outweigh any hassle this may entail. Some of the advantages of using Capifony are:</p>
<ol>
<li>Once your deployment script is defined running a deployment is as simple as changing into the root directory of your project and typing the command ‘cap deploy’.</li>
<li>Capifony stores multiple releases (you get to choose how many, the default is 3) of your project on your server. A symlink called current is created that links to the most recent release. This makes rolling back the project in the event of problems a cinch: to go back to the previous deployment simply type ‘cap deploy:rollback’ from the root directory of your project.</li>
<li>Capifony performs deployments by logging into the production server over SSH. It uses SCM such as Git to pull code down to the server.</li>
<li>Since Capifony connects to the server using SSH it can run any bash commands or symfony console commands that you wish during the deployment.</li>
<li>The deployment is run as a ‘transaction’: if any part of it fails the entire deployment is rolled back and aborted.</li>
</ol>
<p>Capifony adds a number of default tasks that it performs with every deployment. These can easily be extended or overridden in your own deploy.rb script. Capifony can also run any symfony console command on the live server as part of the deployment by using the keyword &#8216;symfony&#8217;. For example, to update the Symfony2 translation file you would simply need to add &#8216;run &#8220;symfony:translation:update&#8221;&#8216; to your deploy.rb file.</p>
<p>Once you have installed capifony you need to cd to the root directory of your project and to run &#8216;capifony .&#8217; in the terminal. This will automatically detect if you&#8217;re working wth a Symfony 1 or 2 application and will create a Capfile in in the root directory as well as creating a  deploy.rb file in the config directory. These need to be added to source control. Once you&#8217;ve setup a basic deployment script run &#8216;cap deploy:setup&#8217; to setup the deployment on the remote server.</p>
<h2>A sample deployment script</h2>
<p>Below is a sample deploy.rb script that I&#8217;m using to deploy a Symfony2 app:</p>
<script src="https://gist.github.com/4055797.js"></script><noscript><pre><code class="language-ruby ruby"># Deployment server info
set :application, &quot;APP NAME&quot;
set :domain,      &quot;APP DOMAIN NAME&quot;
set :deploy_to,   &quot;/path/on/live/server&quot;
set :app_path,    &quot;app&quot;
set :web_path, 	  &quot;web&quot;
set :maintenance_basename, 	&quot;maintenance&quot;

# SCM info
set :repository,  &quot;GIT REMOTE REPO URL&quot;
set :scm,         :git
set :deploy_via,  :remote_cache

set :model_manager, &quot;doctrine&quot;

# Role info. I don't think this is particularly important for Capifony...
role :web,        domain                         # Your HTTP server, Apache/etc
role :app,        domain                         # This may be the same as your `Web` server
role :db,         domain, :primary =&gt; true       # This is where Symfony2 migrations will run

# General config stuff
set :keep_releases,  10
set :shared_files,      [&quot;app/config/parameters.yml&quot;] # This stops us from having to recreate the parameters file on every deploy.
set :shared_children,   [app_path + &quot;/logs&quot;, web_path + &quot;/uploads&quot;, &quot;vendor&quot;]
set :permission_method, :acl
set :use_composer, true

# Confirmations will not be requested from the command line.
set :interactive_mode, false

# The following line tells Capifony to deploy the last Git tag.
# Since Jenkins creates and pushes a tag following a successful build this should always be the last tested version of the code.
set :branch, `git tag`.split(&quot;\n&quot;).last

# User details for the production server
set :user, &quot;deploy&quot;
set :use_sudo, false
ssh_options[:forward_agent] = true
ssh_options[:keys] = [File.join(ENV[&quot;HOME&quot;], &quot;.ssh&quot;, &quot;KEY FILE NAME&quot;)]


# Uncomment this if you need more verbose output from Capifony
#logger.level = Logger::MAX_LEVEL

# Run migrations before warming the cache
before &quot;symfony:cache:warmup&quot;, &quot;symfony:doctrine:migrations:migrate&quot;

# Custom(ised) tasks
namespace :deploy do
	# Apache needs to be restarted to make sure that the APC cache is cleared.
	# This overwrites the :restart task in the parent config which is empty.
	desc &quot;Restart Apache&quot;
	task :restart, :except =&gt; { :no_release =&gt; true }, :roles =&gt; :app do
		run &quot;sudo service apache2 restart&quot;
		puts &quot;--&gt; Apache successfully restarted&quot;.green
	end
end</code></pre></noscript>
<p>A few notes on this:</p>
<ul>
<li>Since Capifony performs actions on the live server it needs a user to log in as to perform actions. I created a user on the server called deploy with the primary group of www-pub and the secondary group of www-data. I then added www-pub as a secondary group to the user www-data that apache runs as. This solved any permission issues that I had.</li>
<li>Setting the option &#8220;set :deploy_via, :remote_cache&#8221; tells capifony to keep a local, cached copy of the repository on the server. This speeds up deployments since only changes to the code base need to be fetched. We needed to install Git on the server to allow this to work and to add a deployment key to our GitHub repo for the deploy user to use when fetching code from Git.</li>
<li>Capifony allows you to share files between deployments. This deployment script shares the parameters.yml file, the log, vendors and uploads directories.</li>
<li>The line &#8220;ssh_options[:keys] = [File.join(ENV["HOME"], &#8220;.ssh&#8221;, &#8220;KEY FILE NAME&#8221;)]&#8221; tells Capifony to use an SSH keyfile with the supplied name. This allows us to register a key on the server for the deploy user.</li>
<li>Since the deploy user needs to access the GitHub repository we needed to add a deployment key for the deploy user to use on GitHub.</li>
<li>The line &#8220;before &#8220;symfony:cache:warmup&#8221;, &#8220;symfony:doctrine:migrations:migrate&#8221;" automatically runs any new doctrine migrations with every deployment. The line &#8220;set :interactive_mode, false&#8221; ensures that Symfony won&#8217;t ask for confirmation when running this command.</li>
<li>The final part of the script overrides the restart method. This is left blank in Capifony (although I think it&#8217;s a standard task in Capistrano Ruby deployments). I needed to restart Apache with every deployment to make sure that the APC cache was cleared since a lot of cached data is stored in APC. The deploy user was given sudo permission only to restart the apache process.</li>
</ul>
<h2>Getting it working with Jenkins</h2>
<p>We elected to have the Capifony deployment set up as a separate job on our Jenkins server rather than having it run as a post build task in our main Jenkins job for the project. The deployment job simply pulls in the latest version of the code from our GitHub repository and performs &#8216;cap deploy&#8217; as a shell command for its single build action. This job is triggered as a downstream job once the main build for our project successfully completes. We chose this configuration for a couple of reasons:</p>
<ul>
<li>This setup gives us a little more freedom to run the deployment job on it&#8217;s own if we ever need to.</li>
<li>If a build or a deployment fails it&#8217;s a little easier for is to see instantly where things have gone wrong.</li>
</ul>
<p>We needed to add an ssh key on the Jenkins server for Jenkins to use when connecting to the live server and to add this to authorized_keys for the deploy user on the server. This setup did give us one other problem though. By default Capifony will deploy the latest commit to a Git repository. If a new commit is made while Jenkins is running a build then Capifony will deploy that, meaning that we could end up with code that has not been through our build process being deployed. Our solution was to have our main Jenkins build tag the repository and to push this tag back to GitHub using  the Git Publisher post build action. This tag is given the same number as the build number in Jenkins for easy identification. As you can see in the deployment script above our Capifony deployment looks for the latest tag in GitHub and deploys this to the live environment. To make sure there are no problems with this process we made sure that Jenkins will only build this project sequentially, not in parallel. This should ensure that the the latest tag in Git is the most recent tested version of the code. Naturally, for the deployment to work Capifony needs to be installed on the Jenkins server.</p>
<p>After setting all of this up I found that it wasn&#8217;t working. I could run &#8216;cap deploy&#8217; from my development environment with it working perfectly, deploying the latest tag from GitHub. When the Jenkins server ran this it failed with a cryptic error about not being able to find the specified tag. I could see the tags being created in GitHub though and spent a couple of frustrating hours trying to work this out. Eventually, I found the problem. It seems that the Jenkins Git plugin creates an internal tag every time a build is run. This is only created on the Jenkins server and not pushed to GitHub. What was happening is that when the Capifony deployment was run on the Jenkins server it connected to the live server and then tried to checkout the tag that was only created on the Jenkins server, resulting in the deployment failing. The solution was to go into the advanced Git config and to make sure that the skip internal tag option is checked. The image below shows the option to check for this.</p>
<p style="text-align: center;"><a href="http://i2.wp.com/jeremycook.ca/wp-content/uploads/2012/11/MRXStats-Config-Jenkins.png"><img class="size-medium wp-image-304 aligncenter" title="MRXStats Config [Jenkins]" src="http://i0.wp.com/jeremycook.ca/wp-content/uploads/2012/11/MRXStats-Config-Jenkins.png?resize=300%2C67" alt="" data-recalc-dims="1" /></a></p>
<h2>Conclusion</h2>
<p>Setting all of this up did take me quite a lot of time, the majority of which was simply due to my needing to learn how to configure and use setup Capifony. As a result of it we have a great continuous deployment setup that works seamlessly. I&#8217;d definitely use Capifony again and am already looking at how we can use it to deploy a couple of legacy Symfony1 apps we have at work. If you have a Symfony app I&#8217;d strongly recommend using Capifony for deployments. If you have a Jenkins server, take it one step further and setup a continuous deployment.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=ieZwaaLBQms:BLxCzC2CBVw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/ieZwaaLBQms" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/11/04/continuous-deployment-with-symfony2-jenkins-and-capifony/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2012/11/04/continuous-deployment-with-symfony2-jenkins-and-capifony/</feedburner:origLink></item>
		<item>
		<title>Turbocharging your Logs</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/RGY7BlISTYU/</link>
		<comments>http://jeremycook.ca/2012/10/02/turbocharging-your-logs/#comments</comments>
		<pubDate>Wed, 03 Oct 2012 02:10:07 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Monolog]]></category>
		<category><![CDATA[PHP 5.3]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=287</guid>
		<description><![CDATA[Logging can be a really powerful tool to help you to keep on top of problems in your applications. However all too often this information is lost amongst multiple log files spread out over many different servers. I’ve recently setup and configured a Graylog 2 server at work and thought I’d write about it and [...]]]></description>
				<content:encoded><![CDATA[<p>Logging can be a really powerful tool to help you to keep on top of problems in your applications. However all too often this information is lost amongst multiple log files spread out over many different servers. I’ve recently setup and configured a Graylog 2 server at work and thought I’d write about it and getting PHP applications to send both application and error messages to the server.</p>
<h2>What is Graylog2?</h2>
<p><a href="http://graylog2.org/">Graylog2</a> is a logging server that can aggregate log messages from multiple sources. It&#8217;s an open source project and you can configure your servers and applications to send all log messages to Graylog for later analysis. Graylog stores them in an Elastic Search database and allows you to perform custom searches on them. You can also see in real time how many log messages are being received and processed. The real killer feature in Graylog is streams. A stream in Graylog is a predefined custom search. The server will display to you log messages that only match the stream criteria selected, graphing the results for you. You can also attach alarms to streams so that if the number of messages recorded for a stream exceeds a certain level over a period of time an email alert can be sent out.</p>
<p>Messages can be sent to Graylog via UDP or AMQP and there are libraries for many languages allowing you to send messages. UDP has the advantage of being quick in that the application does not need to wait for confirmation in the way that it would with TCP. However AMQP allows for log messages to be saved in the event that the Graylog server ever goes down. You can configure your servers to send messages to Graylog via Rsyslog so that even system logs can be aggregated in one place. Getting the server installed and running can be a little time consuming as it uses MongoDb and ElasticSearch for storage, Java for the Graylog server that accepts and stores incoming messages and Ruby on Rails for the web frontend. The best guide to getting all of this going in my opinion can be found at <a href="http://dean.io/posts/getting-started-with-graylog2-for-logging-updated-for-0-9-6">Getting Started with Graylog2 for Logging</a>. I would add two ‘pro tips’ to this from my experience:</p>
<ol>
<li>If you’re using an Amazon EC2 instance to run your Graylog server don’t forget to open ports 514 and 12201 for UDP in the security configuration. Opening 514 allows your Graylog server to receive Rsyslog messages and 12201 is the default port that Graylog receives messages in Gelf (Graylog Extended Log Format) on. If you don’t make sure these ports are open you’ll spend hours like me wondering why your server isn’t receiving messages…</li>
<li>Double check that the disk that ElasticSearch is saving data to has plenty of space. Graylog uses ElasticSearch to store log messages and depending on the volume of messages you’re handling this can mount up pretty quickly. You can configure how long messages are kept for (the default is 30 days) however.</li>
</ol>
<p>Obviously, setting up and maintaining a Graylog server only makes sense if you have multiple servers to manage. Assuming that you do it can be a real godsend. There are libraries in many common languages for sending messages to a Graylog server and the Graylog project maintains a test server for you to try sending messages to (link on their website).</p>
<p>So, you now have a working Graylog server: how do you send messages to it from PHP?</p>
<h2>Introducing Monolog</h2>
<p><a href="https://github.com/Seldaek/monolog">Monolog</a> is a logging library for PHP 5.3 + is well worth checking out. It supports the 8 official logging levels defined in RFC 5424 and allows you to log messages to multiple formats. A Monolog logger has at least one handler attached to it, and handlers are used to process log messages. A handler takes care of recording log messages to different backends such as streams (files), emails or Graylog. When attaching a handler you also specify the log level that handler records, allowing you to specify multiple handlers, each recording a different log level. Handlers come with appropriate message formatters but this can be overridden, allowing you to send emails with JSON embedded data if you wish. Logging a message is as simple as calling a method with a string as the first argument and an optional associative array of extra ‘context’ data as a second argument. Monolog will take care of finding a handler that can handle the message and error level being logged.</p>
<p>Thanks to <a href="https://github.com/mlehner">Matt Lehner</a> Monolog has a handler for Graylog. To log messages to a Graylog server you’ll also need the Gelf-PHP package available from Packagist. Assuming a composer installation of Monolog and Gelf-PHP the following code will write test warning, error, info and debug log messages to your Graylog server on the default Gelf port of 12201:</p>
<script src="https://gist.github.com/3824538.js"></script><noscript><pre><code class="language-php php">&lt;?php

require &quot;vendor/autoload.php&quot;;

use Monolog\Logger;
use Monolog\Handler\GelfHandler;
use Gelf\MessagePublisher;

$log = new Logger('Test');
$log-&gt;pushHandler(new GelfHandler(new MessagePublisher('IP OR DOMAIN NAME OF YOUR GRAYLOG2 SERVER')));

$log-&gt;addWarning('Test warning message');
$log-&gt;addError('Test error message');
$log-&gt;addInfo('Test info message');
$log-&gt;addDebug('Test debug message');
</code></pre></noscript>
<h2>Sending Logging Messages from Applications</h2>
<p>So, how would you go about sending log messages from your applications to Graylog? Symfony2 uses Monolog by default for logging and it’s relatively simple to add the Graylog handler to your application config. This <a href="https://gist.github.com/2479478">Gist</a> gives information on how to do that. Once it’s all configured sending a message to Graylog is as simple as retrieving the logging service from the service container and adding a message.</p>
<p>It’s a little (but not much) harder with applications where a DIC is not available. We have an older application at work that uses Symfony 1.4 that I wanted to add logging for. To do that I ended up adding a class that returns a singleton (evil, I know) instance of Monolog, fully configured to send all messages to our Gelf server. The code for that looks something like this:</p>
<script src="https://gist.github.com/3824561.js"></script><noscript><pre><code class="language-php php">&lt;?php
use Monolog\Logger;
use Monolog\Handler\GelfHandler;
use Gelf\MessagePublisher;

/**
 * Class to configure and return a Monolog instance
 *
 * @author Jeremy Cook
 */
class LoggingHelper
{
    /**
     * Monolog instance to hold and use
     * @var Monolog\Logger
     */
    static protected $instance;

    /**
     * Method to return the Monolog instance
     *
     * @return Monolog\Logger
     */
    static public function getLogger()
    {
        if (! self::$instance) {
            self::configureInstance();
        }

        return self::$instance;
    }

    /**
     * Method to configure the Monolog instance
     *
     * @return void
     */
    static protected function configureInstance()
    {
        self::$instance = new Logger('NAME FOR THIS LOGGER');
        self::$instance-&gt;pushHandler(new GelfHandler(new MessagePublisher('IP OR DOMAIN NAME OF YOUR GRAYLOG2 SERVER')));
        self::$instance-&gt;pushProcessor(function ($record){
            //Need to filter values in auto-globals
            //This is because the gelf-php library will not allow 'extra'
            //values with a key of id to be added
            $filter = function (array $values) use (&amp;$filter) {
                $ret = array();
                foreach ($values as $key =&gt; $value) {
                    if ($key === 'id') {
                        //If the key is id simply continue
                        //NOTE: we should consider how to handle this better.
                        continue;
                    } else if (is_array($value)) {
                        $value = $filter($value);
                    }
                    $ret[$key] = $value;
                }

                return $ret;
            };
            if (count($_SERVER)) {
                $record['extra'] = array_merge($record['extra'], $filter($_SERVER));
            }
            if (count($_GET)) {
                $record['extra'] = array_merge($record['extra'], $filter($_GET));
            }
            if (count($_POST)) {
                $record['extra'] = array_merge($record['extra'], $filter($_POST));
            }
            if (count($_COOKIE)) {
                $record['extra'] = array_merge($record['extra'], $filter($_COOKIE));
            }

            return $record;
        });
    }
}
</code></pre></noscript>
<p>This code also attaches a processor to the Monolog instance that automatically collects all data from $_GET, $_POST, $_COOKIE and $_SERVER and adds it to the context of a log message, helping us to debug problems more easily.</p>
<h2>Logging all PHP Errors to Graylog</h2>
<p>Sending error messages from your application code is likely to only be half of the story though: what about errors from the PHP interpreter itself? We have some legacy code that I work with that produces a lot of errors and warnings and I wanted these recorded in Graylog too to give us a better chance of tracking them down. Luckily PHP allows you to register error handlers, exception handlers and shutdown functions. Using a combination of these I was able to capture all PHP errors and log them to Graylog. To do this I used the logging helper class from above and the following code:</p>
<script src="https://gist.github.com/3824584.js"></script><noscript><pre><code class="language-php php">&lt;?php
/**
 * This file sets up exception and error handlers to log errors to our Graylog2
 * server.
 *
 * @author Jeremy Cook
 */

//Add the autoloader generated by composer for dependencies.
require_once 'path/to/composer/autoload.php';

/**
 * Create a closure to handle uncaught exceptions
 */
set_exception_handler($handler = function(Exception $e) use (&amp;$handler) {
    $message = sprintf(
        'Uncaught exception of type %s thrown in file %s at line %s%s.',
        get_class($e),
        $e-&gt;getFile(),
        $e-&gt;getLine(),
        $e-&gt;getMessage() ? sprintf(' with message &quot;%s&quot;', $e-&gt;getMessage()) : ''
    );
    LoggingHelper::getLogger()-&gt;addError($message, array(
        'Exception file'  =&gt; $e-&gt;getFile(),
        'Exception line'  =&gt; $e-&gt;getLine(),
        'Exception trace' =&gt; $e-&gt;getTraceAsString()
    ));
    /**
     * If there was a previous nested exception call this function recursively
     * to log that too.
     */
    if ($prev = $e-&gt;getPrevious()) {
        $handler($prev);
    }
});

/**
 * Set a custom error handler to make sure that errors are logged to Graylog.
 * Allows any non-fatal errors to be logged to the Graylog2 server.
 */
set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext){
	$message = 'Error of level ';
	switch ($errno) {
		case E_USER_ERROR:
			$message .= 'E_USER_ERROR';
			break;
		case E_USER_WARNING:
			$message .= 'E_USER_WARNING';
			break;
		case E_USER_NOTICE:
			$message .= 'E_USER_NOTICE';
			break;
		case E_STRICT:
			$message .= 'E_STRICT';
			break;
		case E_RECOVERABLE_ERROR:
			$message .= 'E_RECOVERABLE_ERROR';
			break;
		case E_DEPRECATED:
			$message .= 'E_DEPRECATED';
			break;
		case E_USER_DEPRECATED:
			$message .= 'E_USER_DEPRECATED';
			break;
		case E_NOTICE:
			$message .= 'E_NOTICE';
			break;
		case E_WARNING:
			$message .= 'E_WARNING';
			break;
		default:
			$message .= sprintf('Unknown error level, code of %d passed', $errno);
	}
	$message .= sprintf(
		'. Error message was &quot;%s&quot; in file %s at line %d.',
		$errstr,
		$errfile,
		$errline
	);
	LoggingHelper::getLogger()-&gt;addError($message, $errcontext);

	return false;//Returning false will mean that PHP's error handling mechanism will not be bypassed.
});

/**
 * This function will be called before the script exits.
 * This allows us to catch and log any fatal errors in the Graylog2 server.
 * This is needed as the set_error_handler function cannot be used to handle
 * any of the errors in the array below.
 */
register_shutdown_function(function(){
    $codes = array(
        1   =&gt; 'E_ERROR',
        4   =&gt; 'E_PARSE',
        16  =&gt; 'E_CORE_ERROR',
        32  =&gt; 'E_CORE_WARNING',
        64  =&gt; 'E_COMPILE_ERROR',
        128 =&gt; 'E_COMPILE_WARNING'
    );
    $error = error_get_last();
    if (is_array($error) &amp;&amp; array_key_exists($error['type'], $codes)) {
        $message = sprintf(
            'Error of type %s raised in file %s at line %d with message &quot;%s&quot;',
            $codes[$error['type']],
            $error['file'],
            $error['line'],
            $error['message']
        );
        $logger = LoggingHelper::getLogger();
        if (in_array($error['type'], array(32, 128))) {
            //These errors are warnings and should be logged at a lower level.
            $logger-&gt;addError($message);
        } else {
            $logger-&gt;addAlert($message);
        }
    }
});
</code></pre></noscript>
<p>This code is contained in a &#8216;logging.php&#8217; file that is simply included in our index.php file for our application.</p>
<h2>Don’t let the Gorillas put you off…</h2>
<p>I really like Graylog2, despite the abundance of pink and Gorillas in the UI design. It’s a very useful application and is something that we’re going to be making increasing use of at work over the next year or two.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=RGY7BlISTYU:SJhGobAhylY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/RGY7BlISTYU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/10/02/turbocharging-your-logs/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2012/10/02/turbocharging-your-logs/</feedburner:origLink></item>
		<item>
		<title>Normalising DateTimes with Doctrine Events</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/fPmiLxG6jvM/</link>
		<comments>http://jeremycook.ca/2012/06/24/normalising-datetimes-with-doctrine-events/#comments</comments>
		<pubDate>Mon, 25 Jun 2012 03:21:30 +0000</pubDate>
		<dc:creator>Jeremy Cook</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony2]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://jeremycook.ca/?p=274</guid>
		<description><![CDATA[Two of the biggest pains in development for me are character encoding and working with date time information. The former continually bites me when I least expect it, although making sure everything in a project is UTF-8 encoded seems to go a long way to mitigating this problem. Working with date time information is also [...]]]></description>
				<content:encoded><![CDATA[<p>Two of the biggest pains in development for me are character encoding and working with date time information. The former continually bites me when I least expect it, although making sure everything in a project is UTF-8 encoded seems to go a long way to mitigating this problem. Working with date time information is also subtly tricky. I&#8217;ve recently been working on an app that stores a lot of information about sports statistics. Part of this involves storing information on when a game , trades on players, etc took place. Since this information can be entered in any number of different timezones I thought I would write about the approach that we took to normalise the data as it is inserted into the database.</p>
<h2>The Problem</h2>
<p>In collecting data for the application we are getting a lot of date time information that can be entered in multiple timezones. When the information is retrieved we allow the user to select the timezone that they want to view the data in. We quickly decided that the only way to go was to store all date time information in the UTC timezone but we still needed a way to seamlessly convert date time data into that timezone when it is saved. The project is being built using a combination of Symfony2 and Doctrine2. We discovered that Doctrine will always populate DateTime objects for entities with a timezone that matches the default timezone set on the server when entities are hydrated. Solving half of the problem just involved making sure that UTC was set as the default server timezone. The <a href="http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html#handling-different-timezones-with-the-datetime-type">advice of the Doctrine</a> project is to convert instances of DateTime to use UTC before they are persisted in the database and to store the timezone information separately and we wanted to find a way to do this that was as simple and maintainable as possible.</p>
<h2>Potential Solutions</h2>
<p>The first solution we considered was to perform the timezone conversions at the entity level but we quickly abandoned this idea for a number of reasons. Firstly, this would involve a huge amount of code duplication. Every setter in every entity that dealt with DateTime objects would need to perform a conversion on DateTime instances that are saved. This would either involve lot of duplicated code or some complicated inheritance structure. Worse, if a developer created an entity that didn&#8217;t implement this behavior we could quickly find that we had corrupted data in the database.</p>
<p>The second solution we considered was an extension of the first. Doctrine allows you to define a series of lifecycle callbacks on entities that can be fired when certain events take place. We thought about adding PrePersist and PreUpdate callbacks that would perform the timezone conversion automatically whenever an entity is saved or updated by the entity manager. However this solution suffers from the same problems as the one above in that it requires code duplication and/or inheritance. It would also mean that developers would need to remember to add this behavior to all entities that need to work with DateTimes, leading to problems if this is forgotten.</p>
<p>The next solution we considered was possibly the worst. We thought about enforcing the timezone changes at the application level, before the entities were ever given to the entity manager. This was very quickly discarded due to the obvious code bloat and possibilities for duplication that exist.</p>
<h2>The Solution</h2>
<p>The solution we hit on was to leverage <a href="http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#listening-to-lifecycle-events">Doctrine&#8217;s system of event listeners</a> to help us do the work. Doctrine allows you to register listeners with the entity manager that are called whenever certain events occur. We created an event listener that is triggered on the onFlush event. This collects all entities that are scheduled for insertion or update and uses Reflection to iterate over their private and protected properties looking for DateTime objects. Any that are found have their timezones set to UTC. The code for the event listener class is below:</p>
<pre class="brush: php; title: ; notranslate">

&lt;?php
namespace Events\Doctrine;

use ReflectionObject;
use ReflectionProperty;
use DateTime;
use DateTimeZone;
use Doctrine\ORM\Event\OnFlushEventArgs;
/**
* Class to provide an event listener that processes entities when they are persisted or updated
*/
class DateTimeListener
{
/**
* Method to listen to the onFlush event
* When this event is triggered the method will look at all entities
* scheduled for update or insertion.
* It will retrieve all DateTime instance from these and ensure they are
* set to UTC timezone
* @param Doctrine\ORM\EventListener\OnFlushEventArgs $args
*
* @return void
*/
public function onFlush(OnFlushEventArgs $args)
{
    $zone = new DateTimeZone('UTC');
    //Get hold of the unit of work.
    $entityManager = $args-&gt;getEntityManager();
    $unitOfWork = $entityManager-&gt;getUnitOfWork();
    //Get hold of the entities that are scheduled for insertion or update
    $entities = array_merge($unitOfWork-&gt;getScheduledEntityInsertions(), $unitOfWork-&gt;getScheduledEntityUpdates());
    foreach ($entities as $entity) {
        $reflect = new ReflectionObject($entity);
        foreach ($reflect-&gt;getProperties(ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED) as $prop) {
            $prop-&gt;setAccessible(true);
            $value = $prop-&gt;getValue($entity);
            if (! $value instanceof DateTime || $value-&gt;getTimezone()-&gt;getName() === 'UTC') {
                $prop-&gt;setAccessible(false);
                continue;
            }
            $value-&gt;setTimezone($zone);
            $prop-&gt;setValue($entity, $value);
            $prop-&gt;setAccessible(false);
            $unitOfWork-&gt;recomputeSingleEntityChangeSet($entityManager-&gt;getClassMetadata(get_class($entity)), $entity);
        }
    }
}
}
</pre>
<p>What I like about this solution is that it doesn&#8217;t require any intervention on the part of the developer higher up in the application. Entities are simply created or edited and no special attention needs to be paid to time zones saved in DateTime instances. However, this solution isn&#8217;t without it&#8217;s own issues. Firstly, the fact that this is done by the entity manager at the event level gives the whole thing a touch of &#8216;magic&#8217;. We&#8217;ll need to make sure this is well documented so that developers working on this code in the future don&#8217;t end up spending time trying to work out how this behavior is happening. Secondly, using Reflection and iterating over every property of every entity that is being saved or updated isn&#8217;t the fastest thing in the world to do. At this stage I&#8217;m not too concerned as, like most systems, there will be many more read than write operations in this application. If this does become a problem we could possibly introduce some sort of class map that we could use to decide which entities have DateTime instances in them that we might need to modify. It&#8217;s possible that the class meta data, held by the entity manager, would be able to give us this information. For now I&#8217;m quite happy with this solution and with the event system in Doctrine in general. We&#8217;ve also used Doctrine events to automatically calculate some statistics data for us when entities are flushed but that&#8217;s a topic for another post.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=fPmiLxG6jvM:mml4vJ7z2ow:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/fPmiLxG6jvM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/06/24/normalising-datetimes-with-doctrine-events/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2012/06/24/normalising-datetimes-with-doctrine-events/</feedburner:origLink></item>
		<item>
		<title>Implementing IteratorAggregate and Iterator</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/ry_32LFXcLs/</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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=ry_32LFXcLs:k2UEEk7CSFU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/ry_32LFXcLs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/05/06/implementing-iteratoraggregate-and-iterator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2012/05/06/implementing-iteratoraggregate-and-iterator/</feedburner:origLink></item>
		<item>
		<title>Making PHPUnit, Doctrine &amp; MySQL Play Nicely</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/g0_lchtCx68/</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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=g0_lchtCx68:sJn_fRs47LE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/g0_lchtCx68" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/02/27/making-phpunit-doctrine-mysql-play-nicely/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2012/02/27/making-phpunit-doctrine-mysql-play-nicely/</feedburner:origLink></item>
		<item>
		<title>Implementing the ArrayAccess Interface</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/n3kXq_YZ9wI/</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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=n3kXq_YZ9wI:Mag_iXygHo0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/n3kXq_YZ9wI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/01/22/implementing-the-arrayaccess-interface/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2012/01/22/implementing-the-arrayaccess-interface/</feedburner:origLink></item>
		<item>
		<title>Using the Countable Interface</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/LONoIrGocMc/</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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=LONoIrGocMc:N4CT3XKyzqg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/LONoIrGocMc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2012/01/01/using-the-countable-interface/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2012/01/01/using-the-countable-interface/</feedburner:origLink></item>
		<item>
		<title>Using SalesNet Web Services from PHP</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/I50oNEBPSqI/</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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=I50oNEBPSqI:dmJ4lmYQzcM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/I50oNEBPSqI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremycook.ca/2011/12/06/using-salesnet-web-services-from-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2011/12/06/using-salesnet-web-services-from-php/</feedburner:origLink></item>
		<item>
		<title>Zend_Form and Validating Values for Multiple Column DB Keys</title>
		<link>http://feedproxy.google.com/~r/JeremyCook/~3/9GbFhYI1XWA/</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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/JeremyCook?a=9GbFhYI1XWA:7QAT-22tUkY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/JeremyCook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/JeremyCook/~4/9GbFhYI1XWA" height="1" width="1"/>]]></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>5</slash:comments>
		<feedburner:origLink>http://jeremycook.ca/2011/10/25/zend_form-and-validating-values-for-multiple-column-db-keys/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 2.400 seconds. --><!-- Cached page generated by WP-Super-Cache on 2013-05-22 13:47:36 --><!-- Compression = gzip -->
