Otaqui.Com

Pete Otaqui’s blog about web development and everything else

Archive for the ‘cakephp’ tag

Create A Custom CakePHP Console Application Using Shells, Tasks, Models and Controllers

leave a comment

CakePHP doesn’t just come with its own console applications for baking code, managing ACL, inspecting classes, manipulating the schema, internationalisation and running the testsuite (whew!) it also lets you write your own console applications.

[NB: I always have an external cake core directory, for easy swapping. The code examples all assume you have done this, or at least created an alias in your terminal to point to the core cake directory with something like: alias cake='../cake/console/cake'

First off, to find out about the current console applications you are running jump into a terminal and cd to your app directory, then simple run the “cake” command to see what you have available:

app_dir $ cake

This will output a list of available shells in the core cake library and the two “vendors” directories.

So how do you go about creating your own? The CakePHP documentation on creating Shells & Tasks is a good place to start.

An application I’ve needed to automate with a cron-job, and also have available as an in-app, on-demand function is the sending of emails. I’m not talking about writing a mass mailer here, but rather just sending out course information to users who are booked to attend – and doing so both automatically and on-demand when an administrator decides it is necessary. This is an obvious instance where you don’t want to duplicate the code in the controller and the shell.

In my case, I have several kinds of email I want to send, so I set up a generalised Task, used by several different Shells. The advantage of doing things this way around is that any other Shells can also make use of the emailer Task in the fututre.

Here’s some simplified code from one of the Shells, a “booking reminder” for delegates:

// file app/vendors/shells/booking_reminder.php
<?php
class BookingReminderShell extends Shell {
  var $uses = array("Booking","User","Course");
  var $tasks = array("Emailer");
  public function main() {
    // use $this->Booking etc as if we were in a controller
    // use $this->Emailer for the task
  }
}

And then we have the Task:

// file app/vendors/shells/tasks/emailer.php
<?php
class Emailer extends Shell {
  public function execute() {
    // this method is called when the task is instantiated,
    // gives you a chance to setup
  }
  public function send($to,$from,$subject,$message,$attachments=null) {
    // called from shell with: $this->Emailer->send();
  }
}

Note how both Shells and tasks extend from the base “Shell” class. Also note how Shells use a method called “main()” when they are run, whereas Tasks use “execute()” when they are created.

Written by pete

February 10th, 2010 at 10:43 pm

Posted in Professional

Tagged with ,

CakePHP’s basics.php functions – a series of really useful shortcut functions available globally in your CakePHP app

leave a comment

If you are working with CakePHP and haven’t checked it out yet, it’s very well worth looking through basics.php in the API docs.

As well as adding some PHP 5 functionality on PHP 4 servers, the script also adds a fair number of utility functions to the global namespace, such as:


// similar to print_r(), but dumps to the view and
// is disabled if debug isn't > 0 in config.php
pr($anything); 

// returns the correctly internationalised plural or
// singular depending on locale.
__n($singular, $plural, $count, $return);

Written by pete

February 24th, 2009 at 10:07 pm

Posted in Professional

Tagged with

Disable Debug Output for Ajax in CakePHP

4 comments

If you are developing a CakePHP application and you have the debug value set to anything greater than 0 in your config/core.php file, you will find that Ajax requests will also get the extra information appended to the output.

In order to circumvent this add this to your “app_controller.php” file (which sits directly inside the “app/” dir, rather than in “app/controllers”):

<?php
class AppController extends Controller {
  var $components = array('RequestHandler');
  var $helpers = array('Html','Form','Ajax');
  function beforeFilter() {
    if ( $this->RequestHandler->isAjax() ) {
      Configure::write('debug',0);
    }
  }
}
?>

Note that while this will disable the debugging output, it will also have other affects too (for the life of the Ajax Request) like extending the length of time that the “schema” is cached. This should make little or no difference, but is worth remembering.

Written by pete

February 15th, 2009 at 5:15 pm

Posted in Professional

Tagged with ,

Custom Model and Field Result Set in CakePHP

one comment

If you’re using CakePHP and want to perform a custom SQL query while forcing your results into an arbitrary Model-based array when they are given back to you, you could do a lot worse than using grigri’s (who is a fellow South Westerner and therefore obviously a good bloke ;) DboMysqlEx (Mysql Extended) Class, or at least this particular part of it:

<?php
require_once (LIBS . 'model' . DS . 'datasources' . DS . 'dbo' . DS . 'dbo_mysql.php');
class DboMysqlEx extends DboMysql {
   var $description = "MySQL DBO Driver - Extended";
   // Override resultSet to allow for Model__field type aliases
   function resultSet(&$results) {
		if (isset($this->results) && is_resource($this->results) && $this->results != $results) {
			mysql_free_result($this->results);
		}
       $this->results =& $results;
       $this->map = array();
       $num_fields = mysql_num_fields($results);
       $index = 0;
       $j = 0;
       while ($j < $num_fields) {
           $column = mysql_fetch_field($results,$j);
           if (!empty($column->table)) {
               $this->map[$index++] = array($column->table, $column->name);
           } else {
               if (strpos($column->name, '__')) {
                   $parts = explode('__', $column->name);
                   $this->map[$index++] = array($parts[0], $parts[1]);
               } else {
                   $this->map[$index++] = array(0, $column->name);
               }
           }
           $j++;
       }
   }
}
?>

This code, which overrides the default MySQL DBO, allows you to SELECT something AS Modelname__Fieldname (with a double underscore) and will end up populating your result set as you would like it to ($results['Modelname']['Fieldname']).

In order to use a custom datasource, copy the code and save it as “/cake_dir/app/models/datasources/dbo/dbo_mysqlex.php” and edit your “/cake_dir/app/config/database.php” file so that it uses the “mysqlex” driver instead of plain old “mysql”.

This all came from a discussion on the excellent CakePHP Google Group

Grigri posted a copy of his modified MySQL Extended DBO online if you want some more of his nice features like backtracing.

Written by pete

February 6th, 2009 at 1:22 am

Posted in Professional

Tagged with ,