Category Archives: CakePHP

Book review: CakePHP Application Development

CakePHP Application Development

In the beginning of December I’ve been asked to write a review of a book called CakePHP Application Development. The interesting thing was that I received a copy of the book exactly on my birthday – 29-th of December (probably consequence, but it was really nice). In this article I will write about what this book covers and my opinion of the content. Hope it will be a good guide for these of you who will decide to buy a copy of it from Amazon.com.

What this book covers

First two chapters start with some theoretical explanations about concepts and patterns which are used in the Framework as well as the process of installation of the framework.

The next chapter explain how to build a really simple application. The readers could use to with the framework way of coding, everything in this chapter is hand crafted, so people could actually see how it’s works.

After this there are 4 chapters which explain in details how the Models, Controllers and Views are working in details.

There is one chapter which explain how to build an scaffolded application with the Bake console script. There is an explanation how to create Models, Controllers and Views.

The next chapters explain how to build a real world example with CakePHP called Quickwall (Questions and Answers), which is different from standard blog creation example. In these chapters the authors upgrade and optimize the app and expand it’s functionality, so at the end it could be used in the real world.

The good things

  • Even though it’s really difficult to write for a framework which still is in development, where some coding conventions could be changed, this book cover almost everything which is currently used in CakePHP1.2
  • The book is build with example driven approach which is really helpful for understanding from the developers
  • Each article is separated in sensible 3 sub-sections: introduction, or theoretical part, Time for action and What Just Happened. This approach is really useful, because first, explained what will be done in the current chapter, the second part display the actual code snippets and the third one explain step by step the code presented in the previous part. For me it’s really good approach of writing a technical book
  • Using non trivial building a blog is also a plus, I personally don’t think that anyone will write a new blog platform, just because for fun. The Quickwall application could be used in real world without any problems.

What I didn’t like

  • It’s opposite of the first thing in the previous list – just because the framework in still in motion the book is jist a little bit outdated. There are few code snippets where I found that for example condition word is in the right part, while at this moment it’s moved to the left. The code in the book was:
    'conditions' => array('ModelName.field_name' => 'LIKE value')

    while it should be

    'conditions' => array('ModelName.field_name LIKE' => 'value')
  • There are some things which are missing although they are well known – the behaviors. The same as the authors explained about the components and helpers, they should take a moment and explain the behaviors as well. In fact this is totally missing in this book.
  • Although the validations are well explained in the book, I miss the list of methods provided from the core.
  • There isn’t any information about the internationalization, which for me as developer working with many people and different languages is essential.

The conclusion

I would recommend this book for PHP developers who are new to the framework and they are willing to understand the core functionality of it. With the good approach of introduction-code-explanation, it will be really easy to learn how to use the CakePHP. This book could build a base, but it cannot create from you an advanced CakePHP developer (well I think it’s not the main purpose of it anyway). The learning is ongoing process and people which are willing to learn could start with this book, but after this, they need to continue reading other materials, as well as start with real development tasks, because the practice is the best teacher invented ever.

Here is a sample chapter from the book kindly provided from Pakt Publishing

Reviews by others:

Autoload your javascript and css in CakePHP

Have you ever wanted to have all your css or javascripts files loaded automatically once they are on place under /webroot/js and webroot/css folders? Well this is the solution.

What is all about

I’ve build a quick helper which will include all files under the js/ and css/ directories. So once the javascripts and css are there, they will be loaded automatically.

How to use it?

Using it is really easy. It’s like a normal helper:
1. add the file autoload.php under your /app/views/helpers
2. add it in the $helpers var in the controller
3. add the following snippet in your layout file. It should be under /app/views/layouts:

<?php echo $autoload->javascript();?>

This will include all files under /webroot/js

<?php echo $autoload->css();?>

This will include all files under /webroot/css

<?php echo $autoload->all();?>

This will include all files under /webroot/js and /webroot/css

Key features:

1. The helper includes all files recursively.
2. The helper includes also files under /root/vendors/js and /root/app/vendors/js too (same apply to css). Vendors are loaded first. (Thanks to suggestion from Juan Basso)
3. The order of the files in one directory is based on the name, so now you can control the order as well. (Thanks to suggestion from Juan Basso)
4. Files starting with . (dot) are not included, files under directories starting with . are not included as well, so you can exclude some files
5. if you want to load some files after other use directories. For example if you want to include plugins after the main lib (jQuery), place them in plugins directory like:
js/plugins/plugin_one.js
js/plugins/plugin_another.js
js/.hidden/plugin_third.js
js/jquery.js
the result will be:

