CakePHP's Has and Belongs to Many (HABTM)

Having worked with CakePHP on several projects, I have definitely found may quirks in how CakPHP works. There are instances that you would have expected things to work but doesn't.

One of CakePHP most wanted is CakePHP's Has and Belongs to Many (HABTM) relationships. Here is the easiest way to add HABTM relationship to a Model.


$type = $this->Type->find('first', array('conditions' => array('name' => 'Developer')));
$this->User->set(
    array(
        'id' => 1,
        'name' => 'Thorpe Obazee'
        'Type' => $type
    )
);


This without a doubt works! Our user will have a HABTM relationship with our Developer Type. Looking at this example, how would you add the User 2 HABTM relationships?

Well let's see.


$types = $this->Type->find('first', array('conditions' => array('name' => 'Developer'), 'limit' => 2));
$this->User->set(
    array(
        'id' => 1,
        'name' => 'Thorpe Obazee'
        'Type' => array($types)
    )
);


Would you have expected this to work? Well, it doesn't. Adding multiple HABTM relationships in CakePHP is quite different than adding a single one. Here's the way to add multiple HABTM relationships.


$types = $this->Type->find('first', array('conditions' => array('name' => 'Developer'), 'limit' => 2));
$type_ids = array();

foreach ($types as $type) {
    $type_ids[] = $type['Type']['id'];
}

$this->User->set(
    array(
        'id' => 1,
        'name' => 'Thorpe Obazee'
        'Type' => $type_ids
    )
);


Voila! This works! I have come to love CakePHP like any other framework I've used. I don't know if this is intentional on the part of the developers but I don't find it very intuitive.

 Logging in as another user in CakePHP

Sometimes, we are tasked with features like making an application administrator log in as a different user. This makes it an easy way for the administrator  to do task as  another user, see what another user is able to do and see. CakePHP makes it so easy for developers to implement this feature.

The steps are very simple:
  1. Store your admin details in another session variable
  2. Login user you want to be logged in as
Here is a sample code for implementing this:

    public function admin_login_user($id) {
        if (!$this->User->exists($id)) {
            throw new NotFoundException(__('Invalid User'));
        }

        $this->Session->write('Auth.Admin', $this->Session->read('Auth.User'));
        $this->Session->delete('Auth.User');
        $user = $this->User->findById($id);
        $this->Auth->login($user['User']);
        $this->redirect($this->Auth->redirectUrl());
        $this->autoRender = false;
    }
Logging out as the user is just as simple:
  1. Check if your session variable indeed has an admin session to log into after you logout as the user. Just a security check.
  2. Login as the Admin
  3. Delete the store where you saved the admin session

    public function logout_user() {
        if ($this->Session->read('Auth.Admin')) {
            $this->Auth->login($this->Session->read('Auth.Admin'));
            $this->Session->delete('Auth.Admin');
            $this->redirect($this->Auth->redirectUrl());
        }
        $this->autoRender = false;
    }
Frankly, I am loving how CakePHP does this.

 Back to PHP

My current project with Sourcepad is converting a web application with with Drupal to CakePHP. We opted to develop the application with Ruby on Rails but the client wanted it developed in PHP. I would have loved to develop something again in Rails but clients can be persuasive (really persuasive).

With PHP, we had a few choices. We could develop the application using CakePHP, CodeIgniter, Yii or Kohana, frameworks I have had much experience in.

We ended up using CakePHP by writing up pros and cons for CakePHP and CodeIgniter. Yii and Kohana would have been very fine options but my project partner has little experience with them. 

Here's a list of what we had:

CakePHP
  • ( - ) Slow
  • ( + ) Built in themes
  • ( + ) Rails-like relationships
  • ( + ) Better Integration with Testing Suite(PHPUnit)
  • ( +/- ) Convention over Configuration
  • ( + ) Harder to mess up code because of stricter conventions
CodeIgniter
  • ( + ) Solid performance from the start
  • ( - ) No built in themes
  • ( - ) No ORM
  • ( - ) Built in Unit Test Class is weak
  • ( - ) Can potentially become hard to manage
  • ( +/- ) Configuration over Convention (somehow) 
People can of course argue that there are extensions for the CodeIgniter framework and CakePHP would be just as fast with proper caching.

The CakePHP and CodeIgniter frameworks are great. I've used both extensively (especially CodeIgniter). The thing is, in the end, we didn't choose because of the pros and cons(although CakePHP won). It will be team experience that will affect the framework decision. Only I had experience developing using the CodeIgniter framework, so we chose CakePHP.

Haha. Problem solved!

 Handy Shortcuts Using RubyMine

I have been an avid fan of RubyMine ever since I discovered it. I tried using other tools like Sublime Text 2, Textwrangler and others. The only other lasting editor I used was Vim on my Ubuntu Desktop and MacVim on my Mac.

There are tons of things I miss from Rubymine whenever I develop using other editors. Here are a few:
  1. Image Preview - Do you want to make sure you have the correct image to use in your CSS? Hover over the declaration and press Shift.
  2. Insane Code Inspection - Rubymine helps you be aware of deprecated methods, unneeded methods and overridden methods. 
  3. Checking of Source - A great feature I like about it is Command-clicking. Whenever I am not sure what a method does, I Command-click the method and I am instantly forwarded to the method declaration. This is quite handy if you want to check gem sources.
Here are a few shortcuts I have been using with Rubymine in the span of a year I have been using it. I really hope this helps Rubymine users like myself to ease up development and trim development time.

Joining lines (Shift + Ctrl + J)

I never had the idea that there was such a function in editors. I discovered this when I thought of a way to join lines instead of doing a backspace on every line in a 100+ line file.

Toggle Comments (Command + /)

This will be very familiar since this is used  by Textmate and Sublime Text. It will comment depending on which type of file you have open.

Show / Hide Project Folder (Command + 1)

I work mostly on a small 13" laptop and I need all the space I can get. The project pane can easily be hidden so that I can use up the the full length of my small screen.