Archive for the 'Symfony' Category

YTM launch!!

No more beta for YouTellMe.nl
The website which is taking over the Dutch product comparison market is officially going out of beta @ 8 o clock.
Party in Amsterdam, Keizersgracht 182 :) Festivities starting right now!

13342_350348980430_784785430_9966158_5558110_n

Things are going well, looking very forward to international launch.
We’ve changed a lot since the first reviews!

13342_350352790430_784785430_9966172_7726367_n

Beter pictures coming after the event :P

PS. Thanks to Python and Django, for enabling us to beat the competition :)

PSS. Next2News, eduhub, come and join :)

Apache & Business & Css & Django & Dutch & Events & Javascript & PHP & Prototype & Python & Symfony & Web Development & YouTellMe tschellenbach 11 Dec 2009 150 Comments

Django vs Symfony

As you can see from the posts (one, two) I’ve always been a big Symfony fan. Symfony is really great, but my current favourite is clearly Django. I had to dive deep into python to use it, but it was well worth the effort.

Choosing Django:

Django has a few killer features which make it a better choice for many projects.

High Level Fields

As a starter there’s the usage of high level fields when describing your data model. This is best clarified by an example of a model definition in django:

class Author(models.Model):
   ip = models.IPAddressField()
   email = models.EmailField()
   company = models.ForeignKey(Company)
   picture = models.ImageField(upload_to='images/profile_pics', blank=True)
   homepage = models.URLField(verify_exists=True, blank=True)

Fields are specified by their purpose, such as Email, Url and Image. From this definition all subsequent logic such as form validation and file uploads are handled. The homepage field’s validation will even ping the url to see if it exists.

Read more: Creating Models (django project)

Form Handling

Starting with the knowledge that you have an email field you will often want a nice text input in your form with a regex to check if the email is valid. Django has all these standard use cases worked out for you. The following example clarifies this by using Django’s ModelForm. A model form is basically a normal Form class, with the fields pre-populated as one would expect it based on the given model.

#Form specification
class AuthorForm(ModelForm):
   class Meta:
      model = models.User
      fields = ('ip','email','picture','homepage', 'company')

#Using the form in the view (controller in Symfony terminology)
form = AuthorForm(request.POST, instance=author_instance)
if request.method == 'POST':
  if form.is_valid():
     form.save()
     return HttpResponseRedirect(request.path) 

#In the template (view in Symfony terminology)
{{ uform.first_name.label_tag }}
: {{ uform.first_name }} {{ uform.first_name.errors }}

Django will display a file field for the image field, a text field for the url (with validation), a text input for the email field and a select box for the foreign key relation. Saving the result of the form to the database is as simple as calling save on the instance of the form. Writing custom widgets and field types is straightforward. Currently many localized fields such as a Dutch postal code Field and widgets are available. Symfony has been trying to emulate the Django newforms library. Unfortunately the syntax doesn’t seem very friendly. (Pity php doesn’t have metaclasses)

Read more: Forms (Django book)

Superb ORM

Probably the largest difference is caused by the ORM. In PHP both Propel and Doctrine are nice projects, but simply quite inadequate. The Django ORM is syntax heaven if you are coming from php. A small example:

#Find the first 5 authors which have a relation to a company
#with the name YouTellMe (exact match) and site url that contains youtellme.nl
Author.objects.filter(company__name = 'YouTellMe', company__site__icontains = 'youtellme.nl')[:5]

The possibilities of the standard Django ORM system are quite good. Your queries will be optimized into joins if you call select_related, many to many relations are supported and polymorphic keys are as well. The only part it fails at is query optimization in terms of column based lazy loading and support for complex relations. Fortunately you can fall back to using SQL alchemy, which is Python’s most prestigious ORM layer. SQL alchemy allows you exact query control for performance tuning and many more options you did not know you needed.
However it isn’t (yet, i hope) fully integrated into Django. It would really be great to see a tighter integration with SQL alchemy, but even the Django ORM strongly outperforms Doctrine and Propel.

Read more: DB api.

Python

You could see this both as an advantage or disadvantage. Discussing the differences between Python and PHP is probably best left for a later post. Suffice to say that I found my programming productivity to be substantially higher with Python compared to PHP. The disadvantage is a smaller number of available scripts, developers and hosts. If you are in a position in which you can choose, you really should give python a go. There must be a reason why YouTube and Google do ;)

Read more: Python in 10 Minutes

Speed

