AD7six.com

Book review CakePHP 1.3 Application Development Cookbook by Mariano Iglesias

12 July, 2011

Show comments

I had this book on order since it was announced, it took a while to arrive, a while to find the time to write this review, and then a while longer to publish it. I could apologise to my readers here, but it's probably more time effective if I just send you both an email.

Anyway, the book: Mariano is no stranger to the CakePHP community, and through various things that he's published or contributed has demonstrated that he probably knows a thing or two about making apps with CakePHP.

Everything about this book set's high expectations. The author; the reviewers; the topics covered and the bee on the cover.

Positive Points§

Packt Publishing's format of Get ready, Do it, How it works is clearly a formula that works and works well for programming books, no complaints on that front, each chapter in the book seems focused and allows you to do, see it working1 and then analyze what you've done to understand better how the code is working.

This book assumes that you have a basic understanding of how CakePHP works, and therefore doesn't waste pages telling you how to, for example, install CakePHP. I like that. I mean, I didn't write The Book for it to be ignored or brushed over. That's not to say it's a book only for advanced users though - If you've ran through the blog tutorial and are capable of answering your own questions via google, you know all you need to know to pick up this book and make best use of what it presents.

I remember reading the first two CakePHP books and being quite disappointed. Why pay for a book that doesn't cover much more than what's available online; This book is different. The topics covered are almost mouth-wateringly good: RBAC, OpenID, 'more complex' SQL, Behaviors, Writing a Datasource, Routes in detail, Web Services, Shells, Sending emails from shells, Internationalization, Testing, using MagicDb. Some of those topics are sore points that keep coming up in support channels and I'm simply glad that there's now some well-written example describing how it works which can be pointed at and used. Others are topics which users will want to make use of but don't necessarily know how to go about it. Now they can pick up this book and be on the go in a few hours.

There are subtle best practices woven into the examples, for example the use of $this->cakeError('error404') - I think the cakeError method is underused in the wild because developers don't think to use it and instead do something like $this->render('/errors/404'); die;. There were various points in the book where the code examples gave new insight as to how to use code that I thought I knew well.

I'm sure by now (after publishing this, I'm going to look for the other reviews that I've been avoiding and read them.) there are plenty of positive reviews and Mariano's head is big enough. It was a good book and you'll probably be a better CakePHP developer for reading it.

Negative§

There isn't anything truly negative about this book.

I think the only thing I didn't like was that Mariano used only his own plugins. Nothing wrong with a bit of self promotion, but for example the OpenID section is only a couple of pages, and doens't teach you anything.

Pedantic points§

I debated whether to include these points at all. But if I didn't, this review would seem a bit short and fanboi-y.

I wouldn't feel honest if I kept to myself so, here we go:

Pedantic point one: DRY code execution§

When presenting code for comment (in answer to a question, or to help clarify a point), I would always strive for the idea behind the code to be understood rather than the code itself. That way, if you forget the code you can most likely at least still remember the idea or principle behind the code and probably arrive at the same or better code solution again. These ideas are present if everything that I write, and one of them is to apply DRY to code execution.

In the first chapter (Authentication) there's a section to allow logins with username or e-mail, if you break down what the code actually does it works like this if you try to login with a valid username and password:

  • User fills out the login form, and submits their username + password
  • Auth component automatically checks if there is a user with the username and password supplied
  • Auth component logs user in
  • Auth component redirects user to wherever your app wants to send them.

Here's what happens with the code from the book when user login with a valid email and password combination:

  • User fills out the login form, and submits their email + password
  • Auth component automatically checks if there is a user with the email-as-username and password supplied
  • Auth component does not logs user in
  • Auth component writes "Login failed. Invalid username or password" in the session
  • Application login function runs
  • Application looks for a user with the email and password supplied
  • Application logs the user in
  • Application redirects user to wherever your app wants to send them
  • User may be presented with the un-shown "Login failed. Invalid username or password" message and be puzzled

That means there are 2 attempts to login, and an un-shown message left floating around in the user's session. It may seem trivial, but I feel it sends the wrong message to the developer. Rather than disable the automatic login "feature" of the Auth component and handle both cases ([username + password], [email + password]), in the application login function with a simple OR query - the book's code let's cake do the work and then runs through the same logic again itself.

Pedantic point two: Cache confusion§

All of the examples in the book work[1], but one of the things I'm sure will frustrate readers is when they take the code from the book, tweak it a little and boom: Things break. One of these waiting landmines is the way caching is implemented in chapter four. In this chapter the afterFind method of a model is used to talk to twitter's api to get the tweets for users. Caching is implemented so that you don't need to talk to the api each time you query the profile model. However, the key used for reading and writing to the cache is 'tweets_' . $twitter, however the two parameters passed to the timeline function are $twitter, $count. Therefore if you call find on the profile model with the default count (10) it works, if you immediately call find again specifying a different count - you don't talk to twitter's api again, you simply get the previously cached result back.

I've seen what happens when users hit this sort of problem and can't understand why it doesn't work: They just turn caching off. If the same So, it's best to preempt such problems and include some kind of warning that if you're using caching at all: make sure the key you read/write to includes all the paramters that the relevant data is based upon.

Pedantic point three: Use Debugkit§

Chapter five gives an excellent tutorial on how to get a better SQL query log. But the question is why: Debug Kit does all this and more. There's also a hidden "feature" in the presented code. If you have more than 200 SQL queries (which seems surprisingly common ), only the first 200 queries get logged by default. Let's say you have 201 queries on the page you're investigating and of those 201 queries only the last one takes longer than the minimumTime set in the queryLog; the result is the queryLog shows you that the page contains 0 queries, and none of them were slow. That's misleading to the developer and is even hiding that they are running so many queries.

It's an interesting code example, but I don't feel you end up with anything you can or should use.

Conclusion§

Buy it.

I recommend this book whether you started using CakePHP today, or you've used it for years. I learned a few things from reading this book - which given the amount of time I've spent looking at the CakePHP code was both surprising and refreshing.

Congratulations Mariano on a great book.


  1. Confession! I haven't ran any of the code examples. Short of a typo/parse error though each example looks to do what it sets out to do