<![CDATA[Content with Style]]> http://www.contentwithstyle.co.uk/content/rss Thu, 19 Mar 2009 11:05:31 +0000 Zend_Feed http://blogs.law.harvard.edu/tech/rss <![CDATA[Zend_Translate with dynamic parameters]]> http://www.contentwithstyle.co.uk/content/zendtranslate-with-dynamic-parameters http://www.contentwithstyle.co.uk/content/zendtranslate-with-dynamic-parameters Just a quick snippet to have dynamic parameters in the underscore function, without having to write sprintf every time.

]]>
Just a quick snippet to have dynamic parameters in the underscore function, without having to write sprintf every time.


<?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 <= 1) {
      return $args[0];
    }
        
    return call_user_func_array('sprintf', $args);  
  }
}

Usage would be something like the following:


$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');
]]>
Fri, 13 Mar 2009 11:46:57 +0000
<![CDATA[My take on jQuery charts]]> http://www.contentwithstyle.co.uk/content/my-take-on-jquery-charts http://www.contentwithstyle.co.uk/content/my-take-on-jquery-charts A while back I did a couple of posts 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.

]]>
A while back I did a couple of posts 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.

I started out with pie charts, and essentially did a mashup between Jon Combes approach and Advanced Canvas Based Pie Chart by Matthew Knott, then wrapped a JQuery plugin around it.

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 ...

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 the little demo that I mocked up, which I uploaded as a zip file as well, but I am sure you guys figure what I mean.

The whole thing is nothing new, and Plotkit or Bluff 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.

]]>
Sat, 28 Feb 2009 20:24:47 +0000
<![CDATA[Perl validation from PHP]]> http://www.contentwithstyle.co.uk/content/perl-validation-from-php http://www.contentwithstyle.co.uk/content/perl-validation-from-php 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 ...

]]>
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 ...


public function validationErrorPerl($content) {
  $hash = md5(microtime() . $content);
  $infile = CACHE_DIR . '/validation_' . $hash . '.pl';
  $outfile = CACHE_DIR . $this->config->cache->dir . '/validation_' . $hash . '.txt';
  file_put_contents($infile, $content);
  $cmd = "/usr/bin/perl -c $infile 2> /dev/null &> $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;
}
]]>
Thu, 26 Feb 2009 11:07:31 +0000
<![CDATA[PyObjC newbie frustration]]> http://www.contentwithstyle.co.uk/content/pyobjc-newbie-frustration http://www.contentwithstyle.co.uk/content/pyobjc-newbie-frustration 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.

]]>
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.

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 documentation does give no clue on how to use Authorization with PyObjC, but only shows a C function ...?

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?

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

]]>
Sat, 21 Feb 2009 18:27:25 +0000
<![CDATA[You and the stu nicholls guy]]> http://www.contentwithstyle.co.uk/content/you-and-the-stu-nicholls-guy http://www.contentwithstyle.co.uk/content/you-and-the-stu-nicholls-guy A short look at last week's web rage (and maybe a little about web standards)

]]>
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.

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.

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 they 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 them, the people who seem to have so many good ideas.

One of them is Dean Edwards, who I've met several times at the Pub Standards, when his and my occasional attendance overlapped.

Now, he's forgotten to renew his domain, and the reminder didn't reach its intended target. That's kinda stupid, 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)

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 telling-off, throwing everything in except the kitchen sink.

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:

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,

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 discussion about CSS (or tables)for layout was reheated and served.

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.

]]>
Mon, 09 Feb 2009 10:25:26 +0000
<![CDATA[Shell script for adding virtual hosts in Leopard]]> http://www.contentwithstyle.co.uk/content/shell-script-for-adding-virtual-hosts-in-leopard http://www.contentwithstyle.co.uk/content/shell-script-for-adding-virtual-hosts-in-leopard 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.

]]>
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.

Prerequisites

Open the Terminal and execute the following commands:


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

This will enable the vhost include file to be read from the httpd conf.


sudo sed -i -e s/^\</#\</ /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

This will enable the Virtualhosts in apache.
Now let's enable PHP as well:


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

All we need to do is restart apache:


sudo apachectl restart

Adding a vhost

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.

The shell script itself:


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