<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/plugins/plugin_one.js"></script>
<script type="text/javascript" src="js/plugins/plugin_another.js"></script>

(same apply to css as well)

Warning: I’ve noticed that this helper doesn’t work properly with scriptaculous, because the script tries to load the additional plugins and they fail, but for jQuery there is not a problem at all.

Finally here is the code of the helper:
Continue reading

Careful with JavaScript includes

Ok, this is not a code snippet article. It’s just an experience which you probably already met, but it was nightmare to find and it took me 1/2 a day to fix this “stupid” bug.

So what is the case?

Working on a project including some advanced JavaScript and Ajax techniques my coworker Milen noticed that the Session is not behaving as expected. In a simple function like:

 function test($id = false){
  if ($id != false) {
    echo $id;
    echo $k = $this->Session->read('some_var');
    $this->Session->write('some_var', $id);
  }
  $this->set('tests', $this->paginate());
 }

The result should be quite easy to be predicted: if you pass for example 5 on the second reload the $k should be with the same value as $id. Unfortunately instead of 5 the $k was ‘images’. Yep, quite strange, isn’t it?

if you put die() at the end of the function, the result is as expected.

What was the problem

In our current project we are using jQuery and some of it’s plugins. So the problems was in the ThickBox plugin. If you remove it from the header everything works.

Digging into unpacked version of the plugin we’ve noticed that the loading picture is not where it should be. there is an variable

 var tb_pathToImage = "images/loadingAnimation.gif"

and as you may notice the path is not compatible with Cake convention and obviously it’s not in the http://server/cakeapp/tests/test/images/.

In the example above we were writing id into the session. Yes but calling: http://server/cakeapp/tests/test/images/loadingAnimation.gif mean that $id take value of ‘images’.

It was quite tricky, because if you loading CSS or JavaScript and the file is not there, FireBug or even the html /if there is no correct CSS the styling will fail/ will warn the developer, but image loaded into the JS function is quite difficult to find.

Anyway, the conclusion is “Watch you JavaScript libs and what files they require”.

Translating plural and singular forms in CakePHP

I don’t know how good you know the *.po translation file syntax, but for me it was a text file with “msgid” and “msgstr”, where msgid is the string, which could be found in a code of the app, wrapped with __() function and msgstr is the string which is the translation.

Following this convention in all of my projects I had not problems till now. But on this one I’ve noticed that the translation is not quite accurate especially when translating time. I am speaking about usage of timeAgoInWords() function from the TimeHelper.

I noticed that when there is a translation file for the specific language singular and plural words are not translated properly, I had results like “3 hour and 34 minute” instead of “3 hours and 34 minutes”.

I thought that I’ve found a bug, and I submitted a ticket in the trac, but I was wrong, because syntax of the PO files is a little bit extended than my understanding. πŸ™‚

99% of the cases the standard approach could fit just fine, but when it’s used __n() function which is described as:

Returns correct plural form of message identified by $singular and $plural for count $count.

the translation file needed a specific syntax. Here is the example of it:

msgid "hour"
msgid_plural "hours"
msgstr[0] "hour"
msgstr[1] "hours"

As you can see instead of msgid<->msgstr pair, there is also msgid_plural and array of msgstr which holding the translations of singular and plural values. Note that in some languages plural could have 2 or more forms. In these cases the syntax will be (Czech):

msgid "%1 second"
msgid_plural "%1 seconds"
msgstr[0] "%1 sekunda"
msgstr[1] "%1 sekundy"
msgstr[2] "%1 sekund"

It’s good to set the plural forms definition in the project settings which are in the beggining of the file. This is very handy when you use PoEdit or similar translation tools, because if is your setting is correct, these tools will provide for each plural form separate tab.

The syntax of plural form definition is like:

"Plural-Forms: nplurals=1; plural=0;\n"

It hold 2 parameters the first one holding the number of plural forms in the specific language and the second one is an expression how to determine the plurals. If you don’t know how to set this correct for a specific language, check this good document of all available languages. πŸ™‚

More information about the PO syntax I founded in that article. I’ve noticed in that the article there are shortcuts, which are not useful for me so far, but you never knows, in the future they could be handy.

Regarding to that I am wondering is there a POT file for the core lib translations which could be a big helper to anyone who need to translate the whole framework.

