Archive for the 'PHP' Category

Using php to dynamically generate conflict free css

This little blog has been getting a lot of coverage lately thanks to a write up by Ajaxian. Developing with Symfony is great and always gives you a lot to think and write about.

For my new product I was having a CSS conflict. This tends to happen when you include your own html and css into someone else’s website. For instance if you have a widget as such:


<div id="mywidget">
<h1>My hello world widget</h1>


H1 {

The solution to this problem is quite straightforward, you simply specify your css selector as div#mywidget H1. However, what if you want to allow people to customize the looks of your widget. Now you could off course ask them to include the div#mywidget part, but chances are this will give problems.

Since I was already using the great sfCombineFilterPlugin an easy solution was available. (If you didn’t use the sfCombineFilterPlugin yet, go check it out immediately. Also have a look at Yahoo’s Yslow)

The sfCombineFilterPlugin uses php to gzip, minify and cache your css and javascript. Here is how to extend that behavior to include the #mywidget specification. (Assuming you have sfCombineFilter installed)

Step 1: open your .htaccess

Just below the RewriteBase instruction add:
# if we are retrieving javascript or css
RewriteRule ^css/packed/prepend/(.*\.css) /sfCombineFilterPlugin/combine.php?type=css&prepend=1&files=$1
RewriteRule ^css/packed/(.*\.css) /sfCombineFilterPlugin/combine.php?type=css&files=$1
RewriteRule ^js/packed/(.*\.js) /sfCombineFilterPlugin/combine.php?type=javascript&files=$1

Step 2: add this class to the top of web/sfCombineFilter/combine.php

Partly based on CSS parser class.

class prependCss

    public static function prependCssString($str) {
        // Remove comments
        $str = preg_replace("//*(.*)?*//Usi", "", $str);

        $parts = explode("}",$str);
        if(count($parts) > 0) {
            foreach($parts as $part) {
                list($keystr,$codestr) = explode("{",$part);
                $keys = explode(",",trim($keystr));
                $newkeys = array();
                if(count($keys) > 0) {
                    foreach($keys as $key) {
                        if(strlen($key) > 0) {
                            $key = (!strstr($key, '#mywidget')) ? '#mywidget'.$key : $key;
                            $newkeys[] = $key;
                    $keystr = implode(', ',$newkeys);
                if(!empty($keystr)) //needed for spaces behind last }
                $rules[] = $keystr . " {" . $codestr . "}";
            $prependedCss = implode("n", $rules);
        return $prependedCss;

    public static function prependCssFile($filename) {
        if(file_exists($filename)) {
            return self::prependCssString(file_get_contents($filename));
        } else {
            return false;

Step 3: hack around in combine.php

below $minify_js add:
$prepend = true;

change the stuff below this comment to:
// Get contents of the files
$contents = '';
foreach ($files as $path) {
if($prepend && $_GET['type'] == 'css') {
$contents .= "\n\n" . prependCss::prependCssFile($path);
} else {
$contents .= "\n\n" . file_get_contents($path);

And finally just change your urls to css/packed/prepend/yourcss.css (if you are using relative paths in your css you might need to add an ../)


Using this technique your css will load without any problems in third party sites. This comes in very useful when creating widgets or greasemonkey scripts.

Css &PHP &Symfony &Web Development tschellenbach 29 Oct 2007 13 Comments

Introducing a cross site ajax plugin for Prototype

Update: there have been some improvements to this plugin. Have a look at this post regarding the update. Thanks for the feedback!

After some days of hard labor, I finished my cross site Ajax plugin for the prototype framework 1.5.0. (Download Plugin Here) While working on a new product of mine I realized I needed cross site Ajax, which is not supported in the Prototype framework.

During cross site Ajax requests the standard XmlHttpRequest approach breaks down. The problem is that XmlHttpRequest is bounded by the same site policy. Fortunately the script tag has the freedom to do as it pleases.

Some other libraries such as dojo and jquery do support the script method for doing Ajax. There is even a project on source-forge called COWS, which is dedicated to this purpose. This plugin is an adaptation of the jquery plugin, but modeled to look like an XmlHttpRequest. The credits of the original code go to Ralf S. Engelschall , which amazingly achieved to make it nicely cross browser compatible. This plugin supports FF, IE, Safari, Opera and Konqueror, but has only been properly tested in FF and IE.

Prototype’s structured way of doing Ajax was my main reason to choose the prototype framework. Furthermore it is also included in the great Symfony framework. In Prototype Ajax requests are written like this:

new Ajax.Request('myurl', {
method: 'GET',
crossSite: true,
parameters: Form.serialize(obj),
onLoading: function() {
//things to do at the start
onSuccess: function(transport) {
//things to do when everything goes well
onFailure: function(transport) {
//things to do when we encounter a failure

The cross site plugin simply allows you to do Ajax cross site, by specifying crossSite: true (line 3 of the above example). I will now cover some technical aspects of the plugin, but if you just want to start using it simply skip to the plug and play instructions below.

How it works – Technical Aspects

This plugin uses the dynamic script tag technique. This basically means that we insert new <script> tags into the Dom. Since this script tag is not bound to the same site you can send and receive data in the Ajax way. In its most basic form the javascript would be like this:

this.node = document.createElement('SCRIPT');
this.node.type = 'text/javascript';
this.node.src = '';
var head = document.getElementsByTagName('HEAD')[0];

In order to make it very easy to use with Prototype, or any other library for that matter, I decided to mimic the functions of the XmlHttpRequest. This is easily achieved by implementing the functions open, send and onreadystatechange. Furthermore I needed to specify the variables readyState and status in order to support prototype’s onLoad, onSucces and onFailure.

Detecting the loading of a script element is not that easy. Browsers such as Safari and Konqueror simply give no indication of this at all. One common solution to dealing with this is to use an interval and perform a check. The work at TrainOfThoughts however takes the beautiful approach of inserting a helper script. This exploits the fact that the dynamically added scripts are executed in sequence. This approach makes the plugin nicely cross browser compatible.

Detecting failure is rather cumbersome for the script technique. As far as I know there is no way to read the headers on the incoming file, or to inspect its contents through javascript. This leaves us with the rather blunt approach of setting a global variable using the server output. It works, but it could be prettier.

Plug and Play implementation instructions

Firstly you need to load the plugin javascript file: download cross site ajax plugin for the prototype framework 1.5.0.

Secondly you need to change your regular prototype Ajax request, by ensuring that you instruct it to use the crossSite and GET methods, as such (observe line 2 and 3):

new Ajax.Request(baseurl+'/comment/giveratingjs', {
method: 'GET',
crossSite: true,
parameters: Form.serialize(obj),
onLoading: function() {
//things to do at the start
onSuccess: function(transport) {
//things to do when everything goes well
onFailure: function(transport) {
//things to do when we encounter a failure

Thirdly you might need to rewrite some of your javascript code to accommodate the instant execution of the scripts.

Fourthly, if you want to use onFailure for any of your scripts you need to send some javascript instructions back from the server. You need to do this both on success and on failure (since a global variable is used). This is the javascript variable you need to set:

'var _xsajax$transport_status = 200;' Or
'var _xsajax$transport_status = 404;'

Symfony specific tips

Symfony detects if it receives a XmlHttpRequest and automatically turns off your debug bar and layout. Unfortunately it is not so kind to the script technique. So in your action you need to do this manually:

sfConfig::set('sf_web_debug', false);

Furthermore your validation files by default only look at POST variables (this one tricked me). To instruct them to look at both, simply mention

methods: [post, get]

at the top of your validation.yml

Since you will probably want to send html to the browser, I would suggest you put this little function (found in the symfony escape helpers) in your toolbox.

public static function esc_js($value) {
return addcslashes($value, "\0..\37\\'\"\177..\377\/");


The dynamic script tag technique opens up a wide range of possibilities. Personally I am very glad with the results and would like to thank Ralf S. Engelschall for his superb cbc work. Unfortunately I didn’t include an example this time. You will have to wait for the products’ launch:). Comments and improvements are always appreciated. Enjoy your cross site scripting!

Javascript &PHP &Prototype &Symfony &Web Development tschellenbach 25 Oct 2007 240 Comments

Symfony & Gravatars – easy implementation

Lets start with a small explanation. Gravatars are so called ‘globally recognized avatars’. Basically it is an open directory for avatars. If you didn’t get one yet, feel free to head over to

The implementation of gravatars for your site is already extremely easy. However if you are fortunate enough to be using Symfony, it becomes a real piece of cake. Quite a few people already use gravatars, including the Symfony blog. This number will probably increase quite a bit, given the recent purchase of the company by Automattic.

Gravatars are attached to an email address. Lets assume your program is already setting and getting the email addresses. All you need to get up and running with Gravatars is these simple 3 steps.

1. Extend your setEmail to do setGravatar as well

(somewhere in lib/Comment.php)

function setEmail($input) {




2. When getting the Gravatar, retrieve the full image code

(somewhere in lib/Comment.php)

function getGravatar() {
$md5email = parent::getGravatar();
$size = 45;
$rating = 'R'; // possible values [ G | PG | R | X ]
$url = '<img width='.$size.'px height='.$size.'px class="gravatar" src="'.$md5email.'&rating='.$rating.'&size=35" alt="gravatar" />';
return $url;

3. In your view template

Simply do: $comment->getGravatar();


Have a look at the result:
Gravatar implementation

PHP &Symfony &Web Development tschellenbach 19 Oct 2007 53 Comments

We love FireFox, 76%

A few days ago I noticed a bug in the Digg-this plugin for my blog. The javascript with this plugin was causing errors with Internet Explorer. The problem must have been around for a week or so, before I noticed it. Now my site doesn’t get too many visitors, but I would have expected someone to complain about it.

Looking in my stats it becomes clear why no-one has. Though only a small and insignificant sample, the traffic at my blog is strongly IE averse. Just have a look at the stats:

Overview of important browsers

Pie Chart of Overview

PHP &Symfony &Web Development tschellenbach 11 Oct 2007 5 Comments

Ajax for unique usernames

I always enjoy the logical thinking required for programming. For Symfony it is really nice how it all just flows together. I wanted to implement an ajax check for unique usernames. Something similar like how you see it on Twitter. Lets get started:

First create a validator in lib/validators/sfUniqueUserValidator.class.php

class sfUniqueUserValidator extends sfValidator
public function execute (&$value, &$error)
//check if the username exists
$c = new Criteria();
$c->add(sfGuardUserPeer::USERNAME, $value);
$user = sfGuardUserPeer::doSelect($c);
if (!empty($user))
$error = $this->getParameter('user_error');

return false;

return true;

public function initialize ($context, $parameters = null)
// Initialize parent

// Set default parameters value
$this->setParameter('user_error', 'This username is taken');

// Set parameters

return true;

Then in your view template use:

<?php echo observe_field('rusername', array(
      'update'   => 'userstatus',
      'url'      => 'sfGuardAuth/checkuser',
      'with' => "'id='+$('rusername').value",
  )) ?>

this will monitor an input field called rusername, and submit its value to the sfGuardAuth/checkuser internal url.

And to glue it all together, in the actions:

  public function executeCheckuser()
     $username = $this->getRequestParameter('id');
     $userValidator = new sfUniqueUserValidator();
     if (!$userValidator->execute($username,$error))
     return $this->renderText($username.' is taken');

     return $this->renderText($username.' is available'); 



Ps. any tips for posting code in wordpress would be greatly appreciated, for me it does the strangest types of things.

PHP &Symfony &Web Development tschellenbach 05 Oct 2007 10 Comments

Quick Symfony trick – The remote_function workaround

As mentioned in previous posts, Ajax in Symfony is a very easy experience. However sometimes the pre-made functions don’t provide all the functionality you need.

Unfortunately when you want to update a dynamically assigned part of the page you apparently need to write your javascript manually. In my case I had a list of comments where I wanted to be able to vote them up or down. So i needed the remote_function to update whichever comment the javascript code was called from. The remote_function however always adds nice quotes around what you type. So:

'update'  => 'obj',
'url'     => 'comment/giverating',

results in this javascript:
new Ajax.Updater('obj', '/frontend_dev.php/comment/giverating', {asynchronous:true, evalScripts:false})
This makes it impossible to refer to an object for the first argument of the Updater method.

How to update a dynamic area:

In javascript you can refer the location from which a function is called by passing the this variable in the function call. So in your function call you write:

link_to_function(__('+'), 'giverating('this)' )

Now in your actual javascript function you simply receive the this object and update it, as such:
function giverating(obj) {
new Ajax.Updater(obj, '".url_for('comment/giverating')."', {asynchronous:true, evalScripts:false})

Note that using the url_for php function to write the javascript ensures that a routing change will not upset the functioning of the javascript.

PHP &Symfony &Web Development tschellenbach 30 Sep 2007 Comments Off on Quick Symfony trick – The remote_function workaround

Quick Symfony Trick – The power of filters

After reading the Symfony book it was not clear to me how to deal with servers in the config setting. Say that you are creating a site on your local computer and then want to deploy it to your server. Some variables might be different, like in my case the image directory.

Symfony nicely support setting variables for development environments, but I found no such functionality for different servers. In the meanwhile I’ve created a simple filter setup which deals with the problem very nicely.

First set your config values in the frontend/config/app.yml:

  server: 'local'
    imagedir: 'http://comments/comment/images/'
    imagedir: ''

Next create a filter in lib/filters/setconfFilter.class.php:

class setconfFilter extends sfFilter
  public function execute($filterChain)
    // Execute this filter only once
    if ($this->isFirstCall())
define('SERVER', sfConfig::get('app_server'));
      define('IMAGE_DIR', sfConfig::get('app_'.SERVER.'_imagedir'));

// Execute next filter

Now to tie our little labor together set in frontend/config/filters.yml between security and cache:
setconf: ~
class: setconfFilter

Here you now have your own server dependant config settings, just use IMAGE_DIR in your template and it will refer to the correct location. If you are really lazy and do not want to change your app.yml every time you sync with production, we could automate that in the filter as well. Simple write something like this in the filter to define the SERVER constant:

define('SERVER', ($_SERVER['SERVER_NAME']=='comments')?'local':'production');

and remove the definition of the server from the app.yml.

Read more: About filters
Read more: the Symfony configuration system
PS. Also have a look at some of the great cheatsheets out there, from the Symfony wiki:

Admin generator cheat sheet
Directory structure and CLI
View: Partials, Components, Slots and Component Slots
Form Helpers
Javascript and Ajax Helpers

Server Validation
Model: Schema
Lime Unit & Functional Testing
ORM Diagram

PHP &Symfony &Web Development tschellenbach 22 Sep 2007 37 Comments

« Previous PageNext Page »