Otaqui.com Blog

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

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.