RSS Feed for comments

Myth Busting CakePHP

Written on Thu, Jan 19th 2012, 18:53 in

Myth busting CakePHP

PHP, unlike other languages, lacks standardization in several aspects when it comes to choosing a set of tools for web development. One of the most miscellaneous and often confusing areas of the most popular language on the web is frameworks, a quick google search will show you no less than 30 different known PHP frameworks and there are plenty more in development as evidenced in the most recent PHP projects on github, every other day a couple new a created.

Being that this language is so widely adopted amongst very different kinds of developers across the world and with varying experience levels, there is no surprise that there are very well defined groups favouring one framework or the other alleging indisputable superiority of their tool of choice. During my years using PHP I've seen numerous people on IRC, forums, twitter and other social sites looking for advice on choosing a framework, and have also perceived increasing amounts of uncertainty and false statements about CakePHP when reasoning against using it as the tool of choice for rapid application development.

This article does not intend to show the advantages of using a framework, which are already well discussed and established in many other blog posts, books and articles, nor tries to give a comparison among different tools, and by no means pretend to diminish or talk against the use of other PHP frameworks. The primary objective of this writing is answering to most common misconceptions around developing sites using the CakePHP framework.

Is it Rapid?

For several years the term RAD or "Rapid applications development" has been used for many web tools to publicize themselves. It is interesting how people read and use this term without actually realizing it refers to software development methodologies and not only the act of coding an application.

Most remarkable attributes of RAD is the development of applications in an iterative way based on the use of prototypes. While CakePHP cannot convince you of building your software iteratively it does a pretty good job at prototyping. Inclusion of tools such as a code generation tool, application scaffolding and automatic generation of CRUD interfaces makes this framework one of the most desirable tools for people looking for delivering functional prototypes to clients in a timely fashion.

Other characteristics of rapid application development include the reuse of components. This is actually one the areas where CakePHP is king, counting several hundreds of open source plugins on the wild to enhance the rapid prototyping experience such as user management packages, css scaffolding, advanced administration interfaces, and lots more. If you wish to take a look at a compelling and very complete list of available CakePHP extensions, visit http://cakepackages.com.

Finally, in more modern conception of RAD, applications should be constantly tested and delivered. Only a handful of the popular PHP frameworks offer the ability to automatically test your application using unit test of functional tests integrated with the browser, and CakePHP is amongst them. The project itself puts a great deal of emphasis on creating, improving and maintaining its own set of automated tests which can be seen as the safety net on which users can rely as an insurance of good quality code.

It also offers the ability to create test skeletons for your own code and makes it blatantly easy to integrate them with your data set and business rules. In CakeDC we also have plenty experience in quickly setting up continuous integration environments to quality-assure the code we produce and constantly deliver new versions.

RAD is not determined by the tools you use, but how you use them. CakePHP offers several features that makes it easy to adapt to rapid methodologies such as eXtreme Programming, SCRUM, and other, but it will always be up to the developers to take advantage of these and deliver outstanding quality applications.

Is it too strict?

This is by far the most common myth about CakePHP and it is a present misconception amongst beginners and people that have not read but a few pages of the documentation. The reasoning behind this is that the framework implements a very tight and strict MVC pattern which you can divert from only with lots of extra work. This idea stems in four different places, let's talk about them individually:

Restrictive conventions

Conventions is where CakePHP derives most of its agile development power from. It saves developers time and tedium of figuring out how to name things, where to to put them, what would be their roles, etc. Nevertheless, for people coming from different backgrounds, have never used a framework before or wished to start implementing one using an old legacy database, it seems daunting to adapt the framework conventions to their needs.

Good news is that CakePHP can very easily adapt to any naming convention you like. Sure, you are still required to follow file naming conventions, so the framework can locate your classes, very much like other languages such as Java requires you to name files a certain way. Nevertheless, following the Java example, it is well know how you can code Java applications to suite a very wide rage of needs. Same analogy can be made with CakePHP.

