Stupid CakePHP Controller Tricks

A big shout-out to my favourite typist for showing me some of these gems, which I will gladly share with you

So, one of the things that often happens in CakePHP is that you will have multiple values to send to your view, so you might have code that looks like this:

PHP:
  1. $this->set('user', $this->User->read(null, $id));
  2. $this->set('foo', $foo);
  3. $this->set('bar', $bar);
  4. $this->set('baz', $baz);

Seems simple enough, yes? Once when I showed code similar to this to the above-mentioned typist, he said "ew" and showed me two neat little tricks to make the code (a) more readable and (b) a little more efficient.

Solution one? Use compact() to pass all the variables to your view.

PHP:
  1. $user = $this->User->read(null, $id);
  2. $this->set(compact('user', 'foo', 'bar', 'baz'));

What does the compact() function do? It takes the array you pass into it and looks for variables of the same name as the elements in that array. It then spits out an array of key => value pairs. So, one little trick with compact() means you only have to use one set statement. This works because all those $this->set() statements simply add those values to an array. But you already knew that, right?

The second solution is similar to sing the "chmod 777 firehose" to solve UNIX-based permissions problems.

PHP:
  1. $user = $this->User->read(null, $id);
  2. $this->set(get_defined_vars());

Now, while this looks neat it does come with one big caveat: if you use get_defined_vars() you will be passing a lot of stuff into your view that you might not want there. In a way it's like using REGISTER_GLOBALS in your CakePHP. Every variable you've defined in the controller (and some other ones that CakePHP has defined for you) in your current scope will be available in the view.

12 Responses to this post.

  1. paitken's Gravatar

    Posted by paitken on 07.08.07 at 3:46 pm

    You have a typo in your compact() code :)

  2. Nate's Gravatar

    Posted by Nate on 07.08.07 at 3:46 pm

    It's only like using register_globals if you're inefficient in your variable assignments (none of these tricks will actually make you a better coder). Also, I hear it takes a typist to know a typist.

  3. Geoff Ford's Gravatar

    Posted by Geoff Ford on 07.08.07 at 3:46 pm

    Whats stupid about the compact method? It's a great tip.

    I agree about the get_defined_vars method being a little too lazy :)

  4. Lamby's Gravatar

    Posted by Lamby on 07.08.07 at 3:46 pm

    Ew, the second one is awful. :)

    I actually use opposite of 'compact', 'extract' a lot inside views. For example, instead of:

    You can do

    This makes views much easier to read IMHO, especially when you're passing data into helpers.

    Peace,
    /Lamby

  5. Lamby's Gravatar

    Posted by Lamby on 07.08.07 at 3:46 pm

    Aw, my code was eaten by the comment system. :(

  6. Chris Hartjes's Gravatar

    Posted by Chris Hartjes on 07.08.07 at 3:46 pm

    @paitken: Thanks for pointing that out, I fixed it in the post

    @Geoff: There used to be a segment on Dave Letterman's show called "Stupid Human Tricks", so I sort of took the same idea.

    @nate: It won't make you smarter, it just makes your code look better. I worry about what other info get_defined_vars() pulls in thanks to scope issues. Is there a way to print out a list of all variables that are available in a view?

    @Lamby: I think if you put {php} and {/php} (replace the curly braces with square braces) around your code sample it should show up in the comments as properly formatted code.

  7. anty's Gravatar

    Posted by anty on 07.08.07 at 3:46 pm

    The first trick is neat, the second one is terribly ugly :)
    I wouldn't ever use the second one because if you look at your code after two month you won't remember what you actually assign to the view.

    Thanks for sharing!

  8. Manny's Gravatar

    Posted by Manny on 07.08.07 at 3:46 pm

    Great tip!

    Do you know if there are any performance hits with using compact?

  9. Chris Hartjes's Gravatar

    Posted by Chris Hartjes on 07.08.07 at 3:46 pm

    @Manny: I don't imagine there is any sort of performance hit. Which do you think takes more time: using compact to send 4 variables via $this->set() or to run $this->set() 4 times? My money is on compact() being just as fast.

  10. Nate's Gravatar

    Posted by Nate on 07.08.07 at 3:46 pm

    @Chris: actually, get_defined_vars doesn't pull in anything beyond what's in the current method scope. This does *not* include any object properties (from $this) or anything that Cake has defined. It only includes variables you declare, and the parameters of the method itself.

    In the view, you can do $this->getVars() to get a listing of variables passed from the controller. Or just do array_keys(get_defined_vars()) in the controller to see what you're passing. Either way, if you think get_defined_vars() is inefficient, then it's more than likely that your controller code itself is inefficient, and you're being lazy in your variable assignments.

  11. Promet CakePHP Source» Blog Archive » What is compact() in controller?'s Gravatar

    [...] compact is a native PHP function that creates an array containing variables and their values. Chris Hartjes explains it well in his blog. It’s quite neat because it will save me a few lines and [...]

  12. Tgr's Gravatar

    Posted by Tgr on 07.08.07 at 3:46 pm

    $this->set('foo_bar', $foo_bar) vill result in a variable called $foo_bar.
    $this->set(compact('foo_bar')) will however result in $fooBar, because Controller::set() calls the variable inflector if and only if the first argument is an array and the second is null.
    Can't decide whether this is intentionally evil or just plain stupid...

Respond to this post

Want to advertise on this blog? Send email to chartjes@littlehart.net
GTcars Canadian Car Audio TurboDodge Car For Sale Sign
Audi Forum Mustang Forum Dodge Intrepid Miata Turbo
GTscene Pontiac Bonneville


@TheKeyboard is Digg proof thanks to caching by WP Super Cache!