add_vhost_conf() {
	cat localvhost.tpl | sed "s/{VHOSTNAME}/$1/" | sed "s@{VHOSTDIRECTORY}@$2@" >> /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 

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


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

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

You should now be able to add vhosts by typing:


cd /path/to/shellscript/folder
sudo add.sh vhostname /path/to/vhost/webroot

Once you're done do an apache restart again:


sudo apachectl restart
]]>
Sun, 08 Feb 2009 08:22:59 +0000
<![CDATA[Installing APC on Leopard]]> http://www.contentwithstyle.co.uk/content/installing-apc-on-leopard http://www.contentwithstyle.co.uk/content/installing-apc-on-leopard Some short notes on getting APC to work nicely with OS X Leopard.

]]>
There are a few steps needed to install APC 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.

  • First, download the appropriate version of the APC package
  • Unpack it (doesn't matter where)
  • Now start Terminal and cd to the unpacked directory from the above step
  • Run 'phpize'
  • Now it needs to be configured. Copy the following configuration (note: it must be entered into the Terminal prompt as a single line)
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
  • Nearly there: now type 'make'
  • sudo make install (you will need to enter your root password)
  • Finally, add 'extension=apc.so' into your php.ini

And that's it!

]]>
Tue, 03 Feb 2009 12:02:17 +0000
<![CDATA[Spotify now in the news]]> http://www.contentwithstyle.co.uk/content/spotify-now-in-the-news http://www.contentwithstyle.co.uk/content/spotify-now-in-the-news One of my favorite apps lately, Spotify has now reached the technology news section of the Guardian

]]>
One of my favourite apps lately, Spotify has now reached the technology news section of the Guardian

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.

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.

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.

Also let's hope that they don't screw it up big time. Already they had to remove some tracks, 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.

]]>
Thu, 29 Jan 2009 14:20:10 +0000
<![CDATA[CwS blog posts now on twitter]]> http://www.contentwithstyle.co.uk/content/cws-blog-posts-now-twitter http://www.contentwithstyle.co.uk/content/cws-blog-posts-now-twitter Posts from our blog will now automatically pop up on Twitter.

]]>
Posts from our blog will now automatically pop up on Twitter.

This is only a couple of lines of code, thanks to the API wrapper that Zend Framework now offers, but also thanks to the TinyURL API:


// TinyURL for the blog post
$client = new Zend_Http_Client($config->tinyurl->endpoint);
$client->setParameterGet('url', $url);
$response = $client->request('GET');
$tiny_url_response = $response->getBody();

// TinyURL into the message
$message = $message . ' ' . $tiny_url_response;

// Twitter
$twitter = new Zend_Service_Twitter($config->twitter->user, $config->twitter->password);        
$twitter->status->update($message);

So feel free to follow us, even though twittering to ME only makes sense if it happens automatically, as I personally am no big fan of messages like "I am going outside now" or anything like that.

]]>
Thu, 29 Jan 2009 08:00:19 +0000
<![CDATA[Remove .AppleDouble folders on *NIX boxes]]> http://www.contentwithstyle.co.uk/content/remove-appledouble-folders-on-nix-boxes http://www.contentwithstyle.co.uk/content/remove-appledouble-folders-on-nix-boxes Quick note to myself on how to get rid of those silly .AppleDouble folders

]]>
Quick note to myself on how to get rid of those silly .AppleDouble folders

This fails, if there's funny characters in the filenames:


find . -name '.AppleDouble' | xargs rm -Rf
xargs: unmatched single quote

Hence we need to wrap the string into quotation marks:


find . -name '.AppleDouble' -printf '"%p"\n' | xargs rm -Rf
]]>
Thu, 22 Jan 2009 22:54:42 +0000
<![CDATA[Make sure firebug console debug doesn't break everything.]]> http://www.contentwithstyle.co.uk/content/make-sure-that-firebug-console-debug-doesnt-break-everything http://www.contentwithstyle.co.uk/content/make-sure-that-firebug-console-debug-doesnt-break-everything Maybe some of you have already had problems with leaving debug statements in JS code. A console.log() left in the deployed code can break the whole application, and it might only come up when someone without firebug is testing it at a later stage.

]]>
Maybe some of you have already had problems with leaving debug statements in JS code. A console.log() left in the deployed code can break the whole application, and it might only come up when someone without firebug is testing it at a later stage.

Very embarrassing indeed, and I recall a story where the whole development team had neglected to test without firebug, but a scheduled session of Acceptance Tests held at a different site was about to fail. Someone then had to rush there and managed to save the day by installing firebug on the test machine, so that they could get on with it. This taught me a valuable lesson about what can happen in an environment where there are many developers: Mistakes WILL happen!