Blast from the past

Hey guys,

last week I’ve worked on a project which I finished somewhere in spring of 2007 and I decided to share my experience with this post. I don’t know did you had such experience, but for me it was interesting, because working on old code is always challenge.

Basically, the project was really small one, which uses 80% of scaffolding, so really nothing complicated. Now the client wanted some extensions to the core functionality /like adding few more look-up tables and some basic reports/ and because I was the only one developer who worked on it, they ask me to do this and I agreed.

My first thought was to upgrade the core CakePHP lib to the last version, but after thinking I decided not to, because if something goes wrong /like some deprecated functions/, I need to do more work in debugging rather than focusing on the real tasks.

What I noticed while I coded?

The major one – Improvement of the console script. In the past it was in the /cake/scripts/. In the folder there were acl.php, bake.php and bake2.php, extract.php for label extraction and master bake which I never used. Now, the console script is more advanced and provide more functions. Still I am not big expert on it and I still using it for basic operations :).

Fully translated labels – it’s related to the previous one – when the code was generated with old bake script, some of the labels weren’t wrapped with __() function and especially for me it was biggest pain. Someone could tell me that there was ability to modify the templates, but I personally never did it.

The truth is that CakePHP in fact is improved a lot since then. Hopefully it will continue in this direction in the future as well.

Anyway, it was really interesting experience for me.

Working with nested data and find method with breadcrumbs in CakePHP

Do you working with tree data in your projects?

Well, in CakePHP there is a Tree behavior which will help you to handle such structures. Let me show you how to use it in your projects. Hierarchical data structures are very well described here by Mike Hillyer and I would suggest you to take a look before you continue reading.

Let’s say we have following data structure:

CREATE TABLE IF NOT EXISTS `categories` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `parent_id` INT(10) DEFAULT NULL,
  `name` VARCHAR(255) DEFAULT NULL,
  `lft` INT(10) DEFAULT NULL,
  `rght` INT(10) DEFAULT NULL,
  PRIMARY KEY  (`id`)
)

Note, that in that table there are 3 special fields: parent_id, lft and rght.

The first one is very familiar to everyone who understanding the tree structures. The other 2 are to handle the MPTT logic (see the article mentioned above). The beautiful part of using Tree behavior is that you don’t need to worry about these 2 extra columns. The behavior will fill them automatically. πŸ™‚

So, continue with the example. Attach the Tree behavior to your Model:

<?php
class Category extends AppModel {
    var $name = 'Category';
    var $useTable = 'categories';
    var $actsAs = array('Tree' => 'nested');
}
?>

That’s it. Now when you save (insert or update) your data into the table, the fields lft and rght will be automatically populated with the correct values. Of course your task is to have proper value set in parent_id πŸ™‚

Why this is so important?
As you already know /if you read the article for MPTT/ using lft and rght values will give possibility to get very easy nested data in various ways.
In Model::find function there is already threaded option, but what about having breadcrumbs?

Here is a way to extend the Model::find function with this functionality. /inspired by Daniel Hofstetter’s post/

<?php
class Category extends AppModel {
    var $name = 'Category';
    var $useTable = 'categories';
    var $actsAs = array('Tree' => 'nested');

    public function find($type, $options = array()) {
        switch ($type) {
            case 'breadcrumbs':
                if(!isset($options['fields']))
                    $options['fields'] = null;
                if(!isset($options['recursive']))
                    $options['recursive'] = null;
                if(is_object($this->Behaviors->Tree) && $options['id']){
                    return $this->Behaviors->Tree->getpath($this, $options['id'], $options['fields'], $options['recursive']);
                } else {
                    return null;
                }
                break;
            default:
                return parent::find($type, $options);
        }
    }
}
?>

As you can see I am using the function TreeBehavior::getpath. There are a lot of handy functions in this behavior, but for breadcrumbs example this is just enough.

How to use it?

$this->Category->find('breadcrumbs', array('id'=>1));

so if you have data like this:

1 Root
2     Cat1
3         Cat1.1
4     Cat2

and use the function mentioned above with id=3 the result will be:

Array
(
    [0] => Array
        (
            [Category] => Array
                (
                    [id] => 1
                    [parent_id] =>
                    [name] => Root
                    [lft] => 1
                    [rght] => 8
                )
        )

    [1] => Array
        (
            [Category] => Array
                (
                    [id] => 2
                    [parent_id] => 1
                    [name] => Cat1
                    [lft] => 2
                    [rght] => 5
                )
        )

    [2] => Array
        (
            [Category] => Array
                (
                    [id] => 3
                    [parent_id] => 2
                    [name] => Cat1.1
                    [lft] => 3
                    [rght] => 4
                )
         )
)

