Welcome to the Cookbook

loading...

3.13.1 Creating Shells & Tasks

3.13.1.1 Creating Your Own Shells

Let's create a shell for use in the Console. For this example, we'll create a ‘report' shell that prints out some model data. First, create report.php in /vendors/shells/.

<?php 
class ReportShell extends Shell {
	function main() {}
}
?>
  1. <?php
  2. class ReportShell extends Shell {
  3. function main() {}
  4. }
  5. ?>

From this point, we can run the shell, but it won't do much. Let's add some models to the shell so that we can create a report of some sort. This is done just as it is in the controller: by adding the names of models to the $uses variable.

<?php
class ReportShell extends Shell {
	var $uses = array('Order');

	function main() {
	}
}
?>
  1. <?php
  2. class ReportShell extends Shell {
  3. var $uses = array('Order');
  4. function main() {
  5. }
  6. }
  7. ?>

Once we've added our model to the $uses array, we can use it in the main() method. In this example, our Order model should now be accessible as $this->Order in the main() method of our new shell.

Here's a simple example of the logic we might use in this shell:

class ReportShell extends Shell {
	var $uses = array('Order');
	function main() {
		//Get orders shipped in the last    month
		$month_ago = date('Y-m-d H:i:s',    strtotime('-1 month'));
		$orders =    $this->Order->find("all",array('conditions'=>"Order.shipped >= '$month_ago'"));

		//Print out each order's information
		foreach($orders as $order) {
			$this->out('Order date:	' .    $order['Order']['created'] . "\n");
			$this->out('Amount: $' .    number_format($order['Order']['amount'], 2) . "\n");
			$this->out('----------------------------------------' .    "\n");
	 
			$total += $order['Order']['amount'];
		}

		//Print out total for the selected orders
		$this->out("Total: $" .    number_format($total, 2) . "\n"); 
	}
}
  1. class ReportShell extends Shell {
  2. var $uses = array('Order');
  3. function main() {
  4. //Get orders shipped in the last month
  5. $month_ago = date('Y-m-d H:i:s', strtotime('-1 month'));
  6. $orders = $this->Order->find("all",array('conditions'=>"Order.shipped >= '$month_ago'"));
  7. //Print out each order's information
  8. foreach($orders as $order) {
  9. $this->out('Order date: ' . $order['Order']['created'] . "\n");
  10. $this->out('Amount: $' . number_format($order['Order']['amount'], 2) . "\n");
  11. $this->out('----------------------------------------' . "\n");
  12. $total += $order['Order']['amount'];
  13. }
  14. //Print out total for the selected orders
  15. $this->out("Total: $" . number_format($total, 2) . "\n");
  16. }
  17. }

You would be able to run this report by executing this command (if the cake command is in your PATH):

$ cake report 

where report is the name of the shell file in /vendor/shells/ without the .php extension. This should yield something like:

Hello user,
   Welcome to    CakePHP v1.2 Console
   ---------------------------------------------------------------
   App : app
   Path:    /path/to/cake/app
   ---------------------------------------------------------------
   Order date:    2007-07-30 10:31:12
   Amount:    $42.78
   ----------------------------------------
   Order date:    2007-07-30 21:16:03
   Amount:    $83.63
   ----------------------------------------
   Order date:    2007-07-29 15:52:42
   Amount:    $423.26
   ----------------------------------------
   Order date:    2007-07-29 01:42:22
   Amount:    $134.52
   ----------------------------------------
   Order date:    2007-07-29 01:40:52
   Amount:    $183.56
   ----------------------------------------
   Total:    $867.75

3.13.1.2 Tasks

Tasks are small extensions to shells. They allow logic to be shared between shells, and are added to shells by using the special $tasks class variable. For example in the core bake shell, there are a number of tasks defined:

<?php 
class BakeShell extends Shell {
   var $tasks = array('Project', 'DbConfig', 'Model', 'View', 'Controller');
}
?>
  1. <?php
  2. class BakeShell extends Shell {
  3. var $tasks = array('Project', 'DbConfig', 'Model', 'View', 'Controller');
  4. }
  5. ?>

Tasks are stored in /vendors/shells/tasks/ in files named after their classes. So if we were to create a new ‘cool’ task. Class CoolTask (which extends Shell) would be placed in /vendors/shells/tasks/cool.php. Class VeryCoolTask (which extends Shell) would be placed in /vendors/shells/tasks/very_cool.php.

Each task must at least implement an execute() method - shells will call this method to start the task logic.

<?php
class SoundTask extends Shell {
   var $uses = array('Model'); // same as controller var $uses
   function execute() {}
}
?>
  1. <?php
  2. class SoundTask extends Shell {
  3. var $uses = array('Model'); // same as controller var $uses
  4. function execute() {}
  5. }
  6. ?>

You can access tasks inside your shell classes and execute them there:

<?php 
class SeaShell extends Shell { // found in /vendors/shells/sea.php
   var $tasks = array('Sound'); //found in /vendors/shells/tasks/sound.php
   function main() {
       $this->Sound->execute();
   }
}
?>
  1. <?php
  2. class SeaShell extends Shell { // found in /vendors/shells/sea.php
  3. var $tasks = array('Sound'); //found in /vendors/shells/tasks/sound.php
  4. function main() {
  5. $this->Sound->execute();
  6. }
  7. }
  8. ?>

You can also access tasks directly from the command line:

$ cake sea sound

In order to access tasks directly from the command line, the task must be included in the shell class' $tasks property. Therefore, be warned that a method called “sound” in the SeaShell class would override the ability to access the functionality in the Sound task specified in the $tasks array.