In all my years as a software developer I've found several databases which table names can hardly be read, and which foreign key naming is absurdly complicated. None of this is a roadblock for implementing a system using CakePHP as the base framework. I'll leave you a few hints for bending conventions using a bit of configuration:

  • Choose a human readable model name, the table associated with it can be configured using the $useTable property on the class.
  • Foreign key names for associations can be configured in the association arrays. If you happen to have complex association which cannot be modelled through the use of a single foreignKey field, set the configuration option to false and use the conditions array.

    class Students extends AppModel { public $useTable = 'sys87_stu_tab'; // Table name not using conventions

    public $belongsTo = array(
        'School' => array(
            'className' => 'School',
            'foreignKey' => 'id_sys_schoo_pk' // A odd named columns used as foreign key
        ),
        'ClassRoom' => array(
            'className' => 'ClassRoom',
            'foreignKey' => false,
            'conditions' => array(
                'Student.odd_field = ClassRoom.class_number',
                'Student.is_enrolled' => true
            )
        )
    );
    

    }

  • Controller names do not determine how the url will look like. You can create custom routes very easily to map any controller in your system. Do not choose controller names because of how they will look like in the URL

  • The same thing applies to action names, you can name them whatever you like, the router can be configured to map to any controller function.

  • View template files are located in folders named after the controller and action for your own convenience, but you can use the render() function in the controller or the $viewName and viewPath properties to render any file or your liking.

CakePHP embraces the convention over configuration motto, but it just means it is a preference in how we choose to do our code, a little configuration is always possible to change defaults.

All actions require a view template

There is no doubt the time will come when your application will need to perform an action and not render any text to the client as response, perhaps you only want to log some data, redirect the user, save something to the database, or just execute a command and there is no real need to report back any text. Another valid reason is when building APIs sometimes it is faster to return any serialized data directly and having an extra layer will only slow things down.

Unlike other frameworks, CakePHP tries to render by default every time, if you think about it this is the perfect behaviour, having actions with no views is the exception and not the rule, so it is saving you for the tedious repetitive task of telling the controller to render it for you. There are a couple of extremely simple ways of switching off this default:

public saveSomething() {
    $this->autoRender = false;
    $this->Something->save($this->request->data);
}

public function apiReponse() {
    $data = $this->Somthing->find('all');
    $this->set(array('data' => $data, '_serialize' => array('data')));')
}

Both actions shown above will skip the template rendering process. The first one use the special $autoRender property to instruct the controller to bypass the View layer, the second one is a new feature introduced by the newest 2.1 version to render a serialized view as requested by the client (either XML or JSON) out of the data array.

As you see it only took only line of code to have optional views. Piece of cake!

All Controllers require a model

Similar to the optional views reasoning, there are valid reasons for having controllers with no associated model. This is a less common problem particularly after the release of CakePHP 2.0. As in previous examples, just one line of code is needed in order to decouple controllers from any possible model.

class MyController extends AppController {
    public $uses = false;
    ...
} 

Variable $uses hints the framework to not associate any model to the active Controller, one line of code for disabling stuff contrasts with other frameworks where you have to explicitly load everything and it is very common to see hundred of class importing lines. As a side note, in case any of you is wondering, there is no performance hit by using the default behaviour, models are only used when requested.

It is not possible to get data from another controller

To begin with, the above statement is incorrectly formulated. Controllers are not meant to share data, and controllers are also not tied to a single source of data. This is also a very common misconception among beginners. They think they are required to encapsulate all operations for a data source in a single controller and then they are faced to the challenge of displaying data using the logic they already made in other controllers.

This is actually caused by the belief that most of the logic should be put into controllers, instead of models. This is simply not true. A good application always has most of the code living on the model layer which is the natural place for managing data and foster method reusing.

These are a few tips for working with data coming from different models:

  • Do use associations, if a model is correctly linked to another, then when pulling up some data from one, you will also get data from the other, display logic belongs to the view layer. If you have Posts and Comments, use associations to bring data from both tables down to the view, and make use of helpers and elements to correctly format and render this data.
  • Models can be chained when associated correctly, from a Posts controller you can access the Comment model using $this->Post->Comment
  • Do extract any common method done in the controller up into the model. For instance if you coded some special logic from finding comments and want to use the across your application, then having this method in the Comment model will be the most appropriate place. Models can be included in any controller using $this->loadModel() or the $uses variable.
  • Use requestAction() if you want to embed reusable widgets in your views, this lets controllers and models do their best job and helps you keep your views tidy and readable.

Does CakePHP's ORM suck?

Short answer is... Some times. But all ORM implementations do once in a while. In particular CakePHP's ORM implementation is starting to show its age. It was started as a much ahead of its time ActiveRecord-like data layer, and it was way ahead of the competition for many years. Both PHP and other ORM implementations have progressed, whereas it seems like we have not progressed as fast as others did.