After this with

$breadcrumbs = Set::extract('/Category/name', $result);
echo ' / '.implode(' / ', $breadcrumbs);

you will have the following result

/ Root / Cat1 / Cat1.1

I am leaving to you the styling of it as well as adding the links to the parent nodes.

Building cake application (Part VI)

Saturday (Day 6)

Problem with validation messages while translating
Although my native language is Bulgarian and the requirement from the client was to have this site only in Bulgarian, I’ve preferred to have it in English and to make the translation with the i18n functions of CakePHP. There are 2 reasons to do this:

1. This will give me the possibility to show you the result of all these days of coding and
2. I can reuse some part of the codes the same as I’ve used in this project

So, up to my experience having application in English is never a bad idea. πŸ™‚

You know, that the translating process is not very exciting process, but someone need to do it and because there is no one who can help me with this I’ve start the translation. Anyway. πŸ™

While translating I noticed that the most of the validation messages are not appear of the translation file. I knew this from my past experience, but I needed to find an easy and elegant solution to translate these messages instead of putting them in all views. Putting in the view you need to do this at least 2 times.
Continue reading

Building cake application (Part V)

Friday (day 5)

Constructing SQL statement for the search
Yep, today I need to finish the Profile search for the admin part. As I mentioned, the search is only by fields of experience, so there is no big and scary where clause /especially if you want to cover all cases, like splitting the words with AND, OR etc. will cause huge where with all possible combinations/.

There are 2 specific requirements here: The results need to be ordered by relevance and the report need to show fields of competence which are match to the search criteria next to each row /user/.

What does it means? Let’s say there are 2 users. First one has following skills like Java, PHP, MySQL, HTML and JavaScript, the second one knew only JavaScript and HTML, so when we search for users matching criterion PHP and HTML, the search results need to be ordered like this:

User1 – matching fields: PHP, HTML – relevance 2 criteria matched
User2 – matching fields: HTML – relevance: 1 criteria matched
and so on.

At first glance it look like I had to build huge SQL including few sub queries or functions for fetching the fields of relevance and matching fields and I was prepared for at least one day to accomplish this task, but in fact it was very fast.
Continue reading

Building cake application (Part IV)

Thursday (day 4)

Today I need to go downtown again. I am quite unhappy, because this mean that I need to work extra later on, but there are priorities, as you probably know. Here is what I’ve done today.

Working on the administration part
Today, I’ve worked on the administration part. There are some small bugs and glitches which I needed to clear in the Key look-up tables such as, stripping down the Categories functionality – this application requires only 2 levels of nesting in the Fields of experience, so allowing the extra levels will confuse the customers.

fixing some bugs in the front end as well
I’ve still have troubles with the redirects in the Auth component. I know it’s all my fault but it’s really annoying. I need to check what exactly is the problem with this. πŸ™

Adding delete all related records to the external user’s profile
Back to the admin part. I needed to implement delete all related records interface – if an admin user decide to remove an External user profile – let’s say someone try to test the application, or just an appropriate user /spammer/ this action should delete all relative records to that profile.

The problem was that I thought that key node is ‘dependent’ while the right one is ‘exclusive’. So, it’s set to true in the hasMany, hasOne etc. and if the parent record is deleted all records in the child tables are deleted too.
Continue reading

Building cake application (Part III)

Wednesday (day 3)

Adding dynamic pages
Today, I’ve decided to add some extra functionality to the application by adding a dynamic pages functionality. The main reason why I did this was because this system needed an “About the application” page as well as other pages and I’d preferred to leave this task to the clients. I also think that with small effort I am giving good impression to the client.

Instead of replacing fully the pages controller, I’ve decided to leave them due to use them for some system pages such as, “Thank for registration” and some other simple pages which are required.

Simple horizontal menu
Added a very light horizontal menu. I like it because it’s really small and works perfect for 1-2 level menus.

Using textile for formatting
I’ve decided to use textile for the formatting of the dynamic page’s content. There is a solution with behavior class, but I found a helper solution, so the installation and configuration was quite easy. I’ve also find a nice help description which briefly explains how to use textile format which I placed above of the page content field.
Continue reading