When arguing with my colleague about the choice of framework we conducted a speed test between Django and Symfony using Apache bench. At the time I was arguing in favor of Symfony. We compared a lightweight PHP framework, with Symfony and Django. Symfony was stripped down for performance and was only about 30% heavier compared to the lightweight framework. When comparing it to Django however, the results showed that Symfony was only able to handle half the load Django could. Using Python and Django seems to have a substantial effect on your server hardware requirements. (Note that these tests were only intended as an indication for internal usage. We didn’t test enough scenarios to be certain how the outcome would hold up on a live site. )

Symfony Still Rocks

When working with PHP Symfony is still an awesome framework. In many aspects it is even superior to Django. There are quite a few things Django could learn from Symfony:

Generic validation Classes and support for automatic js form validation

When using Symfony your javascript form validation is automatically generated. This is possible because of the usage of generic validation classes. In Django this would be hard to achieve since the validation system is not based on reusable classes.

A debug toolbar


One Symfony feature which I really miss in Django is the debug toolbar. Having an overview of your DB Queries, config settings, logging messages and caching information is very convenient. Especially for debugging a site with caching the caching indicators in Symfony are awesome. These caching indicators simply show which part of the page are taken from cache and which are freshly generated.

DRY templates

Symfony has a simple but very pleasant template tag called a component. A component tag calls a specified view and renders the corresponding template. The typical use case for this tag is sidebar with news items. You will want to show this sidebar on many pages, but you wouldn’t want to have to call that code inside each and every view which needs the sidebar. Doing so would clutter your view and hinder template caching. A nicer approach is to use a component template tag which calls the view responsible for retrieving the news from the database and rendering the sidebar template. This way of allowing the template to invoke code allows for DRY views and templates.

Clear Javascript and CSS management

In Django including a javascript or css file comes down to writing the respective tags in the template. In Symfony these things aren’t left to the template, but are set by the code. This allows for a few neat features. For instance the usage of an ajax utilizing template tag (helper in Symfony) will automatically ensure that prototype.js is loaded on that page. If you would set a textarea to rich, Symfony will automatically figure out you need TinyMCE to achieve the desired effect. Furthermore it allows for a general config file where you specify which assets should be loaded for a certain combination of application and view (in Django terminology). The main benefit of such an approach comes when you combine your css and javascript files and want to optimize the groupings. Here an example of the Symfony config:

// In the view.yml - comparable to settings.py
indexSuccess:
  stylesheets: [mystyle1, mystyle2]
  javascripts: [myscript]

[php]
// In the Action - Controller in Django terminology
$this->getResponse()->addStylesheet('mystyle1');
$this->getResponse()->addStylesheet('mystyle2');
$this->getResponse()->addJavascript('myscript');

// In the Template - The view in Django

Both are great, but Django more so

Having used both Django and Symfony I believe the two frameworks can learn a great deal from each other. Fortunately many people seem to experiment with a wide variety of frameworks (Including at least one delicious developer, version 3 of delicious maybe? ;)). Django in general has some excellent features, which make it a better choice for web development. If you are somehow bound to PHP, Symfony is still a good choice. The Django community is buzzing and active like no other and I look forward to posting on the various features.

If you didn’t try it yet:
django-project.com
djangobook.com

Note: Looking to hire Python and Javascript Coders

YouTellMe.nl is currently looking to hire Python and Javascript programmers in The Netherlands. Drop me an email at thierry [at] youtellme.com if you would like to know more or want to suggest someone for the job openings.

Django & Symfony & Web Development tschellenbach 27 Aug 2008 1,004 Comments

A new job! – but no Symfony

Note: We are actively seeking to hire exceptional PHP programmers. More on the job offering at the bottom of this posts.

Zero BubbleAfter one of my posts got featured on Ajaxian many interesting offers hit my mailbox. One of them was actually from a startup right here in Rotterdam called ZeroBubble. I was happily surprised to find an IT startup in Rotterdam. Especially since after talking to them it became clear that they operate at the highest level of technical possibilities and have an absolutely amazing team. Two months ago I happily joined their ranks.

YouTellMe

The project we are working on is called YouTellMe. I don’t want to share too much about it right now, but surely I will have plenty of exciting blog posts coming up in the next months.
Currently we are working with some of the nicest tech on the net. To give some examples: our admin interface is written entirely in ExtJs, the site’s search is powered by Lucene, we use prototype 1.6 for great object extending, for ajax functionality we use yahoo history manager to keep it bookmarkable, the entire site has been optimized according to the Yslow principles and we are doing some interesting things with openSocial. Given all these you can’t help but wonder why we aren’t using Symfony.

Why no Symfony?