This is part true and part a misleading statement. One of the biggest complains about the ORM is that it reports data using plain PHP arrays instead of objects. There are pretty passionate defenders of both ways of data representation. The clear advantage of using arrays is that they are less expensive both in memory and performance time, and also there are several times more array functions in PHP that for any other structure. We have to face it, arrays are king in PHP, there is no other structure that is handled so easily and efficiently as arrays in this language.

On the other hand using objects enables logic encapsulations and easier vertical growth of your application, there are numerous clear ways in which embracing full object oriented paradigms will benefit your applications in terms of readability, and code structure.

Is CakePHP lagging behind? Absolutely not! At this point you can use plugins to swap the return types and even the model layer completely to suit your needs. Also the project itself is working toward its next major version that will feature a new Model layer addressing long standing requests.

A couple of such plugins are CakeEntity (https://github.com/kanshin/CakeEntity) and MongoCake (https://github.com/lorenzo/MongoCake), the first one allows you to transparently convert data finds into objects and the second one replaces the model layer to use the popular Doctrine ORM while integrating cleanly with the rest of the CakePHP ecosystem.

Getting comfortable using the built-in ORM can take time, as with learning any other library, but it is indeed very powerful and flexible once you understand the basics. For those who need something else, there are already implemented alternatives that can be easily integrated to the framework.

Will CakePHP scale?

There are several benchmarks comparing PHP frameworks performance. I will not argue against the validity of such comparisons, but the most remarkable similarity among them is that they only measure time for rendering a page without any data access and using no extra libraries.

In all of the benchmarks I have reviewed CakePHP is placed among the slower ones, not the slowest, but definitely not close to the frameworks that show on top of the chart. When reviewing the code used for benchmarking you realize that other frameworks purposefully disable features (such as layouts) in order to show higher to the chart. The question is, what is this actually measuring? No surprise they all claim to be the "fastest PHP framework".

That is not a real comparison, if you want to have applications displaying static content, using html is a better tool for the job. A fair benchmark should be done by displaying the same data, using common real-life examples. There are, nevertheless, a couple of benchmarks out there using actual applications with the same features in every different framework.

Examining those you see that strongest contenders lose a great part of their winning margin. It is clear that database and session access are the real performance hitters, and with complete confidence, building larger systems will lower the difference more and more. Input and output operations are several order of magnitude bigger than any framework operation.

A good example is comparing this two numbers, the amount of time taken by my laptop to load the CakePHP default app homepage is 11ms, doing a query in my database to look rows from the comments table and their authors takes 27ms, that is more than twice the time it took the framework to boot, fetch some data, build a view and render it to the browser. What do you think is worth optimizing first?

Take some advice from the giants in the industry. If you have followed the technical evolution of sites such as twitter and facebook closely, you will be reminded of important changes they made, once they realized the slowest part of their application was not actually the framework or language they were using, but how they were accessing the data.

For instance, twitter was built using Ruby on Rails, and performance quickly started to degrade once the became popular, is the framework to be blamed? Not at all, they very clearly explained that their flaw was in the application architecture, they initially designed the app to be like a blog, but they should have actually modelled their database to act like a messenger. Did that prevent them from being extremely popular and wealthy? Not a bit.

What we can learn from the twitter example is to not focus prematurely on optimization, it is a lot more important to deliver the application first, but if you happen to have a good application and data architecture you will definitely help yourself scale better. Their performance problem has been solved differently at the same pace as they grow, every new few million users adds new challenges.

CakePHP does help you sort out those challenges by offering excellent caching capabilities in multiple different caching engines, such as the popular Memcached service. It also helps you fine tune your HTTP responses to make better use of reverse proxies, and finally there are plenty of user extensions available that will help you reduce the fat in your database access, and cache static or semi-static content for maximum performance.

Do not let the FUD confuse you, building an awesome application has very little to do with selecting the fasted PHP framework out there, it is about having the right mindset, a good idea a good tools to help you deliver quality code in a timely fashion.

Back to José's articles

Comments:

Add comment
openID

What is OpenID?

OpenID is a new open standard that lets you sign in to web sites with a single URL that you own. This URL can be your homepage or blog, or it can be provided to you by a web site you use. In either case, you only have to sign in once to your OpenID provider and so you only need to maintain a single password.Learn more.

How is CakeDC using OpenID?

You can use your OpenID identity when posting comments on the site. When you see a form field with OpenID logo entering your OpenID identity is sufficient to allow your post. We also accept Google or Yahoo! identities. Simply use either "google.com" or "yahoo.com" and our OpenID library will locate your information from the appropriate source.