debuggable

 
Contact Us
 

Make your life easier with these five CakePHP Quicktips

Posted on 27/5/08 by Tim Koschützki

Hi guys,

here are five quick CakePHP tips you should consider when you want to make your life easier. Isn't clean code all we want?

1. The prd() convenience function

Do you often find yourself doing the following in your controller, models and views?

pr($someVar);
die;

Why not wrap it up into a nice function that you can call just like pr() ?

function prd($var) {
  pr($var);
  die;
}

Simple, yet effective! You can just drop that into your bootstrap.php and do this from now on:

prd($someVar);

One line less to type! I hear many people argueing that you should use debug(). Good call, but it does not provide a parameter that let's you exit out, so you would end up doing something similar anyway. If someone uses anything else, be sure to throw it into the discussion.

2. How to debug your CakePHP emails?

Yeah so you set up a local mailserver in order to test your emails' output? Then had to wait between one and twenty minutes for the email to arrive? That is not KISS is it?

Cake's Email Component has a nice debug mode which you can use. Just set the following in your controller:

$this->Email->delivery = 'debug';

The Component stores its debug output as a Session flash Message, however. In order to access the debug information, you would do this:

$this->Email->send();
prd($this->Session->read('Message.email'));

The dump includes all headers, subject and message. The debug output is internally wrapped into a <pre> tag and therefore you have to keep in mind that non-explicit newlines will be shown as such in the debug output. However, they will not be in the email text. Be sure to explicitely insert newlines in the email via

<?php echo "\n\n"; ?>

for example.

You could also create a debugEmail() method in the app controller to wrap this Session read call to not always have to remember it.

3. Use elements where possible and make them belong to the controller

In a web application you will find yourself dealing with the same "site elements" time and again. Cake's elements are very handy for that. So why not use the views of a specific model as an element, too, to save code lines? Have a look at this in a fictive /views/posts/index.ctp

<?php if (count($posts) == 0): ?>
<p>Sorry, there are no posts yet!</p>
<?php return; endif; ?>

<?php foreach ($posts as $i => $post): ?>
  // big long code to render the post which is duplicated in /views/posts/view.ctp
<?php endforeach; ?>

This looks much better:

<?php if (count($posts) == 0): ?>
<p>Sorry, there are no posts yet!</p>
<?php return; endif; ?>

<?php foreach ($posts as $i => $post): ?>
  <?php echo $this->element('../posts/view', array('post' => $post, 'forIndex' => true, 'excerpt' => false)); ?>
<?php endforeach; ?>

You can use that as an element now in the index.ctp view as we did or as a different page. Only controller-independent elements should go into /views/elements. Everything else should stay in the controller-specific folder as view files. Disagree? Share your view!

4. Combine your h1 titles with Cake's page title

Very often people set the page title within their controller, which is bad. The page title is view logic so it should go into the view. For everybody not knowing about this yet, you can do the following in any view file as well:

$this->pageTitle = 'Something here';

So let's go a step further and output the page title as the h1 headline for your page in a very semantic line to kill two birds with one stone:

<h1><?php echo $this->pageTitle = 'Credit Cards'; ?></h1>

5. Avoid long parameter lists

A method with long parameter lists is always not a nice thing. It takes up space and will most likely need to be wrapped over two lines. How ugly!

Consider this:

function setup($settings = array()) {
  $defaults = array(
    'assocs' => array(
      'types' => array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany')
    ),
    'queries' => array(
      'filters' => array(),
      'associated' => true,
      'describe' => false
    ),
    'schema' => array(),
    'log_sql_table' => 'logs'
  );

  $this->settings = am($defaults, $settings);
}

instead of a function with a long parameter list.

Happy baking!

-- Tim Koschuetzki aka DarkAngelBGE

 
&nsbp;

You can skip to the end and add a comment.

Abhimanyu Grover said on May 27, 2008:

Hey... nice tips. Especially the debug email. Keep posting these mini-tips as you find it, I really enjoy these quickies on my projects.

Richard@Home said on May 27, 2008:

die(pr($someVar))

Aitch  said on May 27, 2008:

Not completely sure I buy into #4, but I see where you are coming from, and I like the rest.

In a few situations I use the same view file for a couple of actions, and it is useful to change the pageTitle in the controller method to modify. It's really convenient to do it that way for those pages (add/edit methods using the same view for example). It seemed more elegant and easier to recognise for others in the future to do this via $this->pageTitle than a separate $this->set('title' ....) Perhaps it is not entirely MVC but I can let that one go.

For the add/edit example, to get around this it is possible to look at the action name and work that into the pageTitle anyway .... ( essentially do something like $this->pageTitle = $this->action . " Item" etc ... )

Peter Butler said on May 28, 2008:

Thanks Tim, some excellent tips there, I will certainly be giving all these a try

Tim Koschützki said on May 29, 2008:

@Peter: Cool, please let me know how it goes.

@Abhimanyu: Yeah we will do, for sure.

@Aitch: Why do you not buy into #4? Let's discuss it. The way your last paragraph describes is the approach I am choosing, too.

Baz L said on May 31, 2008:

I'm confused about the elements. Where do we put the files for elements that belong to the controller?

Khaled  said on Jun 02, 2008:

Email hack is great ;-) thanks Tim

kvz said on Jun 02, 2008:

Thank you Tim! Though 5 may hurt semantics (documentation, IDE's etc)?

Tim Koschützki said on Jun 02, 2008:

@Kvz: Do you have an example of how this could hurt?

@Khaled: Cheers

Shane said on Jun 03, 2008:

#5: it is one of my pet peeves if not documented carefully.

Cake uses a lot of associative arrays as parameters, but the documentation has not caught up with the code in places. And I find myself spending time looking at source code to find out what parameters the function accepts.

Tim Koschützki said on Jun 03, 2008:

@Shane: Exactly you are right. That's why extra care is being taken for writing the cookbook now.

Martin Bavio said on Jun 05, 2008:

About #3:

What if I want to show only a small snippet of the post and not the same view that in posts/view. I think the scenario that you set is unusual, most of the times you just want to show a small snippet linking to the whole view action.

Tim Koschützki said on Jun 05, 2008:

Martin Bavio: You would do it like this:

http://bin.cakephp.org/view/1074611387

Notice the excerpt variable being set to true. Then in the actual view.ctp you would do your TextHelper::truncate logic or whatever if that variable is true.

Does that answer your question?

Martin Bavio said on Jun 05, 2008:

Freaking magic! Tim, you are a genious, goodbye elements!

Matti Putkonen said on Jun 27, 2008:

Number 4. actually hit me hard. I have been a bad puppy. Will do better in the future.

I actually had some sidebars (elements) used in layouts set from the controller too and used the same logic to move those to individual views.

Abhimanyu Grover said on Sep 03, 2008:

Just thought about another email debugging method, prd() is not possible all the time.. why not create a temporary file in 'tmp' folder instead.

Jason Leveille said on Sep 24, 2008:

I found that with tip number one I also needed to implement a debug_backtrace (otherwise my debug info referrenced the bootstrap file rather than the place where I was calling my debug/die function):

function d($data)
{

$backtrace = debug_backtrace();

debug('File: ' . $backtrace[0]['file'] . ' Line: ' . $backtrace[0]['line']);

unset($backtrace);

die(debug($data));

}

Of course debug_backtrace is PHP5 specific.

Jason Leveille said on Sep 24, 2008:

debug_backtrace is not php5 specific as I previously mentioned. I was thinking of debug_print_backtrace.

debug_backtrace (PHP 4 >= 4.3.0, PHP 5)

This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.