Tag Archives: symfony

Review of Panic’s Coda – One-Window Web Development for Mac OS X

I’ve recently been trialling Coda, Panic’s web development environment for Mac OSX. It currently costs $99 (about £65 at current rates) per licence, and offers a fully-featured 15-day trial before you burn your money. The version I’m looking at here is 1.6.2.

Coda sells itself as offering a complete environment for all-round web developers: somewhere to do your coding, a css tool for the design-oriented, and built-in subversion, FTP and SSH tools to transfer your masterpieces from your localhost to your live environment. In other words… an IDE (although it’s perhaps telling that it never uses that acronym in its sales pitch).

Coding
Coda offers a passable pure coding environment. It has all the basic text editing things: fancy colours, a certain amount of text completion and insertion (e.g. comment blocks). I don’t want to bore you with a list all the small details I found wanting in its text editor. Some of the bigger issues I had were lack of diff tool, and the inability to search across an entire project (or ‘site’ in Coda-speak). On the plus-side the editor did have a nice visual list of functions in your code. Macromate’s TextMate is often compared to Coda (a not entirely fair comparison, but anyway…), and to be honest in terms of code editing offers lots of things Coda doesn’t, and all the things Coda does. So, take your pick…

Styling
The css editor is pretty much what you get from tools like MacRabbit’s CSSEdit. You get to edit your css with a user-interface rather than hand-coding the stuff. That’s pretty much it. I’m left wondering just how useful Coda’s CSS tool is. If you’re proficient in CSS then do you really need a GUI to help you? If you’re not proficient in CSS then you’ll still be confused because Coda assumes you have some knowledge of how HTML and CSS work together. It’s a kind of irritating half-way house which I suppose might make life easier for half-way-house developers. I’m not sure.

FTP/SSH
One of the really nice things about Coda is that you can fiddle around with a local copy of your website and FTP it up to your live hosting account, all in a simple, integrated way. When you alter a file a little icon appears next to it in Coda’s file browser. Just click it, and off it goes. It really is very simple and easy to understand. So it has the same feature if you’re working in a more serious environment, where SSH is the only way to transfer? Erm… nope.

No quick-and-easy scp-equivalent? Let’s just stop here and digest what Coda’s all about. Those of you wondering what scp is will probably be ok with Coda. Those of you who know will probably realize that Coda’s aimed primarily at semi-pro developers who need to access hosting accounts with FTP. If you work in a professional environment where servers are locked down to such an extent that SSH is probably your only means of access, well one of Coda’s main selling points is lost.

To be fair there is an SSH terminal. My feelings are that this has been bundled to make Coda look more professional and justify a higher price-tag. Why is it any easier to click a button in Coda taking you to the terminal, than it is to switch to a terminal in a different window? Cmd-Tab? At best you might consider it a very, very minor advantage. At worst it confuses Coda and makes you wonder whether it’s trying to pitch itself at semi-pro or at professional developers. Is it for the Rails and Symfony developers out there? Who knows.

Preview window
Coda’s preview window lets you see your webpage as it would appear in a browser. Well, actually it shows you how you web page does appear in a browser, because the preview window is basically just a browser window. Again, I’m left asking the question: Cmd-Tab? Personally I found it more useful to analyze my CSS changes in Firefox + Firebug. Note too that the idea that you can review a single page of your website as a complete entity is a very out-dated and curiously amateurish one. The idea that ‘blah.php’ as a file actually renders a page of HTML is verging on the laughable: there will typically be dozens of files involved in rendering a single web page. Any serious (PHP) web developer would surely be using either home-grown code developed in a framework such as Symfony, or would be modifying available web apps such as Drupal or WordPress. The only way to view a ‘page’ in any vaguely sophisticated web app is to view it in a browser with a web server running. All this makes Coda’s preview window largely defunct. Once again, just Cmd-Tab to Firefox or something. Is it really that hard to do?

Subversion
A big selling point of Coda has been its inclusion of some kind of version control mechanism for your code. In this case subversion. The user interface is nice, although a little basic. Any checked-out code will display little icons next to the file name in the file browser. If you’ve made a change, you’ll see a little ‘M’ icon appear next to the file, which you can click to commit to the repository. It’s all very neat and rather lovely.
This does seem to be one area of Coda that works well. You will have to rely on terminal svn commands for some things, but most day-to-day stuff can be done very neatly and easily. Incidentally, TextMate includes very similar functionality. It doesn’t have the useful icons to let you know when something is out of sync with the repository, so for me Coda’s svn scores a point over TextMate here.

