Navigation

No Piece of Cake

Welcome to all of you on webmozarts.com! Whether you are a PHP developer, a symfony power user or just getting started in object-oriented web application development – this blog is for you.

With our first post, I want to talk about symfony and where this blog is heading. And I don’t mean “symphony” as in music – no! Scrap that “ph”. It’s “symfony”, one of the greatest web frameworks that has been developed in PHP5 so far. (If you ever dare to write symfony with “ph”, tiny kittens will suffer!)

Symfony is by a large part a product of Fabien Potencier’s ingenuity and dedication. I want to deeply express my respect for his work at this point. The framework is a very well-thought piece of work and can immensely boost your productivity.

The amount of features and the complexity come with a drawback though: It takes a lot of time to learn how to develop efficiently with symfony. Many PHP developers are overwhelmed by the object-oriented concepts applied in the framework. Many call for a simplified version and I must agree that symfony suffers some usability problems lately. But why is that and how can we improve the current situation?

The Average Developer

Let’s face it. The average PHP developer knows nothing about “Design Patterns”, “Unit Tests” or “Refactoring”. In the course of my job I had to interview a lot of potential employees. Not only once I faced total ignorance when I talked about these or similar topics. Even basic understanding of PHP could not be taken for granted! What struck me most was that many of these people programmed PHP applications for a living, some of them for more than a decade.

What happens when you confront these developers with symfony? It’s like when my grandma got a computer. It took so much time to teach her using the mouse that telling her about how to write a letter would just have made no sense.

In my opinion, every PHP developer who is familiar enough with the language itself should be able to learn symfony.  If we want to raise the general quality and standards of PHP applications, we must reach these developers. Lowering the burdens for them to learn the framework is crucial for its future community.

Back To Basics

The excellent documentation of symfony obviously is a great help. I remember when I read the symfony documentation for the first time. Its great writing, the presented simplicity of powerful features really struck me. Every couple of pages I was astonished  by the fact that programming in PHP could be so easy! I was torn apart, because I had to read on while I just felt the urgent desire to start programming. Anything.

Unfortunately, this feeling of simplicity quickly fades away when you get started. Questions over questions arise. Where do I put that code? What method again should I use? Is it better to write it this or that way?

Now this is the case for every major programming library. You can’t expect to read a little of the documentation and be an expert (in this case it probably wouldn’t even be worth to use the library). What you can do is look at the code of others, extract the common ideas and find out for yourself how to best organize your code.

What you are searching for is generally referred to as “Best Practices”. The Jobeet tutorial did a great job at presenting such best practices. But further than just being documented, the described concepts must be simple enough for you to remember them next time you need them. And this, partly, is symfony’s weak point.

Forms By Example

To demonstrate my argument, let’s look at how to create a basic profile form in symfony. This form should allow to edit a user’s name, email address and password. The name should only be editable by administrators, while the password should be entered twice to make sure it was entered correctly. The maximum length of the name is 15 characters and the password should not be the same as the name.

Let’s start with the constructor. We need to alter the form depending on the authentication of the current user session, thus we pass the user object to the form.

// lib/form/doctrine/ProfileForm.class.php
class ProfileForm extends sfFormDoctrine
{
  protected $user = null;
 
  public function __construct(sfUser $user)
  {
    $this->user = $user;
  }

So far so good. Now let’s configure the form’s appearance and validation logic.

