<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title><![CDATA[Content with Style]]></title>
    <link>http://www.contentwithstyle.co.uk/feeds/rss</link>
    <description><![CDATA[]]></description>
    <pubDate>Mon, 25 May 2009 08:30:55 +0000</pubDate>
    <generator>Zend_Feed</generator>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <item>
      <title><![CDATA[Getting phpunit to work with MAMP]]></title>
      <link>http://www.contentwithstyle.co.uk/content/getting-phpunit-to-work-with-mamp</link>
      <guid>http://www.contentwithstyle.co.uk/content/getting-phpunit-to-work-with-mamp</guid>
      <description><![CDATA[<p>In order to run my unit tests, I needed to get phpunit running with MAMP. Thanks to the <a href="http://mark-kirby.co.uk/2009/installing-phpunit-with-mamp/">helpful post of Mark Kirby</a> on this, I figured it out.</p>]]></description>
      <content:encoded><![CDATA[<p>In order to run my unit tests, I needed to get phpunit running with MAMP. Thanks to the <a href="http://mark-kirby.co.uk/2009/installing-phpunit-with-mamp/">helpful post of Mark Kirby</a> on this, I figured it out.</p>

<ol>
<li>cd into your PEAR installation directory</li>
<li>Make backup of phpunit file in bin folder</li>
<li>Edit the original file, replace #!/usr/bin/php with #!/Applications/MAMP/bin/php5/bin/php</li> 
<li>3. Also remove this:
<pre><code>
if (strpos('/usr/bin/php', '@php_bin') === 0) {
    set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path());
}
</code></pre></li>
<li>And finally, something that Mark didn't mention, add PEAR include path into /Applications/MAMP/conf/php5/pear.conf</li>
</ol>]]></content:encoded>
      <pubDate>Wed, 13 May 2009 11:41:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Deploying PHP applications with Vlad and SVN]]></title>
      <link>http://www.contentwithstyle.co.uk/content/deploying-php-applications-with-vlad</link>
      <guid>http://www.contentwithstyle.co.uk/content/deploying-php-applications-with-vlad</guid>
      <description><![CDATA[A detailed post explaining the first steps to get Vlad the Deployer working for your PHP application.]]></description>
      <content:encoded><![CDATA[<p>In my current day job I have to deploy a number of web apps every few weeks. 
The person I took over from did the whole thing in a manual and terribly cumbersome way:</p>
<ul>
	<li>exporting the project locally,</li>
	<li>zipping it up,</li>
	<li>moving it to the server,</li>
	<li>unpacking and symlinking it, to finally</li>
	<li>run a small script that would set the correct production config, chmod log and cache folders etc.</li>
</ul>
<p>In the following article, I'm going to describe how I went from there to deploying my Zend Framework-driven PHP apps with Vlad. To save yourself some time, feel free to <a href="#ruby-setup">skip the back story</a>, the <a href="#pre-configure" title="skip installing ruby, gem and rake">pre-requisite of installing ruby, gem and rake</a>, or <a href="#deployment-recipes">go straight to the deployment recipes</a>.</p>

<p id="backstory">I did the above method for a while, and realized quickly how much time is wasted by this process. Remembering my efforts of <a href="http://www.contentwithstyle.co.uk/content/php-deployment-with-capistrano">deploying PHP apps with Capistrano</a>, I felt
it was time to set up an automated deployment routine. While re-reading the article, thoughts returned of how unwieldy and badly documented Capistrano came across,
and I started looking for something more lean, that wouldn't scare of my non-ruby colleagues who might have to do my job when I'm away.</p>

<p>Very quickly I was lead to <a href="http://rubyhitsquad.com/Vlad_the_Deployer.html">Vlad the Deployer</a>, replacing one deployment app where the person in charge of the name had one tipsy field day with, well, another.</p>

<p>Taking it for its first spin, I felt that while there's a lot of confidence behind Vlad, the word "simple" crops up lots of times, but again, 
the documentation is a bit of a thinking man's manual; As soon as you go beyond the initial example it skips a few steps here and there, 
which can leave someone who is unfamiliar with the concept struggling. Maybe it's a case of "it's advanced stuff, just live with it". </p>

<p>Luckily I have my Capistrano experience, so I got started fairly quickly using Vlad for my own purposes. What I liked immediately about Vlad was that it declares as one of the project goals to "use the right tool for the job (ssh, rsync, etc)."</p>

<p id="vlad-goals">My initial goal was to use Vlad</p>
<ul>
	<li>to have a deployment one-liner,</li>
	<li>to roll back if needed, and</li>
	<li>to be able to share logs and other assets between releases</li>
</ul>

<p id="example-app">For the example below I created a demo Zend Framework application with <a href="http://devzone.zend.com/article/4559-Zend_Tool-and-ZF-1.8">Zend_Tool</a>, 
but what I'm describing should work for any PHP app out of the box, actually for any app, if you add any potential server tasks yourself.
This example is using Subversion, but there is other examples out there that'll tell you how to use it with Git and other SCM software.
</p>

<h2 id="ruby-setup">Setup</h2>

<p>To be able to deploy with Vlad you need to have the following 4 things set up:</p>

<h3>1. unix/linux development platform with SVN</h3>
<p>not much to add, Vlad works on Mac OS X and various linux flavours, but not under Windows. For this setup I'm assuming you're working with SVN.</p>

<h3>2. server with SVN client</h3>
<p>Your webserver should be able to work with SVN, and it should be able to reach your SVN repository.</p>

<h3>3. install vlad dependencies</h3>
<p>on OS X 10.5 you already have a rails installation coming with the developer tools; just do</p>
<pre><code>% gem update rails</code></pre>

<p>Alternatively and on earlier OS X, you can use MacPorts, to install Ruby with</p>
<pre><code>% port install ruby</code></pre>

<p>You might also be able to use fink, and on debian/ubuntu you can install via aptitude</p>
<pre><code>
% sudo apt-get install ruby
% sudo apt-get install rubygems</code></pre>

<p>For other platforms and compiling from source see here:<br/>
<a href="http://www.ruby-lang.org/en/downloads/">http://www.ruby-lang.org/en/downloads</a></p>

<p>Next you need to install Rake. For all systems, to update gem and install Rake, do the following. You don't need to <code>gem update</code> if you started from scratch:</p>
<pre><code>
% gem update --system
% gem update</code></pre>

<p>
<a href="http://www.virtualmin.com/index.php?option=com_flyspray&Itemid=82&do=details&task_id=4901&Itemid=82&project=1&pagenum=4">Gem may fail initially</a> - if so this is due to a bug in the gem command and requires you to edit the gem script (found with the command <code>which gem</code> on the command line, it's probably in <code>/usr/bin/gem</code>) by adding to the require statements (under <code>require 'rubygems'</code>):</p>
<pre><code>
require 'rubygems/gem_runner'
</code></pre>

<p>And finally, to install Rake itself:</p>
<pre><code>% gem install rake</code></pre>

<p>There are 3 more dependencies,</p> 
<ul>
<li>Hoe</li>
<li>Rubyforge</li>
<li>open4</li></ul>

<p>but they're installed automatically with the next step.</p>

<h3>4. install vlad as a gem</h3>
<p>To install vlad as a gem, all you need to do is</p>
<pre><code>% sudo gem install vlad</code></pre>

<p>while allowing for dependencies to be installed, which is set by default. Congratulations, you're ready to configure Vlad.</p>

<h2 id="pre-configure">Pre-Configure</h2>

<p>As Vlad is working closely with your system tools, you should set up your SSH for it first. You need to make sure the remote user is set up correctly, and you'll want some way of not having to enter your password a million times. Luckily <a href="http://www.contentwithstyle.co.uk/content/4-ssh-config-tips-for-faster-remote-working" title="4 ssh config tips for faster remote working">I wrote about this recently</a>. For the server I'd like to deploy to I added this. You might not need the ControlMaster/ControlPath, the important line is to set the remote user:</p>
<pre><code>
Host myserver.pretendco.com
    ControlMaster auto
    ControlPath ~/.ssh/master-%r@%h:%p
    User remoteuser
</code></pre>

<p>Now let's have a look at the server itself. There is a possibility that the web directory isn't writable by your remote user and you need to have root permissions. As you should use the root user for all this, and sudo croaks on remote commands, it's best to set your future releases directory to be owned by your remote user.</p>

<p>on the remote machine</p>
<pre><code>
% sudo chown remoteuser:remotegroup /path/to/releases/directory
% chmod 775 /path/to/releases/directory
</code></pre>

<h2>Configure and Deploy</h2>

<p>Next you need to create 2 files for Vlad: A Rakefile in your root directory, and a deploy.rb config file in application/configs. Your project should look a little something like this (yes, this is slightly abbreviated):</p>

<pre> |-application
 |---configs
 |-----config.ini
 |-----deploy.rb  &lt;-- just created
 |---controllers
 |---models
 |---views
 |-library
 |-public
 |-Rakefile     &lt;-- just created
</pre>

<p id="deployment-recipes">At its core, the Rakefile is very straight forward; I've lifted the initial loading step more or less from the Vlad documentation, with the exception of setting the path for deploy.rb manually. Should your application have a root folder <code>/config</code>, you're following default convention and won't need the instructions in the curly braces. Further down I'm resetting the <code>:update_symlinks</code> task to link to shared logs and media folders, as well as linking the Zend library into my library. By default Vlad would set 3 shared folders: /log, /system and /pids, which I am all omitting here.</p>
<pre><code>
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'

begin
  require 'vlad'
  Vlad.load {:config => 'application/configs/deploy.rb'} # set path for deploy.rb
rescue LoadError
  # do nothing
end

namespace :vlad do
  # Clear existing symlink task so that we can redefine.
  Rake.clear_tasks('vlad:update_symlinks')

  # we've only got log to share
  remote_task :update_symlinks, :roles => :app do
    run "rm -Rf #{latest_release}/log && ln -s #{shared_path}/log #{latest_release}/log && chmod -f 666 #{latest_release}/log/*"
    run "rm -Rf #{latest_release}/public/media && ln -s #{shared_path}/cache #{latest_release}/public/media"
    run "rm -Rf #{latest_release}/library/Zend && ln -s #{shared_path}/Zend #{latest_release}/library/Zend"
  end
end
</code></pre>

<p>Next up is deploy.rb, the config file for the to-be-deployed app. The only 3 mandatory lines in all cases are <code>:domain</code>, <code>:deploy_to</code>, and <code>:repository</code>.</p>
<pre><code>
set :application, "Example application"
set :domain, "pretendco.com"
set :deploy_to, "/project/example_releases"
set :repository, 'http://svn.pretendco.com/example/trunk'
set :svn_cmd, 'svn --username svnuser --password svnpwd'
</code></pre>
<p>The default SVN command is <code>svn</code>, but in my case the SVN user is different to local and remote user, and for some reason the SVN password prompt from within the deployment step kept failing on me, so I added it right here. Not the safest thing in the world, but I'm using a limited read-only SVN user for these purposes, so that's good enough for me. Any suggestions of improvement are welcome.</p>
<p>For your convenience I have zipped up <a href="http://www.contentwithstyle.co.uk/resources/vlad-config.zip">both files</a>, or if you like, the <a href="http://www.contentwithstyle.co.uk/resources/vlad-example.zip">whole demo project</a>.</p>
<p>The first time you run vlad, you do</p>
<pre><code>
% rake vlad:setup vlad:update
</code></pre>
<p>You can skip the additional <code>vlad:migrate vlad:start</code> mentioned in the <a href="http://hitsquad.rubyforge.org/vlad/doco/getting_started_txt.html">vlad documentation</a>, as we're neither migrating DBs (this time), nor does Apache need to be restarted.</p>
<p><code>vlad:setup</code> has now created a folder structure on your server that looks like this (abbreviated again):</p>
<pre> |-project
 |---example_releases
 |-----current           &lt;-- link to your web application
 |-----releases
 |-------yyyymmddhhiiss  &lt;-- your web application
 |---------application
 |---------library
 |-----------Zend        &lt;-- link to Zend Framework
 |---------log           &lt;-- link to shared logs
 |---------public
 |-----------media       &lt;-- link to shared media
 |-----revisions.log
 |-----scm               &lt;-- folder used to checkout release
 |-----shared
 |-------log
 |-------media
 |-------Zend
</pre>
<p><code>vlad:update</code> has exported your application from the HEAD of your SVN repository, pushed it into a release folder, and pointed <code>/current</code> to this release. This means once you've verified this initial deployment step you can set your Apache webroot to point to <code>/project/example_releases/current</code>. You can also see that the folders <code>/log</code>, <code>/public/media</code> and <code>/library/Zend</code> have been symlinked, so you'll want to move all your dynamically created files into the shared folder now.</p>
<p>As a side note, I've had two major criticisms about this, out of which I have fixed one in this example: The first one was that initially I didn't include Zend Framework in my release, but rather added it to the global include_path on the server. "Your applications should be self-contained!", Pascal was shouting from his desk, including some expletives. The other thing he flagged up was that the version of my application config checked into SVN was set up for the live environment, so that I didn't have to change a thing when deploying. I have fixed this in the meantime as well, with a set of other convenient changes, but you'll have to be patient for me to write my next post about it and stick with this solution for now.</p>
<p id="finish-line">The good news are that you're ready to go now!
To release a new version:</p>
<ul>
	<li>check in your changes into SVN</li>
	<li>make sure that the repository URL in deploy.rb points to the same as yours</li>
	<li>run <code>% rake vlad:update</code> to deploy your app</li>
	<li>put your feet up, and enjoy the rest of your day.</li>
</ul>
<p>If your release is broken, roll back with</p>
<pre><code>% rake vlad:rollback</code></pre>
<p>This will remove the last release and symlink to the previous version.</p>
<p>As a final word of warning: Using any means of deployment that rely on your code versioning software mean that you have to keep it clean. Only check in code you've tested locally, don't use the branch you deploy from as a backup mechanism. If you and any other people working with your code follow this advice, Vlad will save you lots of time, and turn the pain of updating a site into the joy of releasing something new.</p>]]></content:encoded>
      <pubDate>Fri, 08 May 2009 14:12:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[DOMDocument loadXML throws errors: A bug?]]></title>
      <link>http://www.contentwithstyle.co.uk/content/domdocument-loadxml-throws-errors-a-bug-not-a-feature</link>
      <guid>http://www.contentwithstyle.co.uk/content/domdocument-loadxml-throws-errors-a-bug-not-a-feature</guid>
      <description><![CDATA[<p>So I was wondering why loadXML gives me parsing errors, despite a big try and catch around it ... <a href="http://php.filearena.net/manual/kr/function.dom-domdocument-loadxml.php#69295">it's not a bug they say</a>.</p>]]></description>
      <content:encoded><![CDATA[<p>So I was wondering why loadXML gives me parsing errors, despite a big try and catch around it ... <a href="http://php.filearena.net/manual/kr/function.dom-domdocument-loadxml.php#69295">it's not a bug they say</a>.</p>

<p>
Gavin Sinai put up a code snippet in the PHP.net reference, which shows how to set the error handler to get rid of it: 
</p>

<pre><code>
&lt;?php
function HandleXmlError($errno, $errstr, $errfile, $errline)
{
   if ($errno==E_WARNING &amp;&amp; (substr_count($errstr,"DOMDocument::loadXML()")&gt;0))
   {
       throw new DOMException($errstr);
   }
   else
       return false;
}

function XmlLoader($strXml)
{
   set_error_handler('HandleXmlError');
   $dom = new DOMDocument();
   $dom-&gt;loadXml($strXml);   
   restore_error_handler();
   return $dom;
 }

?&gt;
</code></pre>]]></content:encoded>
      <pubDate>Wed, 22 Apr 2009 16:37:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Unit testing web service based models in Zend Framework]]></title>
      <link>http://www.contentwithstyle.co.uk/content/unit-testing-web-service-based-models-in-zend-framework</link>
      <guid>http://www.contentwithstyle.co.uk/content/unit-testing-web-service-based-models-in-zend-framework</guid>
      <description><![CDATA[<p>Web applications nowadays use an increasingly distributed set of resources. How do we test our MVC applications that use web services in their models?</p>]]></description>
      <content:encoded><![CDATA[<p>Web applications nowadays use an increasingly distributed set of resources. How do we test our MVC applications that use web services in their models?</p>

<h2>What is the problem?</h2>

<p>Unit tests for database driven models are relatively straight forward. Usually we connect to a separate database, containing a known set of data. Since we know the data we can run assertions against it.</p>

<p>However, unit testing models that talk to web services presents us with a different set of problem. Usually our application runs requests against something that is not in our control. Unless the service provider gives us some kind of test mode, we're operating with dynamic live data which shouldn't be used for testing, since it's harder to test in the first place, but also could be harmful to be manipulated.</p>

<p>Let's have a look at two strategies to test out models.</p>

<h2>Mock objects for Services</h2>

<p>If we are using an object to represent the API calls to the service from within our model, i.e. <a href="http://framework.zend.com/manual/en/zend.service.delicious.html">Zend_Service_Delicious</a>, we can swap this object for a mock object. A simple accessor allows us to overwrite private properties of the object:</p> 

<pre><code>
class DeliciousModel {
  private $delicious;

  public function __construct() {
    $this-&gt;delicious = new Zend_Service_Delicious('username', 'password');
  }

  public function getPosts() {
    return $this-&gt;delicious-&gt;getAllPosts();
  }

  public function setProperty($name, $value) {
    if(UNITTEST_CONTEXT) {
      $this-&gt;$name = $value;
    }
  }
}
</code></pre>

<p>Now it's easy swap out private properties from within a unit test:</p>

<pre><code>
public function testDeliciousModel {
  $mockPosts = array('foo', 'bar');    

  $deliciousMock = $this-&gt;getMock('Zend_Service_Delicious', array('getAllPosts'));
  $deliciousMock-&gt;expects($this-&gt;once())
          -&gt;method('getAllPosts')
          -&gt;will($this-&gt;returnValue($mockPosts));
  
  $model = new DeliciousModel();
  $model-&gt;setProperty('delicious', $deliciousMock);

  $posts = $model-&gt;getPosts();
  $this-&gt;assertEquals($posts, $mockPosts);
}
</code></pre>

<p>
Of course this would mean that we're not launching any requests to our services at all, but instead check that models are doing the right method calls to the service API object, and get the right data back.
</p>

<h2>Validate service requests</h2>

<p>
Generally speaking, models that are using web services will transform method calls into HTTP requests against web service end points. Those might come in a variety of flavours, but all together we can say that, if we can intercept the request, we can make sure the model serializes method calls correctly into known request data.
</p>

<h3>Test adapter for Zend_HTTP calls</h3>

<p>If our model uses Zend_Http to launch the API calls, we might provide a hook in the model so that we can swap the HTTP adapter for the <a href="http://framework.zend.com/manual/en/zend.http.client.adapters.html#zend.http.client.adapters.test">test adapter</a> that ships with Zend Framework. We then have access to the entire request that the model launched, which we can use for assertions:</p>

<pre><code>
public function testJsonCall() {
  $adapter = new Zend_Http_Client_Adapter_Test();

  $response = "";
  $response .= "HTTP/1.1 200 OK" . "\r\n";
  $response .= "Content-type: application/json" . "\r\n";
  $response .= "\r\n";
  $response .= '{}';

  $adapter-&gt;setResponse($response);

  $model = new JsonModel();
  $model-&gt;setAdapter($this-&gt;adapter);

  $request_raw = $model-&gt;http_client-&gt;getLastRequest();
  // do your assertions here
}
</code></pre>

<h3>Swap the endpoint</h3>

<p>
Instead of changing the adapter to intercept the call, we could swap the endpoint of the web service against a mock service. This endpoint then can respond with known data which we can use for our assertions.
</p>

<p>Depending on what kind of web services we have to mock, we might use the servers provided by Zend, e.g. <a href="http://framework.zend.com/manual/en/zend.rest.server.html">Zend_Rest_Server</a> or <a href="http://framework.zend.com/manual/en/zend.soap.html#zend.soap.server">Zend_Soap_Server</a>.
</p>

<h2>A better understanding</h2>

<p>Looking at the two strategies above, it still might seem to be a hassle to do, what is essentially a replication of the web service functionality with test data, whether that happens as mock object, on the request/response level, or as test endpoint.</p>

<p>But instead, this exercise is a very <em>valuable documentation of ones understanding of the service functionality</em> at a particular point in time. Given that service APIs are often in a constant state of change, things might break in the future, but the tests we've written can help us understand whether it's down to our own code or the web service instead. If things fail at the web service level, we can now refer to our tests to compare what we expect the service to do with what it actually does.</p>

<h2>Related Links</h2>

<ul>
<li><a href="http://www.pointbeing.net/weblog/2009/04/unit-testing-code-which-consumes-soap-services.html">Unit Testing Code which Consumes SOAP Services</a></li>
<li><a href="http://www.soapui.org/gettingstarted/mocking.html">Mocking with SoapUI</a></li>
<li><a href="http://www.codeguru.com/columns/vb/article.php/c15209">Unit Testing with Stubs or Mocks</a></li>
</ul>]]></content:encoded>
      <pubDate>Mon, 20 Apr 2009 08:37:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[4 ssh config tips for faster remote working]]></title>
      <link>http://www.contentwithstyle.co.uk/content/4-ssh-config-tips-for-faster-remote-working</link>
      <guid>http://www.contentwithstyle.co.uk/content/4-ssh-config-tips-for-faster-remote-working</guid>
      <description><![CDATA[<p>If your ssh experience was so far limited to typing your username and password lots of times, this post is for you.</p>]]></description>
      <content:encoded><![CDATA[<p>With the vast majority of web developers deploying their own code, and ssh playing a central role in the toolbox, I felt that tweaking this part of my work saves me some time, and if not, definitely some frustration over mistyping passwords and host names.</p>
<p>So, for myself as much as everyone out there, here is my collected useful knowledge that has helped me ease the pain of remote work.</p>
		<h3>1. Execute commands remotely as one-liners</h3>
		<p>This is what some deployment tools such as <a href="http://rubyhitsquad.com/Vlad_the_Deployer.html">vlad</a> use, but for a quick look at something, it cuts out valuable seconds you could look at web comics instead.</p>

		<p>Let's try a simple example:</p>
		<pre><code>
matthias:~ matthias$ ssh remoteuser@myserver.pretendco.com ls -l
remoteuser@myserver.pretendco.com's password: 
total 804
lrwxrwxrwx   1 remoteuser remoteuser      31 Nov 10  2007 access-logs -> /links/to/my/access-logs
drwxr-xr-x   2 remoteuser remoteuser    2048 Apr  6  2008 cgi-bin
-rw-r--r--   1 remoteuser remoteuser  808417 Jul 17  2007 error_log_dump
drwxr-x---   3 remoteuser mail     2048 Oct  1  2007 etc
drwxrwx---   7 remoteuser remoteuser    2048 Apr  4 02:33 mail
drwxr-x---   3 remoteuser remoteuser    2048 May 23  2008 public_ftp
drwxr-x---  30 remoteuser nobody   2048 Dec  4 06:33 public_html
drwxr-xr-x   7 remoteuser remoteuser    2048 Sep 24  2008 tmp
lrwxrwxrwx   1 remoteuser remoteuser      11 Apr  1  2006 www -> public_html
matthias:~ matthias$
		</code></pre>
		
		<p>You can even <a href="http://lookherefirst.wordpress.com/2007/11/29/executing-command-remotely-via-ssh/">pipe through to a remote command</a>. Here's an example taken from Look Here First, where the content of a local file is concatenated to a remote file.</p>
		<pre><code>
matthias:~ matthias$ cat localfile.txt | ssh remoteuser@myserver.pretendco.com "cat - >> remotefile.txt"
		</code></pre>

		<h3>2. Add your public key to your remote server</h3>
		<p>Next let's see how we can get around typing our password all the time. One way of doing this is to <a href="http://sial.org/howto/openssh/publickey-auth/" title="OpenSSH Public Key Authentication">add your public key to your remote server</a>.</p>
		<pre><code>
# first, upload public key from client to server
client$ scp ~/.ssh/id_rsa.pub remoteuser@myserver.pretendco.com:~

# next, setup the public key on server
server$ mkdir ~/.ssh
server$ chmod 700 ~/.ssh
server$ cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
server$ chmod 600 ~/.ssh/authorized_keys
server$ rm ~/id_rsa.pub
		</code></pre>
		<p>Of course, we can combine with the previous example and run it like this:</p>
		<pre><code>
matthias:~ matthias$ cat ~/.ssh/id_dsa.pub | ssh remoteuser@myserver.pretendco.com "cat - >> ~/.ssh/authorized_keys2"
		</code></pre>
		<p>Windows users fear not, <a href="http://www.aota.net/Telnet/puttykeyauth.php4" title="Key Authentication with PuTTY">you can do this too</a>, with PuTTY and PuTTYgen.</p>

		<h3>3. Let the ControlMaster handle your sessions</h3>
		<p>Sadly this might not always possible, maybe your key management on your server is different, or you don't have permissions to the file.</p>
		<p>Luckily you can get around this by <a href="http://blog.zenlinux.com/?p=270">letting your first ssh connection act as ControlMaster</a>. By adding the following to ~/.ssh/config, you only need to enter your password once, and all parallel sessions won't ask for a password</p>
		<pre><code>
Host *
    ControlMaster auto
    ControlPath ~/.ssh/master-%r@%h:%p
		</code></pre>

		<h3>4. Set your user and hostname for your host</h3>
		<p>Finally, more often than not your username won't be the same on your local machine and on whatever server you'd like to connect to, or your server might not use the default ssh port. Or maybe you're just tired of typing that superlong domain name, and look for a less challenging typing task. ~/.ssh/config to the rescue.</p>
		<p>As final example:</p>
		<pre><code>
Host myserver
    User remoteuser
    Port 22022
    HostName myserver.pretendco.com
		</code></pre>
		<p>Most likely you won't need the Port instruction in there, because your server runs ssh on the default port 22, so just drop the line.</p>
<p>All this allows us something as compact as:</p>
<pre><code>
matthias:~ matthias$ ssh myserver mycommand
</code></pre>
<p>Have fun, and let's hope this got you into your weekend early!</p>]]></content:encoded>
      <pubDate>Fri, 17 Apr 2009 11:00:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[A caching pattern for models]]></title>
      <link>http://www.contentwithstyle.co.uk/content/a-caching-pattern-for-models</link>
      <guid>http://www.contentwithstyle.co.uk/content/a-caching-pattern-for-models</guid>
      <description><![CDATA[<p>This is a caching pattern for models using Zend_Cache and the __call magic method.</p>]]></description>
      <content:encoded><![CDATA[<p>This is a caching pattern for models using Zend_Cache and the __call magic method.</p>

<h2>The Basic Idea</h2>

<p>
The initial thought behind this is that a model should be able to return calls either uncached or cached, without initializing some cache object every time. It should be easy to switch between the two calls, and the cache should be coming with the model object already.
</p>

<h3>The old way</h3>

<p>
Before introducing the cache pattern, I would create an object that then would use Zend_Cache_Frontend_Class, then initialize a new instance of my model in there, then redefine a method that acts as somewhat like a proxy, but uses the cache.
And if that wasn't enough, I'd have to initialize them both, like in this example:
</p>

<pre><code>
$model = MyModel();
$model_cached = MyModelCached();

$values_direct = $model-&gt;doStuff();
$values_cached = $model_cached-&gt;doStuff();
</code></pre>

<h3>The new way</h3>

<p>
So Matthias asked me: Would it not be nicer if the cache was already available in the model, and you could do something like this:
</p>

<pre><code>
$model = MyModel();
$values_direct = $model-&gt;doStuff();
$values_cached = $model-&gt;cache-&gt;doStuff();
</code></pre>

<p>
A great idea. As you can see this proposed way saves a bit of code, it's intuitive and easy to change, if you ever need to switch between cached and non-cached calls.
</p>

<h2>The Code</h2>

<p>First we need to create an object that initializes the cache. We'll initialize a cache with Zend_Cache and then utilize the __call function to check whether a call exists in the cached object or not. This enables us to only do valid calls.</p>

<pre><code>
class BaseModelCache {
  private $object;
  private $cache;
  
  public function __construct($object) {
    $backendName = 'File';
    $frontendName = 'Class';

    $frontendOptions = array(
      'lifetime' =&gt; 1800,
    );

    $backendOptions = array(
      'cache_dir' =&gt; '/my/cache/dir/',
    );

    $this-&gt;object = $object;
    $frontendOptions['cached_entity'] = $object;

    try {
      Zend_Loader::loadClass('Zend_Cache');
      $this-&gt;cache = Zend_Cache::factory($frontendName, $backendName, $frontendOptions, $backendOptions);     
    } catch(Exception $e) {
      throw($e);
    }
  }
  
  public function __call($method, $args) {
    $class = get_class($this-&gt;object);
    $class_methods = get_class_methods($class);

    if(in_array($method , $class_methods)) {
        $caller = Array($this-&gt;cache, $method);
        return call_user_func_array($caller, $args);
    }

    throw new Exception( " Method " . $method . " does not exist in this class " . get_class($class ) . "." );
  }
}
</code></pre>

<p>The second step is to create a base model class, that we'll use for all our models. It will initialize the cache object using the BaseModelCache and make it available as public property:</p>

<pre><code>
abstract class BaseModel {
  public $cache;

  public function __construct() {
    $this-&gt;cache = new BaseModelCache($this);
  }
}
</code></pre>

<p>Et Voilà! Now we can create models by extending the BaseModel. The cache will be available as described above.</p>]]></content:encoded>
      <pubDate>Mon, 06 Apr 2009 10:50:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Unit testing controllers with Zend Framework]]></title>
      <link>http://www.contentwithstyle.co.uk/content/unit-testing-controllers-with-zend-framework</link>
      <guid>http://www.contentwithstyle.co.uk/content/unit-testing-controllers-with-zend-framework</guid>
      <description><![CDATA[<p>Unit testing your Zend Framework driven MVC applications is not hard at all. This post tries to give a brief overview on how to test your Controllers with Zend_Test.</p>]]></description>
      <content:encoded><![CDATA[<p>Unit testing your Zend Framework driven MVC applications is not hard at all. This post tries to give a brief overview on how to test your Controllers with Zend_Test.</p>

<h2>Install PHPUnit</h2>

<p>Zend Framework integrates with PHPUnit. PHPUnit is a <a href="http://pear.php.net/">PEAR</a> module, and the usual way is to install PEAR that first and then <a href="http://www.phpunit.de/manual/current/en/installation.html">use the pear installer to install PHPUnit for you</a>.</p>

<h2>Create an application bootstrap include</h2>

<p>If you're using the <a href="http://framework.zend.com/manual/en/zend.controller.front.html">front controller pattern</a> and have all your variables set up in the index.php of your web folder, now is the time to <a href="http://framework.zend.com/docs/quickstart/create-a-bootstrap-file">move things into an include file</a>, before you create the controller and dispatcher. We'll use this very file when doing unit tests with Zend_Test</p>

<h2>Start Testing Controllers</h2>

<p>
With the help of Zend_Test we're now able to create tests that dispatch our controllers. We're then able to do assertions against the response, using the provided methods of the <a href="http://framework.zend.com/apidoc/core/Zend_Test/PHPUnit/Zend_Test_PHPUnit_ControllerTestCase.html">ControllerTestCase</a>.
</p> 

<pre><code>
class IndexTest extends Zend_Test_PHPUnit_ControllerTestCase
{
  public function setUp() {
    $this->bootstrap = array($this, 'appBootstrap');
    parent::setUp();
  }

  public tearDown() {
    $this->resetRequest();
    $this->resetResponse();
    parent::tearDown();
  }

  public function appBootstrap() {
    require_once('/my/bootstrap.php');
  }

  public function testHomepage() {
    $this->dispatch('/');
    $this->assertController('index');
    $this->assertAction('index');
    $this->assertXpath("//form[@action = '/foo']");
  }
}
</code></pre>

<h3>Manipulate the request, evaluate the response</h3>

<p>
Now that we've dispatched our controller, we can manipulate the request and access the response, to see what the dispatched action does. For example an action that requires post data, and then redirects us to another page:
</p>

<pre><code>
public testPostAction() {
  $request = $this->getRequest();

  $request->setMethod('POST');
  $request->setPost(array(
    'foo' => 'bar',
    'baz' => 'x',
  ));

  $this->dispatch('/my/post/action');
  $this->assertRedirectTo('/my/expected/redirect');
}
</code></pre>

<h3>Checking data manipulation</h3>

<p>
If we're working with data manipulations in our tests, we could use models to create the data we manipulate, and then to evaluate it after the controller has been dispatched. Finally we'll clean up after the test. Of course you'd want to have stable models at that point.
</p>

<pre><code>
public function testSave() {
  $my_id = $model->create();

  $request = $this->getRequest();
  
  $request->setMethod('POST');
  $request->setPost(array(
    'name' => 'unittest modified',
    'id' => $my_id,
  ));

  $this->dispatch("/save/object/");
  $this->assertRedirectRegex('#/edit/object/id/[\d]+$#');

  $data = $model->get($my_id);
  $this->assertEquals($data['name'], 'unittest modified');
  
  $my_id = $model->delete($my_id);  
}
</code></pre>

<h2>Related links</h2>

<ul>
<li><a href="http://framework.zend.com/manual/en/zend.test.html">Zend_Test Reference Guide</a></li>
<li><a href="http://devzone.zend.com/article/2772-An-Introduction-to-the-Art-of-Unit-Testing-in-PHP">An Introduction to the Art of Unit Testing in PHP</a></li>
<li><a href="http://blog.fedecarg.com/2008/12/27/phpunit-testing-zend-framework-controllers/">PHPUnit: Testing Zend Framework Controllers</a></li>
<li><a href="http://www.zfforums.com/zend-framework-general-discussions-1/installation-configuration-3/zend_test-how-set-up-1569.html">Zend_Test: how to set up?</a></li>
</ul>
]]></content:encoded>
      <pubDate>Thu, 02 Apr 2009 13:47:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Zend_Translate with dynamic parameters]]></title>
      <link>http://www.contentwithstyle.co.uk/content/zendtranslate-with-dynamic-parameters</link>
      <guid>http://www.contentwithstyle.co.uk/content/zendtranslate-with-dynamic-parameters</guid>
      <description><![CDATA[<p>Just a quick snippet to have dynamic parameters in the underscore function, without having to write sprintf every time.</p>]]></description>
      <content:encoded><![CDATA[<p>Just a quick snippet to have dynamic parameters in the underscore function, without having to write sprintf every time.</p>

<pre><code>
&lt;?php
class Translate extends Zend_Translate {
  public function _() {
    $args = func_get_args();
    $num = func_num_args();
    
    $adapter = $this->getAdapter();
    $args[0] = $adapter->_($args[0]);
        
    if($num &lt;= 1) {
      return $args[0];
    }
        
    return call_user_func_array('sprintf', $args);  
  }
}
</code></pre>

<p>Usage would be something like the following:</p>

<pre><code>
$t = new Translate('array', $array_translation, $lang);
echo $t->_('My name is %s', 'Pascal');
echo $t->_('I have a %s and a %s', 'Cat', 'Horse');
</code></pre>]]></content:encoded>
      <pubDate>Fri, 13 Mar 2009 11:46:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[My take on jQuery charts]]></title>
      <link>http://www.contentwithstyle.co.uk/content/my-take-on-jquery-charts</link>
      <guid>http://www.contentwithstyle.co.uk/content/my-take-on-jquery-charts</guid>
      <description><![CDATA[<p>A while back I did <a href="http://www.contentwithstyle.co.uk/search/canvas">a couple of posts</a> touching the subject HTML 5 and the canvas tag. Of course I have been tinkering around with chart drawing APIs and so on, and couldn't help to write a little script myself.</p>
]]></description>
      <content:encoded><![CDATA[<p>A while back I did <a href="http://www.contentwithstyle.co.uk/search/canvas">a couple of posts</a> touching the subject HTML 5 and the canvas tag. Of course I have been tinkering around with chart drawing APIs and so on, and couldn't help to write a little script myself.</p>

<p>I started out with pie charts, and essentially did a mashup between <a href="http://joncom.be/code/excanvas-piechart">Jon Combes approach</a> and <a href="http://www.mattknott.com/content/blog/2008/04/Advanced_Canvas_Based_Pie_Chart.html">Advanced Canvas Based Pie Chart by Matthew Knott</a>, then wrapped a JQuery plugin around it.</p>

<p>Later I added some sidebar charts, which were much simpler to do and don't require to understand the fact that javascript does trigonometric functions in radians rather than degrees, a fact that made my brain boil when I tried to add in the labels, because I was expecting different numbers to come back from my calculations ...</p>

<p>I was keen on passing the chart values in as array, so I could gather data from an HTML table with a couple of lines of JS, for example. I left this out in <a href="http://www.contentwithstyle.co.uk/resources/jquery_canvascharts_demo/index.html">the little demo that I mocked up</a>, which I uploaded <a href="http://www.contentwithstyle.co.uk/resources/jquery_canvascharts_demo.zip">as a zip file</a> as well, but I am sure you guys figure what I mean.</p>

<p>The whole thing is nothing new, and <a href="http://www.liquidx.net/plotkit/">Plotkit</a> or <a href="http://bluff.jcoglan.com">Bluff</a> are way more advanced, but I think it's a nice little demo to read and understand, without being overwhelmed by large files of code. So I hope you enjoy it.</p>]]></content:encoded>
      <pubDate>Sat, 28 Feb 2009 20:24:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Perl validation from PHP]]></title>
      <link>http://www.contentwithstyle.co.uk/content/perl-validation-from-php</link>
      <guid>http://www.contentwithstyle.co.uk/content/perl-validation-from-php</guid>
      <description><![CDATA[<p>A quick method to validate perl scripts from PHP. Took me a long time that perl-c does not use stdout but stderr as output stream ...</p>
]]></description>
      <content:encoded><![CDATA[<p>A quick method to validate perl scripts from PHP. Took me a long time that perl-c does not use stdout but stderr as output stream ...</p>

<pre><code>
public function validationErrorPerl($content) {
  $hash = md5(microtime() . $content);
  $infile = CACHE_DIR . '/validation_' . $hash . '.pl';
  $outfile = CACHE_DIR . $this-&gt;config-&gt;cache-&gt;dir . '/validation_' . $hash . '.txt';
  file_put_contents($infile, $content);
  $cmd = "/usr/bin/perl -c $infile 2&gt; /dev/null &amp;&gt; $outfile";
  exec($cmd);
  $result = file_get_contents($outfile);
  unlink($infile);
  unlink($outfile);
  $result = str_replace($infile, 'perl script', $result);
  
  if(strpos($result,'syntax OK') !== false) {
    return false;
  }
  
  return $result;
}
</code></pre>]]></content:encoded>
      <pubDate>Thu, 26 Feb 2009 11:07:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[PyObjC newbie frustration]]></title>
      <link>http://www.contentwithstyle.co.uk/content/pyobjc-newbie-frustration</link>
      <guid>http://www.contentwithstyle.co.uk/content/pyobjc-newbie-frustration</guid>
      <description><![CDATA[<p>So I was trying out to build a graphical interface for my VHOST shell script, this time in Python, but couldn't get one past hurdle: I need superuser rights to edit /etc/hosts and the httpd.conf.</p>]]></description>
      <content:encoded><![CDATA[<p>So I was trying out to build a graphical interface for my VHOST shell script, this time in Python, but couldn't get one past hurdle: I need superuser rights to edit /etc/hosts and the httpd.conf.</p>

<p>While I was able to build a quick interface for a python script to do essentially the same, using the PyObjC bridge and the Interface Builder, I couldn't figure out how the hell I am supposed to get the authentication going to execute the script as superuser ... and a look into the <a href="http://developer.apple.com/documentation/Security/Reference/authorization_ref/Reference/reference.html#//apple_ref/c/func/AuthorizationExecuteWithPrivileges">documentation</a> does give no clue on how to use Authorization with PyObjC, but only shows a C function ...?</p>

<p>Apart from that I found the Interface Builder pretty intriguing, and I'm starting to like XCode as well. Of course I haven't got much of a clue of how Python is done properly, and especially the underscore convention for actions threw me off at first. Also, what do people mean when they say Pythonic? What makes an app/script/library exactly that?</p>

<p>Of course I am way out of my comfort zone here. Would appreciate some hints and guidance.</p>

]]></content:encoded>
      <pubDate>Sat, 21 Feb 2009 18:27:25 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[You and the stu nicholls guy]]></title>
      <link>http://www.contentwithstyle.co.uk/content/you-and-the-stu-nicholls-guy</link>
      <guid>http://www.contentwithstyle.co.uk/content/you-and-the-stu-nicholls-guy</guid>
      <description><![CDATA[<p>A short look at last week's web rage (and maybe a little about web standards)</p>]]></description>
      <content:encoded><![CDATA[<p>It amazes me time and time again how much emotion goes into our work life. Not that I can exclude myself, I don't even want to: I'm proud if I've achieved a great end result, be it in code or in planning an application, I'm happy when my machines and applications run as expected. Equally I feel the discomfort of a bug that's down to my sloppiness, or worse, a conceptual error that has me repeating or redoing my work, because I couldn't be bothered to fully understand a concept or the implications of a decision made early.</p>
<p>To avoid the latter, I've never stopped learning, reading up on how it's supposed to be done, and trying to see the benefit in generalizations others have suggested.</p>
<p>Web Standards and the people that actively try shaping them is such a subject. Over the years I've followed a number of blogs and web publications, and looked at how <em>they</em> do it, taking on suggestions when they seemed to make sense, trying to work out the benefits when the don't. Lucky me, living in London, even had a chance to see, and at times even chat to some of <em>them</em>, the people who seem to have so many good ideas.</p>
<p>One of them is <a href="http://www.flickr.com/photos/ptg/216749262/">Dean Edwards</a>, who I've met several times at the Pub Standards, when his and my occasional attendance overlapped.</p>
<p>Now, he's forgotten to renew his domain, and the reminder didn't reach its intended target. That's kinda <a href="http://www.reddit.com/r/programming/comments/7vl0t/what_can_i_do_to_get_a_stolen_domain_back/c07j4yd">stupid</a>, but I can confirm that although it has so far not happened to me, I'm uncomfortable about this subject every 2 years, because my registrar has such a bad user interface that I'm never sure if it updated credit card details, if a changed status means that everything is (going to be) ok, etc. (feel free to suggest a registrar that tells me in simple words where I'm at)</p>
<p>Maybe I'm just too forgiving, but imagine: Somebody who has been publicly, on the web and elsewhere, trying to standardize and improve his work universe, forgets something important. That's crazy, and clearly deserves a <a href="http://www.reddit.com/r/programming/comments/7vl0t/what_can_i_do_to_get_a_stolen_domain_back/c07j5t0">telling-off, throwing everything in</a> except the kitchen sink.</p>
<p>Oh, it's so funny, I have to quote it here (who knows, maybe it'll be taken down). So, on the erroneously titled subject of a lost-and-snatched domain with unlicensed content replication, someone called "gmn17" had this to say:</p>
<blockquote><p>man oh man what happens to you guys?, you and the quirksmode guy and the stu nicholls guy, you guys get burned out and then whore yourselves out and can't handle what you created and started, putting down people for using tables and innerhtml like the guy who explains how different the internet and the world wide web are so different, trying to create an atmosphere of holier than thou web design and make people feel like crap for using tables and document.write, it's hard to feel sorry for you, you yourself said many times on that site that you only use it sparingly or can not update it as frequently, and that stu nicholls guy, man what a sellout, someone needs to tell him his javascript is horrible, you just have to be patient, I always liked your site too, lots of nice stuff, can't believe you can write code like that and get into a situation like this, what a world,</p></blockquote>
<p>Amazing! I mean, it's hilarious, it looks so menacing! I wanted to only quote one sentence, but, there is no full stop. I'm interpreting a lot of pent-up anger in there, and the chance of a lifetime. Ironically, his comment wouldn't have been too out of place at Ajaxian, where a <a href="http://ajaxian.com/archives/css-for-layout-another-rant">discussion about CSS (or tables)for layout</a> was reheated and served.</p>
<p>I'm sure you'll find a lot of flak in the comments, too, maybe even some condescending advice. But as far as I read, they only get as personal as "you're probably a backend dev" or the general denial of professionalism on the part of the original author. A great week for making the web a better place, that's for sure.</p>]]></content:encoded>
      <pubDate>Mon, 09 Feb 2009 10:25:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Shell script for adding virtual hosts in Leopard]]></title>
      <link>http://www.contentwithstyle.co.uk/content/shell-script-for-adding-virtual-hosts-in-leopard</link>
      <guid>http://www.contentwithstyle.co.uk/content/shell-script-for-adding-virtual-hosts-in-leopard</guid>
      <description><![CDATA[<p>I was getting annoyed with constantly editing config files myself. That's why I hacked together a shell script to add the vhosts for me.</p>]]></description>
      <content:encoded><![CDATA[<p>I was getting annoyed with constantly editing config files myself. That's why I hacked together a shell script to add the vhosts for me.</p>

<h2>Prerequisites</h2>

<p>
Open the Terminal and execute the following commands:
</p>

<pre><code>
sudo sed -i -e s@^#Include\ /private/etc/apache2/extra/httpd-vhosts.conf@Include\ /private/etc/apache2/extra/httpd-vhosts.conf@ /private/etc/apache2/httpd.conf
</code></pre>

<p>
This will enable the vhost include file to be read from the httpd conf.
</p>

<pre><code>
sudo sed -i -e s/^\&lt;/#\&lt;/ /private/etc/apache2/extra/httpd-vhosts.conf
sudo sed -i -e s/^\ /#\ / /private/etc/apache2/extra/httpd-vhosts.conf
sudo sed -i -e s/^#NameVirtualHost/NameVirtualHost/ /private/etc/apache2/extra/httpd-vhosts.conf
</code></pre>

<p>
This will enable the Virtualhosts in apache.
<br />
Now let's enable PHP as well:
</p>

<pre><code>
sudo sed -i -e s@^#LoadModule\ php5_module@LoadModule\ php5_module@ /private/etc/apache2/httpd.conf
</code></pre>

<p>
All we need to do is restart apache:
</p>

<pre><code>
sudo apachectl restart
</code></pre>

<h2>Adding a vhost</h2>

<p>
Now we're all set, and can create the shell script in some location of your choice. In the example below it's assumed that it is called add.sh.
</p>

<p>The shell script itself:</p>

<pre><code>
#!/bin/sh
#
# Script to validate files in directory
#
add_host_entry() {
	echo "127.0.0.1	$1" &gt;&gt; /etc/hosts
}

add_vhost_conf() {
	cat localvhost.tpl | sed "s/{VHOSTNAME}/$1/" | sed "s@{VHOSTDIRECTORY}@$2@" &gt;&gt; /private/etc/apache2/extra/httpd-vhosts.conf
}

if [ $# -lt 2 ]; then
	echo "syntax: sh add.sh vhostname vhostdir"
	exit
fi

add_host_entry $1
add_vhost_conf $1 $2 
</code></pre>

<p>The template file 'localvhost.tpl' needs to sit in the same folder like 'add.sh':</p>

<pre><code>
#VHOSTSTART {VHOSTNAME}
&lt;VirtualHost *:80 &gt; 
	DocumentRoot "{VHOSTDIRECTORY}"
	ServerName {VHOSTNAME}
	ErrorLog /private/var/log/apache2/{VHOSTNAME}-error_log
	CustomLog /private/var/log/apache2/{VHOSTNAME}-access_log common
&lt;/VirtualHost&gt;

&lt;Directory {VHOSTDIRECTORY}&gt;
	Options Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
	AllowOverride All
	Order allow,deny
	Allow from all
&lt;/Directory&gt;
#VHOSTEND {VHOSTNAME}
</code></pre>

<p>
You should now be able to add vhosts by typing:
</p>

<pre><code>
cd /path/to/shellscript/folder
sudo add.sh vhostname /path/to/vhost/webroot
</code></pre>

<p>
Once you're done do an apache restart again:
</p>

<pre><code>
sudo apachectl restart
</code></pre>]]></content:encoded>
      <pubDate>Sun, 08 Feb 2009 08:22:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Installing APC on Leopard]]></title>
      <link>http://www.contentwithstyle.co.uk/content/installing-apc-on-leopard</link>
      <guid>http://www.contentwithstyle.co.uk/content/installing-apc-on-leopard</guid>
      <description><![CDATA[<p>Some short notes on getting APC to work nicely with OS X Leopard.</p>]]></description>
      <content:encoded><![CDATA[<p>There are a few steps needed to install <a href="http://www.php.net/apc">APC</a> on OS X Leopard. Don't worry, it may look a bit daunting if you've never had to compile anything before but it's very straight forward.</p>

<ul>
<li>First, download the appropriate version of the <a href="http://pecl.php.net/package/APC">APC package</a></li>
<li>Unpack it (doesn't matter where)</li>
<li>Now start Terminal and cd to the unpacked directory from the above step</li>
<li>Run 'phpize'</li>
<li>Now it needs to be configured. Copy the following configuration (note: it must be entered into the Terminal prompt as a <strong>single</strong> line)</li>
</ul>

<pre><code>MACOSX_DEPLOYMENT_TARGET=10.5 CFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -g -Os -pipe -no-cpp-precomp" CCFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -g -Os -pipe" CXXFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -g -Os -pipe" LDFLAGS="-arch ppc -arch ppc64 -arch i386 -arch x86_64 -bind_at_load" ./configure</code></pre>

<ul>
<li>Nearly there: now type 'make'</li>
<li>sudo make install (you will need to enter your root password)</li>
<li>Finally, add 'extension=apc.so' into your php.ini</li>
</ul>

<p>And that's it!</p>

]]></content:encoded>
      <pubDate>Tue, 03 Feb 2009 12:02:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Spotify now in the news]]></title>
      <link>http://www.contentwithstyle.co.uk/content/spotify-now-in-the-news</link>
      <guid>http://www.contentwithstyle.co.uk/content/spotify-now-in-the-news</guid>
      <description><![CDATA[<p>One of my favorite apps lately, <a href="http://www.spotify.com/">Spotify</a> has now reached the <a href="http://www.guardian.co.uk/technology/2009/jan/29/spotify">technology news section of the Guardian</a></p>]]></description>
      <content:encoded><![CDATA[<p>One of my favourite apps lately, <a href="http://www.spotify.com/">Spotify</a> has now reached the <a href="http://www.guardian.co.uk/technology/2009/jan/29/spotify">technology news section of the Guardian</a></p>

<p>To me this doesn't come as such a  big surprise, since I have been raving about it ever since I got myself a cheeky login without invitation code, something that a google search will reveal If you can't get the latter.</p>

<p>It's no often that I do big up an application, but spotify seems to do everything right that other music players didn't quite achieve. For example, I really liked last.fm, but I always wanted to be able to search for a track and then play the album.</p>

<p>Even more amazing that it does get things right that I didn't even ask for. Already my listening behaviour has changed, because I started to use Spotify's direct URLs and collaborative play lists. Let's just wait an see what else is coming in terms of nifty integration.</p>

<p>Also let's hope that they don't screw it up big time. Already they had to <a href="http://www.spotify.com/blog/archives/2009/01/28/some-important-changes-to-the-spotify-music-catalogue/">remove some tracks</a>, and the potential to bomb the application with adverts until everyone tunes out is huge. If they get it right it might be as much of an important app like the iplayer or hulu.</p>
]]></content:encoded>
      <pubDate>Thu, 29 Jan 2009 14:20:10 +0000</pubDate>
    </item>
  </channel>
</rss>