People that do flash will know the trace() function, which gives you debug output, but can be turned off in the export settings, so that the compiler removes those calls from the generated SWF.
But javascript isn't a compiled language so there is no auto removal of debug specific code.
This is why we have to ensure that, even though code does still contain debug code, it shouldn't break. For javascript development this means that at least console.log and console.dir statements need to be dealt with. And yes, I agree: It shouldn't be in there in the first place. But we have to either make sure that calls to the console get removed or that the rest of the javascript application isn't affected when they're made.

Suggestions

Version control hooks

CVS, SVN or GIT offer hooks. I haven't tried this out properly, but I imagine a simple shell script could help. Like doing a grep for console.log and stopping the commit if there's anything in there that should only be debug code.
Of course with this method the downside would be that there would be no means to share the debugging code with other developers through the version control.

Build tools

A similar check/removal process could be done in the deployment stage. Using grep, sed or something similar on the project files to remove any debug related code would ensure that the javascript always gets deployed without debug code.

A mock object

We could provide a mock object, so that calls to the console wouldn't result in an error. This would ensure that the javascript doesn't fail, even though debug code is still in the code.


if(!window.console) {
  window.console = new function() {
    this.log = function(str) {};
    this.dir = function(str) {};
  };
}

Wrapping the debug code

Another valid approach would be to wrap the calls to console.log, and provide error checking or try-catch inside the wrapper.
Of course this only works if all developers will use the wrapper instead of the firebug console object.


var Logger = new function() {
  this.log = function(str) {
    try {
      console.log(str);
    } catch(e) {
      // do nothing
    }
  };
};

Finally ...

Please keep in mind that what I've written is about keeping code from breaking the testing or staging environment. The truth is that, if there is anything that breaks the App in it's live deployment, then something is wrong with the testing process.

Related links

]]>
Fri, 16 Jan 2009 14:49:49 +0000
<![CDATA[Join PhotoBox as PHP developer]]> http://www.contentwithstyle.co.uk/content/join-photobox http://www.contentwithstyle.co.uk/content/join-photobox In a long standing tradition of posting jobs so that you get the chance to work with a CWS author, here's my latest offer regarding a PHP developer job at PhotoBox in London.

]]>
PhotoBox is currently looking for a PHP Developer based in London to join a strong development team of 20.

You should have been working a minimum of three years full-time in OO-PHP, with experience in PHP5. You will be primarily working with Zend Framework using their MVC components, so any exposure to ZF or any other MVC framework is beneficial. At the same time you can show off skills in web standards compliant XHTML and CSS, and have corporate experience in working with Javascript.

The Company

Launched at the beginning of year 2000 PhotoBox is a privately owned and funded company, and specializes in digital photographic services using state of the art facilities.

PhotoBox is the UK and Ireland's number one destination for online photo sharing, storing and printing, with over two million members. Find out more about Photobox in this interview with CTO Graham Hobson. Since the interview the office has been moved to Paddington.

Responsibilities

You will be working as part of the PHP/Front-end team, maintaining and expanding existing web applications as well as develop new ones.

With a regular release schedule you must be able to:

  • Assist in providing development timescales and estimates
  • Assist in providing technical feedback on business requirements
  • Follow project specifications and timescales
  • Use source code management systems (SVN) as appropriate
  • Ensure your code is well documented

Skills Requirements

If you feel this one's for you, please send your CV to techjobs@photobox.com and make sure to mention my name (so I can, totally selfless as I am, benefit from our referral scheme!)

]]>
Wed, 14 Jan 2009 11:33:28 +0000
<![CDATA[Looking forward, looking back]]> http://www.contentwithstyle.co.uk/content/looking-forward-looking-back http://www.contentwithstyle.co.uk/content/looking-forward-looking-back I just about make it for the yearly reviews with this post, I hope. For good measure I've thrown in our aspirations for 2009 in, too.

]]>
Looking back to 2008

The biggest change of 2008 must've been the relaunch of Content with Style. We talked through the theory back in Autumn/Winter 2007, and Pascal and I made some room in our schedules in January. The first day we met, we looked at the then current Wordpress release, weighed the pros and cons against turning our backs to PHP and use Python. Wordpress seemed the quicker option, and as Pascal was going on a big trip a week later, I felt more comfortable pushing something I know. After doing some amazing doodles on A2 paper I lifted from the office, we were all psyched up and ready to go, and it was only early afternoon!