  public function configure()
  {
    $this->setWidgets(array(
      'email'          => new sfWidgetFormInput(),
      'password'       => new sfWidgetFormInputPassword(),
      'password_again' => new sfWidgetFormInputPassword(),
    ));
    $this->widgetSchema->setLabel('password_again', 'Password (again)');
 
    $this->setValidators(array(
      'email'          => new sfValidatorEmail(array(), array(
        'required' => 'Please enter your email address',
      )),
      'password'       => new sfValidatorString(array(), array(
        'required' => 'Please enter a password',
      )),
      'password_again' => new sfValidatorPass(),
    ));
 
    // implement custom validation logic
    $this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
      new sfValidatorSchemaCompare('password_again', '==', 'password', array(
        'invalid' => 'The passwords must be equal'
      )),
      new sfValidatorCallback(array(
        'callback' => array($this, 'comparePasswordAndName')
      )),
    )));
 
    // administrators may enter the user name
    if ($this->user->hasCredential('admin'))
    {
      $this->setWidget('name', new sfWidgetFormInput(array(), array(
        'max_length' => 15
      ));
      $this->setValidator('name', new sfValidatorString(array(
        'max_length' => 15
      ), array(
        'max_length' => 'The name must be 15 characters or longer'
      );
    }
  }

Phew, there’s already a lot going on. We need to know about the widget schema and the validator schema. These are tricky, because for example setWidgets() is called on the form directly, while setLabel() is called on the widget schema. Don’t get that wrong.

Then you need to pass the error messages that are displayed when the fields are not filled out, because the default “Required.” is not really usable for a customer.

The post validator is especially tricky. Once you understood the concept, you need to remember to set it on the validator schema, use sfValidatorAnd with a couple of braces thrown in and mix it with sfValidatorSchemaCompare and sfValidatorCallback. Not easy.

The last thing is to add the “name” field and validator only when the user is administrator. This especially causes complications, because then the field “name” is not always present in the form values, which requires extra checks and template customizations from you. We need to configure the “max_length” constraint twice, once on the input field and once on the validator.  Again we override the error message, because the default is not usable.

What is missing now is the method that checks that the password and name differ:

  public function comparePasswordAndName(sfValidator $validator, array $values)
  {
    // if the field "name" is not editable, it does not exist in $values
    if (array_key_exists('name', $values) && $values['name'] == $values['password'])
    {
      $error = new sfValidatorError($validator,
          'The password must not be the same as the name');
 
      // throw an error schema so the error appears at the field "password"
      throw new sfValidatorErrorSchema($validator, array('password', $error));
    }
  }
}

If you want to set an error for the form, you basically need to throw an sfValidatorError, which behaves like an exception. Because the error should be displayed at the password field, we need to wrap it with an sfValidatorErrorSchema instance and associate it with the fieldname “password”.

This form is not yet complete. The logic to save the profile is still missing, but the above implementation pretty well demonstrates what I want to show.

Tying It All Together

If you go back and re-read the form requirements, you will see that these requirements are not uncommon even for very basic websites. Still the implementation requires you to know many different concepts. Altering the form based on the authentication status, modifying field labels, limiting field lengths, implementing custom validation logic, all of this is so common that it should be far easier. The default error messages should only need to be overridden in edge cases. Don’t expect that the average developers that I spoke about will get that right.

In my opinion, symfony must strive for absolute simplicity. The easier it is to explain its use, the quicker new developers will grasp the real power that lies under the hood of this framework. Together with a well-defined set of recommendations and best practices we will be able to teach new developers and expand the community. And we will be able to help those “average PHP developers” to step into the world of powerful object-oriented concepts.

This is the goal of this blog. We want to analyze our work and present best practices to improve your development. We want to speak about symfony’s strengths and learn about symfony’s flaws to point out possible solutions. We want to teach object oriented concepts in PHP5. We want to investigate what the community needs and try to find answers. Of course, we also want to present our own work. And last but not least, we do want to hear your feedback.

In the coming weeks I will think about possible solutions to the above problems with the Forms framework and post them on this blog. I would also appreciate to hear your ideas.

What is your experience with this new component? Is symfony simple enough for you?

Posted Tuesday, April 7th, 2009 at 21:51
Written by: | Filed Under Category: Thinking Ahead
You can leave a response, or trackback from your own site.

13

Responses to “No Piece of Cake”

Björn Ahlers

Hi there,

on the one hand I agree with you that symfony could be easier for beginners – as I remind my first steps around december 2006… But on the other hand I think that good software requires a basic knowledge of some of the common design patterns, refactoring and last but not least a understanding of OOP. And for the last one, I met several colleagues with no idea what OOP means.
The problem is PHP. Most of the “elder” developers are “still” using PHP the procedural/modular way.
Here I’d like to point out that I don’t want to start a discussion about programming paradigms and which is the best.
So, back to the track: As far as I remember, I had the same problems until I faced the fact, that symfony is heavily build on OOP: I wanted to use symfony, I had to learn PHP-“OOP” and all that stuff around that paradigm. Until that days I used PHP the procedural/modulare way. Fortunately I started with Java two years earlier (2004) so it wasn’t so hard to transfer that knowledge to PHP.

symfony isn’t a framework to learn in 24 days. Jobeet or Askeet just giving a brief overview what’s possible and are to viewed as an good entry to symfony. I learn every day I use symfony. If I look at my first lines of code “for” symfony I blush – but that’s normal, I think.

The “new” concept for Forms are great. I have to admit, that it took a moment for me to point on the benefits, but IMHO the new way is much quicker than the old style with symfony 1.0.x.

That’s a great opening article you got there!

I agree that symfony must strife for simplicity, although I never again want to miss what features and wide options are already available (the forms example you mention is one of them). Building bridges between the existing great codebase and a much simpler approach will probably require some meta framework in between that can be used on demand, but that’s definitely where a part of the symfony development process should be heading.

Welcome to the world of symfony bloggers!

David

A great introduction to symfony and to what I think is a need as well for the future of symfony development. One down side of the forms framework in symfony > 1.1 is that if you need to quickly create small forms with perhaps one or two fields and limited to no validation that the forms framework becomes a hinderance and not an advantage, as beautiful as its OO construction is.

One way I can think to help simplify this is to allow for the quick creation of forms through classes that create “smart” defaults to help make small forms creation simple. Because of the complexity required to define forms we only use it in our projects for forms that will be re-used and fall back to the symfony 1.0 helpers for everything else.

IMHO, symfony is not a framework for such a stupid developer :)