Conclusion
Coda looks lovely, and feels like something designed for semi-pro web developers. I can’t imagine hard-core designers and CSSers finding it particuarly useful, and hard-code programmers and coders won’t find its text-editing functionality up to scratch compared to much cheaper/free tools like TextMate, JEdit, or Eclipse. The preview window and SSH terminal features feel like a bolt-on, and honestly you’d have to be pretty lazy to find Cmd-Tabbing to another application much harder than pressing a button on Coda’s UI. The lack of integrated scp functionality will be annoying for many developers.

Coda costs $99, and could be a really useful value-for-money tool for semi-professional web developers who appreciate the convenience of having almost-TextMate, almost-CSSEdit, almost-web-browser, and SSH terminal thrown into one eye-candy package. Dreamweaver it ain’t. For starters Coda it has none of the HTML-building capability of Dreamweaver.

For about half the cost of Coda you can buy TextMate, CSSEdit, and use Firefox and an SSH terminal. Ok, you have to switch between them which is a slight inconvenience. But you do get more functionality for less cost. At the end of the day it’s all about what you’re comfortable with as a developer.

IWMW 2008 – day 2

So, we’re into day 2 of the IWMW 2008 conference at Aberdeen. Day 1 passed with much alcohol, dancing, Aberdonian ‘furry boots’, oh and some web stuff too.

I think the highlight was an excellent opening talk by Derrick McClure from the Centre for Linguistic Research at Aberdeen. It was a novel idea to have an opening talk by a linguist about the Aberdonian dialect (doric). But it worked, and to be honest this talk was more engaging than any of the other web-related talks that followed yesterday. I can’t even really remember any of the other talks, in fact.

Another highlight was a parallel session by Michael Nolan of Edge Hill University. They seem to be doing a lot of good healthy web 2.0 stuff there, and seem to have been given a lot of freedom in what they do. Edge Hill is a very new university, where student recruitment is king, and the website is viewed as a crucial tool in achieving that goal.

Edge Hill are using the symfony framework as a kind of php glue to bind together tools such as wordpress mu for blogging and bbpress for forums. They also developed their own google-style portal with php and jquery.

So now it’s day 2, I’m sitting in a boring talk feeling a little hungover. Oh well, it’s going to be a long day…

symfony 1.1 and 1.2

symfony 1.1 went live just a month or so ago, and in the relatively short history of symfony is somewhat of a revolution. In fact, the shift in a minor version number belies the effort and heartache that seems to have gone into the newer version, and one wonders at the implied major revamp that symfony 2.0 would someday involve. It saw the departure of a key member of the core team, as well as some major changes to the architecture of the framework as outlined in the diagram below.

symfony 1.1 architecture

 

The great thing about the platform is that being decoupled the classes can be used in isolation, so you can use some features of symfony and not have to use the whole system. In other words, you can build your own custom framework which uses just the bits of symfony that you want.

All this is great stuff, and should help symfony establish a place as the leading PHP MVC framework.

symfony 1.2 is released