The rest of the day we spent realizing that our "customized" pre-1.0 release of Textpattern was in no way happy to work with the importer tool for Wordpress. It later turned out that both our data format as well as the importer were broken, and an import that would keep all IDs intact would be a pest. Sadly that realization took place late in the second day. What then followed was some last minute woes in planning Pascal's trip, and me getting a stinking cold, that knocked me out for the whole week. The next thing we knew it was May, and nothing was done.

With work and other commitments I will mention further down both Mike and I were blocked. As Pascal was worried that we'd never get it done, he took on development on his own (with a few really minor additions by myself) and commissioned Alastair Holt from our good friends at Seventy-two. You're looking at the result right now!

On top of all the work invested into CwS, Pascal also extended his server-farm to two, and successfully carved himself a very nice career out of contracting around London.

In a parallel universe, Mike has not only managed to make a successful move from freelance to permanent back in 2007 and keep it that way, but he also blossomed in his position as Head of User Experience at Trampoline, taking a good step away from development, while exploring his communicative side as speaker all around the world. London, Brighton, USA, Iceland (post-bank-collapse!), you name it, he'll grab some slides and a glass of water.

All this engagement around the world lead him to take a back seat in the world of Content with Style; out of which he sometimes rises to the occasion.

Needless to say, his legacy of amazing CSS and Javascript-related posts is still in the top10 of most visited pages on CwS.

As much as I would like to take a back seat, it's not in cards for the near future. In the beginning of the year, some changes of personnel lead to me pretending to be the Technical Director of Designjunction (now Design Science Office), a post that was made official with the rebranding in May. I thoroughly enjoyed the role, especially mentoring my junior developer, who will no doubt get very far in the future. I would've loved to stay where I was, but the economy had other plans for me.

So I started looking for new work and landed a very nice Systems Developer position at Photobox, where I am finally in a position that is mostly about developing in Zend Framework, something I've been wanting to do much more for a good year. I'm sure I've projected some of my wishful thinking on Pascal during the year, which lead to the technology behind the CwS relaunch.

Only days after starting my new position, I also ventured on a new endeavor of a more personal kind: On November 22 my baby daughter Esmé was born, and I keep making fun of her with inappropriate comparisons in another corner of the internet ever since.

As a final look back, here's a list of the 15 most popular (by views) posts from 2008:

Looking forward

If you've been a long-term follower of CwS or know us personally, you'll probably remember some of our pledges and promises for the future that never made it.

To avoid this, I simply won't promise anything :-). I'd rather tell you about the situation we're in, and some of the things that are up our sleeves as you read this:

We're still looking for collaborators! There are several good intentions and ideas been floating around for new authors on CwS, but so far there are no real commitments or even drafts that might go out any minute. So, if you're looking for a well-read platform to spread the word, drop us a line right here in the comments.

I've prepared a small series of articles that we'll post over the year, which will mainly deal with the next generation of web developers. While we gain seniority in our working lives, the focus of what lies ahead splits into two: Either we keep on specializing, and push the envelope of what's possible in our fields of expertise, or we do more and more strategy and managerial work as team leads, telling our juniors how to do it right. The series is about handing down working patterns that are second nature to us, that speed up our work dramatically.

On the other hand we want to keep doing what we've always done: Write posts about the technologies we use every day right now, and provide useful nuggets of information, small and large, to expand the horizon or pick the brains of our readers.

Finally you can see from our higher rate of short posts, that we started using CwS not only as means to provide information for you, but also as our little black book of quick notes, details we come across once and want to offload our brains for future use. As a side effect we hope to give a little insight into how we work.

Wrap it up already...

All that's left for me now is to wish you all a Happy New Year 2009. May your lives and work pan out nicely, even in uncertain times like this. See you around, and all the best,

from all of us at Content with Style

]]>
Thu, 08 Jan 2009 17:44:03 +0000
<![CDATA[GET parameters and caching]]> http://www.contentwithstyle.co.uk/content/get-parameters-and-caching http://www.contentwithstyle.co.uk/content/get-parameters-and-caching Once you do care about caching and set expiry headers for static files in the far future, you'll have to make sure that crucial new functionality is not pulled from the cache. But a GET parameter is NOT the way to do this ....

]]>
Once you do care about caching and set expiry headers for static files in the far future, you'll have to make sure that crucial new functionality is not pulled from the cache. But a GET parameter is NOT the way to do this ....