symfony is by far the best PHP framework, but you HAVE to know what we’re talking about. It’s not a framework for beginners, or people that don’t even know what a Singleton (just for say one pattern) is.
No doubt it takes a lot of time to study it, at first, but once you got the big picture, you know how to do almost everything, and you can really do it..

The Form Framework was not created for lazy developers who want something to get things done quickly. It’s raw power :) And the drawback is that is a bit complicated, at first. But it surely worths the pain :)

Alan Jones

Seems this was already discussed long ago, and Fabien’s answer was: I don’t want simplicity, I want pure OO structure. If you’re not good enough to get symfony quickly, then stay with Code Igniter. His reaction was abrupt enough to make the co-founder of the framework leave the project.

http://redotheweb.com/2008/09/23/document-driven-development-in-practice-rethinking-sfforms/

Bernhard

@Alan: I don’t think simplicity and pure OO structure exclude each other. The question is how, how complicated and how feature-rich you design your classes.

In my opinion the YAML format Francois suggested looked nice at the first glance, but had its flaws, as Fabien pointed out. You would have had to learn everything twice, once how you do it in YAML and once how you do it in PHP. I think we need a pure PHP concept: One with good conventions and an easy to use interface. One that requires only very few modifications in common cases.

The only Symfony’s flaw is that is made out of PHP ! Which still suffers from its reputation of being a crappy easy-to-use scripting language.

What makes Symfony a very promising framework is that it brings OO programming, best practices and good designs to the PHP world, and aims at raising the overall quality of PHP-based softwares.

I think that rather than simplifying Symfony, it is the documentation that needs work. The Jobeet tutorial goes a long way towards easing in new users, but the API just doesn’t give enough information regarding what a class or method is meant to do in my opinion.

I have to agree with ErisDS – symfony’s biggest current problem is the documentation. I’ve been using it since .6x and I’m just starting to use the new forms framework – I like the power and flexibility but spend most of my time tracking down examples of how to do simple things. The documentation covers very general examples of each capability (not just the forms documentation but the overall framework), which would be fine if the API was thoroughly documented – but it’s not. So then it’s off to the forums in hopes of finding someone else who’s solved the same problem… but now I find myself often coming across solutions that don’t work anymore because so much has changed since 1.0. On my latest project I easily spent as much time combing over the documentation and forums for solutions as I did writing actual code… and I’ve got a couple years experience with the framework! I can’t imagine what its like for someone who’s just starting at this point.

So a little while ago, I read on a blog somewhere that the main guy who was in charge of all the documentation up until 1.2 left over differences with Fabien. Thing is, yes OO-PHP– do it, it’s a good and IMHO, necessary paradigm for a successful, powerful, and extensible PHP framework. But it can still be simple.. I think Symfony developers spend more time than devs with other frameworks just trying to figure out “OK where is the appropriate place for this?”. Maybe even if someone made a map of the object hierarchies and the typical file/folder layouts– that would make it easier for people to see the “bigger picture” easier.

Overall the documentation I find decent (albeit a bit verbose at times), and the while the API docs list all methods and objects, I find the comments on the parameters of most function quite lacking, to the point where I often rather just bust open the code itself to see wtf this thing is expecting.

Les

Frameworks are complex today because today’s Internet users expect decent software written and in a lot of cases, this involves some complexity.

If person’s who want to develop for the Internet are unable to deal with that complixity, then I would suggest another vocation – you are never going to get away from a given level of complexity so deal with it.

Not everyone develops simple websites with limited backend interactivity, so if anything more than that is beyond your capabilities, look for another job.

I loathe people who complain about this framework or that framework, and after all the work that so many people have put into it, there is a serious lack of respect for the real developers who do a damn good job and get absolutely no thanks.

So yer,… either just get on with it and learn to develop to the standards set down by the framework or get off right now.

Les

Umm

> So then it’s off to the forums in hopes of finding
> someone else who’s solved the same problem…

Documentation or not, shouldn’t you have the learnt skill to be able to cope regardless? I would think so, in fact I should expect so, if I was employing you.

Going to a forum to look for a solution or answers certainly isn’t the sort of behaviour I would expect, nor would I accept it – forums generally, are for those who lack skill in my opinion.

Do you lack the skill? Apparently you do…

Bernhard

@Les: If you have read my post carefully, you see that I have a very deep respect for the developers of symfony. Also, I’m not speaking about the complexity of the framework itself, but of the complexity of its API.

Judging someone as being a bad developer because he doesn’t want to deal with unnecessarily complicated APIs is nonsense.

Leave a Reply

 

Additional Resources