But no sooner had 1.1 gone live than we heard that 1.2 is not just in development, but is actually imminent. The current release date is October, which is not very far off. According to the symfony blog, the main (and absolute must-have) feature of 1.2 is a completely revised admin generator system. Other features include bundling Doctrine with the framework and supporting it fully in the same way that Propel currently is. I’m sure a lot of people like using Doctrine, but for me Propel is just fine, and the differences in performance (at least where Propel 1.3 is concerned) are moot (see this blog for a good comparison

Worth upgrading to 1.1?

So should I wait for 1.2? I have a couple of live apps running under 1.0. They work just fine as they are, and I see no reason to update those to 1.1 just yet, only to go through the same process again in October. I think I’ll start using 1.1 in a dev environment for getting used to the new architecture, new command line system, etc. Upgrading to Propel 1.3 is also going to be a good idea for the performance gains.

I’m left wondering when symfony 1.3 will be out. Christmas?! Actually, my guess is that now that some of the major architectural changes have been made, things should start to settle down a little. Anyway, it’s great to see such activity in the symfony core development team: evidence that symfony is not just alive and well, but maturing very fast.

symfony’s sfGuard plugin and LDAP

A while ago I needed to hook up symfony’s excellent sfGuard plugin to some LDAP functionality. There are a couple of issues with the plugin and the readme which I think need fixing. In particular, there is no support for checking both LDAP and standard sfGuard passwords. This is absolutely essential (eg an admin user or guest users who aren’t in LDAP), and I’m somewhat amazed that there’s no provision for this. Moreover, the plugin structure generally makes it seemingly impossible (or if it is possible it’s just too horrible to contemplate) to write your own checkPassword() which does do both sorts of checking.

Anyway this post is partly an attempt for me to get my head round something which I’ve either totally misunderstood, or just isn’t well documented.

 

Confusing README

The README file that comes with the plugin is great, but it’s a little confusing for explaining how you might override its own way of checking passwords with something that’s LDAP-based. It’s really very simple to do when written out in plain English:

1. Make a file called myLDAP.class.php in your application’s lib folder. Put this in it:

class myLDAP extends sfGuardSecurityUser
{
}

2. Now put a method inside the class you just created:
public static function checkLDAPPassword($username, $password)
{
// put your preferred LDAP-checking code in here
// should return true or false
}

3. Add this to your application’s app.yml file:

all:
  sf_guard_plugin:
    check_password_callable: [myLDAP, checkLDAPPassword]

where myLDAP is the file called myLDAP.class.php that you created in step 1 above. checkLDAPPassword is the method you made inside myLDAP.class.php that you made in step 2.

And there you have it. Basic LDAP password checking.

 

How does checkPassword() actually work?

The above code is all very well, but what’s really going on?

Well, there are a couple of steps which I managed to work out:

1. sfGuardUserValidator contains a call to $user->checkPassword($password) where $user is a result of sfGuardUserPeer::retrieveByUsername($username)

2. PluginsfGuardUser (extends BasesfGuardUser) has a method called checkPassword() too. This calls the method you listed in your app.yml file (checkLDAPPassword in this case), or does a standard sfGuard password check (checkPasswordByGuard) if you didn’t specify anything:

public function checkPassword($password)
{
if ($callable = sfConfig::get('app_sf_guard_plugin_check_password_callable'))
{
return call_user_func_array($callable, array($this->getUsername(), $password));
}
else
{
return $this->checkPasswordByGuard($password);
}
}

Which it does depends on how you set up your app.yml file (see Step 3 above).

At this point, if you set up your app.yml correctly you’ll be in your custom checkLDAPPassword() method, which will do whatever you want it to do to check LDAP passwords. So long as it returns true or false depending on whether the check was successful or not, you’ll be ok.

Note that sfGuardSecurityUser class also contains a checkPassword() method. This basically does the same thing as the in sfGuardUserValidator, but in a slightly different way, and allows access to checkPassword() in templates and controllers through the $sf_user object. The important thing to realise is that both pieces of code end up calling the same checkPassword() method in PluginsfGuardUser.

 

So how about LDAP and sfGuard checking?

Now the fun begins. The problem is that it’s seemingly impossible to call checkPasswordByGuard() yourself from inside your custom-built checkLDAPPassword() method. Why would you want to do this? Because that way you can do some standard password checking first to see if your user is in fact a sfGuard user and not an LDAP user. Only if that failed would you do LDAP checking (I suppose you could do it the other way round if you wanted.) Even better, you wouldn’t need to alter checkPasswordByGuard().

So why is it impossible to call checkPasswordByGuard() ‘by hand’? As far as I can see, it assumes that you’re not in a static context, and that you have some kind of user object available. But of course, my checkLDAPPassword() is in a static context. It had to be that way because it was called by call_user_func_array() which uses the output of sfConfig::get() as an argument.

Sigh…

If you find a way of doing this, please let me know. Losing the will to live is merely one of the symptoms of battling with this sort of thing. I have a life to live.

All I can suggest to you in the meantime is to modify your copy of PluginsfGuardUser.php to allow both sorts of password checking. That’s what I did and it worked for me. It’s just a pity that you can’t override the checkPasswordByGuard() method in some way without changing the core of the plugin.

mini symfony

I recently read this post by Francois Zaninotto (recently an ex-core symfony developer) about modifying symfony to make it lightweight enough for ajax calls. As he puts it:

That’s when the idea of a “small symfony” comes. Wouldn’t it be great if you could get access to the model layer, the configuration, the autoloading, the user object, the helpers, and keep a MVC separation, without initializing the whole framework?

As symfony stands, it’s sometimes just a tad too bloated for the kinds of really fast responses needed to make ajax applications work. Francois came up with this solution, which is to cut out the call to sfController::dispatch()

But you still get enough to make use of things like the basic MVC design, autoloading, and helpers. I still haven’t tried it myself, but it seems like a really nice idea. Just a shame he’s no longer in the core team…

Zaninotto

Looks like Francois Zaninotto, one of the core symfony developers, has quit the team. He was largely responsible for the documentation, and co-authored the excellent symfony book, published by Apress.

One of the key successes behind symfony was the documentation. The fact that there was human-readable documentation, and not just an API, was a remarkable thing for an open source project. It’s surely to the detriment of the project that he’s no longer a part of it.

Hopefully he’ll continue to play an active role in the community, and might even consider writing documentation independently of the core team. We’ll just have to see what direction symfony head off in over the next couple of years.

symfony admin generator

The symfony admin generator is one of the best features of the framework. With just a couple of commands and a few changes to a config file, you can have something pretty close to a database access interface. There’s a simple built in security module, and sfGuard is fairly simple to understand if you need a more complex security module.

At first it seems like the admin code is pretty much pre-baked, and there’s not much you can do to change the behaviour of the interface, save change the config files. But one of the most useful things to know about the symfony admin generator is that you can do extra things. It’s not well documented, but sticking this method:

protected function updateModuleNameFromRequest()

in your actions.class.php file allows you to add in extra code each time anything is done in that module (substitute ModuleName for your own module).

For example, if you need to clear the cache each time something is done, put it here. If you need to update a set of data in a one-to-many relationship with a class, put it here.

It seems curious that more is not made of this function in the book and documentation, because it’s so useful.

And don’t forget you can also use the standard executeAction() methods, preExecute(), postExecute(), etc. in your module’s action.class.php file, in exactly the way a frontend action would work. This means you can add in any kind of custom action to the admin section of your application.

symfony redirect vs forward

I’ve found the distinction between redirect() and forward() a little tricky to draw. It always seems to sound obvious until you need to use them. I found a nice article here http://firebird84vn.wordpress.com/category/symfony/. To quote:

The choice between a redirect or a forward is sometimes tricky. To choose the best solution, keep in mind that a forward is internal to the application and transparent to the user. As far as the user is concerned, the displayed URL is the same as the one requested. In contrast, a redirect is a message to the user’s browser, involving a new request from it and a change in the final resulting URL.

If the action is called from a submitted form with method="post", you should always do a redirect. The main advantage is that if the user refreshes the resulting page, the form will not be submitted again; in addition, the back button works as expected by displaying the form and not an alert asking the user if he wants to resubmit a POST request.

OK, so basically a submitted form should be redirected by the action (as opposed to doing a forward). In other situations where you’re calling part of your own application, just use a forward(). Maybe I’ve missed something, but this seems pretty straightforward (pun unintended) after all.

symfony and LDAP

I’ve recently been looking at the essential (ie why isn’t it included in the core?) symfony plugin sfGuard. It offers are really nice, simple way of building a simple user, role, and permissions system into your symfony app.

The great thing is that with a little tweaking (documentation not great) you can add a custom LDAP lookup class, which overrides the standard built in user password lookup. Ok, you need to write your own class, or use a 3rd party one. But the basics of LDAP are built into php5, and it’s really not hard to do.

One problem I had was that sfGuard is designed to make it impossible to do an LDAP lookup and an internal check for a superadmin user. The reasons are a little esoteric, and have to do with mixing static and non-static contexts. Basically, the only option is to change one of the sfGuard library classes. Specifically sfGuardPlugin/lib/model/plugin/PluginsfGuardUser.php

Adding in this fixed things:

    if ($callable = sfConfig::get('app_sf_guard_plugin_check_password_callable_both'))
    {
      $result = false;
      $result = $this->checkPasswordByGuard($password);
      if (!$result)
      {
        $result = call_user_func_array($callable, array($this->getUsername(), $password));
      }
      return $result;
    }

which meant I had to use a special ‘check_password_callable_both’ option in the app.yml file. But at least this way it did checkPasswordByGuard() first, and then tried my added in LDAP class second.

Is there another way of doing this? I don’t know. Probably. But this seemed to work for me, and perhaps could be included in the sfGuard plugin by default. I guess I should get in touch with the developers to check…

 

symfony routes

Routing rules in symfony are a way of getting simple url’s looking the way you want. So rather than ugly things that show everyone how your system works like:

matthewbull.net/index.php?id=3&detail=false&category=true&year=2008

you can have things like:

matthewbull.net/id/3/detail/false/category/true/year/2008

Even better than that, using symfony’s routing system allows you to completely decouple a url from your code. It allows this because routing is set through a YAML configuration file called routing.yml. So you can change your url in this file without having to worry about its impact on your code, and changing lots of tests for request parameters in your controllers. A simple rule like:

routename:
  url: /*
  param: { module: mymodule, action: myaction }

will magically pair each value to its name, no matter what order those pairs appear in in the url.

Suppose I didn’t want all the request parameters written out in the url above, just their values, or perhaps a slightly more user-friendly parameter name. Something like:

matthewbull.net/3/nodetail/category

This is no problem to do in routing.yml because you can assign alternative names, default values, or no name at all to the values given in the url:

routename:
  url: /:id/nodetail/category
  param: { module: mymodule, action: myaction, detail: false, category: true, year: 2008 }

which will mean the url given above will be interpreted as follows:

first value you put after the domain name will be assumed to be the id

‘nodetail’ in the url actually mean use the parameter detail with value false

category will be true, and year will be 2008 even though no year has been sent (ie 2008 is the default year)

Routing is a great way to get user-friendly urls, generate new urls for the same code, or refactor old urls without having to touch your code. They are perhaps a little tricky to get used to at first, but fairly quickly make sense. The main thing to realise is that rules work from top to bottom, and the first one to match is used. Quite often problems or unexpected results come from not ordering the rules correctly. Always put more general rules lower down!