Personally I am a huge fan of the Symfony framework. The team at Sensio has done an absolutely amazing job. My opinion on the framework is best described by these blog posts Part1, Part2. However the current project we are working on has some special requirements. First of all the application’s calculations are very harsh on the servers. Combine this with a large amount of AJAX and you have some serious performance issues. The calculation speed has been pretty optimized by a colleague of mine, who wrote a python daemon for the task. Still it is essential to keep the PHP framework’s overhead to a minimum. Prior to my employment at this company it was decided that Symfony would be too slow to handle the task. This is a topic which often nags Symfony.

I am curious how fast Symfony can be. For the YouTellMe site I need a bootstrapped and blazingly fast framework. In the coming weeks I’ll be setting up some tests too see how Symfony compares to our home build framework. As a starters I’ll definitely relieve Symfony from the ORM and fancy routing. From there on I will need to test to see which components are slow and can be removed. The clean and flexible programming in Symfony should make this easy to do.

Our current framework is very lightweight. It even does not do auto loading. I for one have no clue what the speed gain is from not using auto loading and it would also be interesting to test it. The MVC structure is entirely home build, but the rest of the features use Zend.

If there are readers of this blog, which have gone through the process of stripping Symfony, be sure to leave some tips in the comments!

Jobs at ZeroBubble

ZeroBubble is currently recruiting talented PHP programmers in the Rotterdam area. We are located in the Beurs World Trade center. If you are into the latest technology and like to work with great people, software and hardware be sure to email me at thierry [at] zerobubble [dot] nl or my boss at joost [at] zerobubble [dot] nl. As mentioned we work with fun software such as Ext Js, Lucene, Zend, object oriented js with Prototype 1.6, yahoo history, Yslow principles and openSocial.
We are looking for both full and partime PHP programmers. Python, ExtJs, prototype, server admin, subversion and memcached knowledge are all nice extras. As a main quality though, you have to be excited about building a unique and amazing web application.

Business & Javascript & PHP & Symfony & Web Development tschellenbach 20 Jan 2008 201 Comments

Pake: propel-build-all-save-mysql

I tended to use fixtures in order to save my data before propel-build-all commands. In a discussion on syncing development database structure with production, Mike mentioned he uses mysqldumps. This is actually not a bad idea, given that it is faster and less error prone (propel will never bug you). The downside is off course that it only works for mysql.

Here 3 Pake tasks to automate your mysql dumping:

  1. mysql-dump-data
  2. mysql-load-data
  3. propel-build-all-save-mysql

Download all three pake tasks. To install them simply copy the file to myproject/data/tasks/

You will have to edit the file to configure your database settings.

Note that this is only a temporary solution. I personally would be very happy to see Propel making database structure changes.

I didn’t see any manual on creating Pake tasks. Improvements and suggestions are more than welcome.

PHP & Symfony & Web Development tschellenbach 11 Nov 2007 3 Comments

CommentHub.com – Developed with Symfony

CommentHubCommentHub.com has been developed with Symfony and is currently in Alpha testing. Needless to say it is a great pleasure to use Symfony and new features are being added effortlessly.

CommentHub.com aims to raise the standard in online commenting and make it more social. Commenting has become an important aspect of the internet, however a central system has not been available so far. CommentHub offers a plug and play comment system for your website. Whether it is your blog or any other page, you can add an advanced comment system in a minute. Currently it supports the following features:

  • Fast Ajax commenting
  • Threaded comments
  • Voting on comments
  • Gravatar images
  • Edit capabilities
  • Spam prevention and protection
  • Distinct look for admin comments
  • New comment notification emails for admins
  • Comment RSS Feed
  • Login (to remember email, name and site across websites)

Stronger email integration, personal RSS feeds and social features are all under development. Furthermore the system is already supporting templates. An interface to upload CSS templates will be available soon.

To see the comments in action just scroll down to the bottom of this page. Another example (with more comments) may be found by looking at my previous post.

Currently it is rather bootstrapped and in Alpha testing. To try it out for your website you can register for a webmaster account here (Enter mellow as your invitation code). The product is still under heavy development. Feature request, bug reports and comments are more than welcome.

To have a sneak peak at how easy the implementation actually is, view getting started with CommentHub. Plugins for major blogging systems will soon be available. (If anyone feels like contributing some plugins, it would be greatly appreciated.)

Thanks to Symfony for making the development such a pleasure.

Business & PHP & Symfony & Web Development tschellenbach 08 Nov 2007 1 Comment

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:

html

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

css

H1 {
color:green;
font-size:20px;
}

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:
if($_GET['prepend']==1)
$prepend = true;

change the stuff below this comment to:
// Get contents of the files
$contents = '';
reset($elements);
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 ../)

Conclusion

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 = 'http://www.serversite.com';
var head = document.getElementsByTagName('HEAD')[0];
head.appendChild(this.node);

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);
$this->setLayout(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\/");
}

Conclusion

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

Next Page »