Have a look into the HTTP protocol 1.1 specs about caching, and it becomes obvious why:

We note one exception to this rule: since some applications have traditionally used GETs and HEADs with query URLs (those containing a "?" in the rel_path part) to perform operations with significant side effects, caches MUST NOT treat responses to such URIs as fresh unless the server provides an explicit expiration time. This specifically means that responses from HTTP/1.0 servers for such URIs SHOULD NOT be taken from a cache.

People have tested this, and the bottom line is that you should change the filename instead. Interestingly (I didn't verify this, btw.) it seems that Firefox and IE just ignore this part of the spec sometimes, while Safari does it the right way.

]]>
Wed, 07 Jan 2009 16:55:27 +0000
<![CDATA[XHTML Validation with the W3C validator and PHP]]> http://www.contentwithstyle.co.uk/content/xhtml-validation-with-the-w3c-validator-and-php http://www.contentwithstyle.co.uk/content/xhtml-validation-with-the-w3c-validator-and-php Amongst other changes, I am working on getting this blog over to use application/xhtml+xml as the content type. Of course this calls for a much stricter validation before content can be put live, otherwise users will be confronted with a broken page. The W3C validator and Zend_Http_Client make validation in PHP easy.

]]>
Amongst other changes, I am working on getting this blog over to use application/xhtml+xml as the content type. Of course this calls for a much stricter validation before content can be put live, otherwise users will be confronted with a broken page. The W3C validator and Zend_Http_Client make validation in PHP easy.

People that remember my validation shell script from last year (cough) already know that there is a SOAP-like response format available from the w3c validator. Like other people I am unhappy that the whole thing is not really a proper SOAP endpoint, but merely the same script that returns a SOAP envelope when the post parameter 'output' is set to 'soap12'.
This is very unfortunate. I wasn't able to use Zend_Soap_Client to construct the request, since the passed parameters are wrapped into a SOAP envelope as well, which the validator doesn't interpret.

Instead I used the Zend_Http_Client to do a POST request, which works neatly, but requires processing of the SOAP response as XML document. Below is an example of a validation controller that validates a URL and handles the SOAP response:


<?php
class Admin_ValidationController extends Zend_Controller_Action
{
  public function indexAction() {
    $url = $this->_request->getParam('url');
    $client = new Zend_Http_Client($url);
    $response = $client->request();
    $fragment = $response->getBody();
    
    $params = array(
      'fragment' => $fragment,
      'output' => 'soap12',
    );
    
    $client = new Zend_Http_Client('http://validator.w3.org/check');
    $client->setParameterPost('fragment', $fragment);
    $client->setParameterPost('output', 'soap12');
    $validator_response = $client->request('POST');
    $soap_response = $validator_response->getBody();
    
    $xml = new DomDocument();
    @$xml->loadXML($soap_response);
    $xpath = new DOMXpath($xml);
    $xpath->registerNamespace("m", "http://www.w3.org/2005/10/markup-validator");
    $elements = $xpath->query("//m:errorcount");
  
    $error_str = '';

    if($elements->item(0) && $elements->item(0)->nodeValue > 0) {
      $errors = $xpath->query("//m:errors/m:errorlist/m:error/m:message");
      foreach ($errors as $node) {
          $error_str .= $node->nodeValue. "\n";
      }
    }

    if(!empty($error_str)) {
      $this->view->message = $error_str;
    } else {      
      $this->view->message = 'Validation of ' . $url . ' passed without errors.';
    }
}

No Zend_Http_Client?

For people that cannot or don't want to use Zend Framework at all (or need a facility to encode post parameters as multipart form data), maybe it's worth having a look at the cURL functions in PHP. They provide another easy interface to do HTTP and even FTP requests. A possible snippet could look like this:


$params = array(
  'fragment' => '<html />',
  'output' => 'soap12',
);

$url = 'http://validator.w3.org/check';

$recieved_headers = "";
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params); // multipart encoding
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 
curl_setopt($ch, CURLOPT_REFERER,''); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1); 
curl_setopt($ch, CURLOPT_TIMEOUT,30);

$recieved_headers = curl_exec($ch);         
if (curl_errno($ch)) {
   print curl_error($ch);
} else {
   curl_close($ch);
}

echo $recieved_headers;   

In this example I didn't include the handling of the SOAP response, but you can easily grab that from the previous example.

Happy validating everyone!

]]>
Sun, 04 Jan 2009 12:25:44 +0000