CakePHP Crontab

Thu, Feb 28, 2008

CakePHP, PHP, Server

Due to the way that CakePHP rewrites URL requests with its router, it might seem confusing to execute a Crontab to run a controller action. I will show you how to set up a cron dispatcher so that you can execute all your different controller action schedules on a single file and pass the controller and action as an argument to the file so that the dispatcher will know which action to fire.

First off, you’ll need to create a duplicate of your index.php file inside of /app/webroot/. Once you have duplicated the file, rename it to cron_dispatcher.php and open it up for editing. On line #77 of your cron_dispatcher.php file, you will see the following :

if (!include(CORE_PATH . ‘cake’ . DS . ‘bootstrap.php’)) {
    trigger_error("Can’t find CakePHP core.  Check the value of CAKE_CORE_INCLUDE_PATH in app/webroot/index.php.  It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR);
 }

The code shown above includes the CakePHP core bootstrap.php file and of course, if the include fails, it triggers an error. So we’ll add an ELSE statement to this code so that we can fire our dispatcher if in fact the boostrap was successfully included. After adding your ELSE statement and the appropriate code to initialize the dispatcher, your code from line #77 should now look like this :

if (!include(CORE_PATH . ‘cake’ . DS . ‘bootstrap.php’)) {
    trigger_error("Can’t find CakePHP core.  Check the value of CAKE_CORE_INCLUDE_PATH in app/webroot/index.php.  It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR);
 } else {
    define(‘CRON_DISPATCHER’, true);
    if($argc == 2) {
        $Dispatcher = new Dispatcher();
        $Dispatcher -> dispatch($argv[1]);
    }
 }

And that’s it. You are ready to start executing cron schedules on this cron_dispatcher.php file and pass your controller together with the action as an argument. Here is an example crontab command :

* * * * * php -q /var/www/vhosts/domain.com/httpdocs/app/webroot/cron_dispatcher.php /products/cron/

The command will execute the the cron_dispatcher.php file and pass the argument “/products/cron/” to it. The argument is equivalent to any controller and action in your CakePHP system. So it is /controller/action/

Good luck! I hope this helps!

, , , , , , , , , ,
468x60gif

This post was written by:

Antonie Potgieter - who has written 57 posts on Lost-In-Code.

I (Antonie Potgieter) am a software engineer/web developer located in South Africa. My full-time work is the management of Tribulant Software and the development of its software packages.

Contact the author

5 Comments For This Post

  1. Charlotte Says:

    The path of my cron_dispatcher.php is in: /var/www/vhosts/ninthlink.com/httpdocs/pdf/pdfadmin/webroot/cron_dispatcher.php that looks like:
    <?php
    /* SVN FILE: $Id: index.php 7296 2008-06-27 09:09:03Z gwoo $ */
    /**
    * Short description for file.
    *
    * Long description for file
    *
    * PHP versions 4 and 5
    *
    * CakePHP(tm) : Rapid Development Framework
    * Copyright 2005-2008, Cake Software Foundation, Inc.
    * 1785 E. Sahara Avenue, Suite 490-204
    * Las Vegas, Nevada 89104
    *
    * Licensed under The MIT License
    * Redistributions of files must retain the above copyright notice.
    *
    * @filesource
    * @copyright Copyright 2005-2008, Cake Software Foundation, Inc.
    * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
    * @package cake
    * @subpackage cake.app.webroot
    * @since CakePHP(tm) v 0.2.9
    * @version $Revision: 7296 $
    * @modifiedby $LastChangedBy: gwoo $
    * @lastmodified $Date: 2008-06-27 02:09:03 -0700 (Fri, 27 Jun 2008) $
    * @license http://www.opensource.org/licenses/mit-license.php The MIT License
    */
    /**
    * Use the DS to separate the directories in other defines
    */
    if (!defined(‘DS’)) {
    define(‘DS’, DIRECTORY_SEPARATOR);
    }
    /**
    * These defines should only be edited if you have cake installed in
    * a directory layout other than the way it is distributed.
    * When using custom settings be sure to use the DS and do not add a trailing DS.
    */

    /**
    * The full path to the directory which holds “app”, WITHOUT a trailing DS.
    *
    */
    if (!defined(‘ROOT’)) {
    define(‘ROOT’, dirname(dirname(dirname(__FILE__))));
    }
    /**
    * The actual directory name for the “app”.
    *
    */
    if (!defined(‘APP_DIR’)) {
    define(‘APP_DIR’, basename(dirname(dirname(__FILE__))));
    }
    /**
    * The absolute path to the “cake” directory, WITHOUT a trailing DS.
    *
    */
    if (!defined(‘CAKE_CORE_INCLUDE_PATH’)) {
    define(‘CAKE_CORE_INCLUDE_PATH’, ‘/usr/lib/cake’);
    }

    /**
    * Editing below this line should not be necessary.
    * Change at your own risk.
    *
    */
    if (!defined(‘WEBROOT_DIR’)) {
    define(‘WEBROOT_DIR’, basename(dirname(__FILE__)));
    }
    if (!defined(‘WWW_ROOT’)) {
    define(‘WWW_ROOT’, dirname(__FILE__) . DS);
    }
    if (!defined(‘CORE_PATH’)) {
    if (function_exists(‘ini_set’) && ini_set(‘include_path’, CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . ROOT . DS . APP_DIR . DS . PATH_SEPARATOR . ini_get(‘include_path’))) {
    define(‘APP_PATH’, null);
    define(‘CORE_PATH’, null);
    } else {
    define(‘APP_PATH’, ROOT . DS . APP_DIR . DS);
    define(‘CORE_PATH’, CAKE_CORE_INCLUDE_PATH . DS);
    }
    }
    if (!include(CORE_PATH . ‘cake’ . DS . ‘bootstrap.php’)) {
    trigger_error(“Can’t find CakePHP core. Check the value of CAKE_CORE_INCLUDE_PATH in app/webroot/index.php. It should point to the directory containing your ” . DS . “cake core directory and your ” . DS . “vendors root directory.”, E_USER_ERROR);
    } else {
    define(‘CRON_DISPATCHER’, true);
    if($argc == 2) {
    $Dispatcher = new Dispatcher();
    $Dispatcher -> dispatch($argv[1]);
    }
    }
    if (isset($_GET['url']) && $_GET['url'] === ‘favicon.ico’) {
    return;
    } else {
    $Dispatcher = new Dispatcher();
    $Dispatcher->dispatch($url);
    }
    if (Configure::read() > 0) {
    echo ““;
    }
    ?>

    I am in the folder: /var/www/vhosts/ninthlink.com/httpdocs/pdf/pdfadmin and on the command line I run:
    php -q /var/www/vhosts/ninthlink.com/httpdocs/pdf/pdfadmin/webroot/cron_dispatcher.php /pdfs/hello

    where my controller is pdfs_controller.php and the function I want to call is:
    function hello()
    {
    die(‘hello’);
    }

    But the output is empty:
    [root@www pdfadmin]# php -q /var/www/vhosts/ninthlink.com/httpdocs/pdf/pdfadmin/webroot/cron_dispatcher.php /Pdfs/hello
    [root@www pdfadmin]#

    Please help!! Don’t know what I’m doing wrong. I’ve been looking everywhere but I can’t find out what the problem is. Thank you in advance.

  2. TommyO Says:

    This is relatively wrong in a number of ways. The first being that a script meant to be run in the cron is in the public space, therefore runable from a url. Not so good!

    Cake already provides a shell interface, which would be great for cron scripts. See http://book.cakephp.org/view/108/The-CakePHP-Console for more details.

  3. Hamdi Ben Abdallah Says:

    hello,
    as I know cakephp has a shell directory under app/core vendors where you can put your cron scripts and then you can call them from the cake console as shells, and that way it will be so easy to play with multiple shell scripts and add them to a scheduled cron jobs.

    sorry for my english, it is not fluent enough..

    Best reguards.

  4. Mike Says:

    I agree that you should use the built in CakePHP Console functionality, if available. CakePHP Console requires cli access — some hosting companies do not allow cli access. For this reason the above answer is a good one for conditions where you are not able to add cron or scheduler jobs in a shared hosting environment.

  5. Mike Says:

    I enjoyed reading this post about CakePHP Crontab. Really interesting. I will come back to visit this blog again.

Leave a Reply