CakePHP Crontab

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!

Comments

  1. Charlotte on October 27, 2008

    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.

    Reply
  2. TommyO on January 24, 2009

    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.

    Reply
  3. Hamdi Ben Abdallah on December 21, 2009

    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.

    Reply
  4. Mike on December 22, 2009

    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.

    Reply
  5. Mike on March 21, 2010

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

    Reply
  6. nasim on November 7, 2010

    hi
    i do but i have this error:
    Configure::include(/srv/www/htdocs/cakephp1.3/config/core.php): failed to open stream: No such file or directory in /srv/www/htdocs/cakephp1.3/cake/libs/configure.php on line 391
    PHP Warning: Configure::include(): Failed opening ‘/srv/www/htdocs/cakephp1.3/config/core.php’ for inclusion (include_path=’/srv/www/htdocs:/srv/www/htdocs/cakephp1.3/:.:/usr/share/php5:/usr/share/php5/PEAR’) in /srv/www/htdocs/cakephp1.3/cake/libs/configure.php on line 391
    PHP Fatal error: Can’t find application core file. Please create /srv/www/htdocs/cakephp1.3/config/core.php, and make sure it is readable by PHP. in /srv/www/htdocs/cakephp1.3/cake/libs/configure.php on line 392

    please help me

    Reply
  7. Hamdi Ben Abdallah on November 20, 2010

    You should use the params: –app and –core and use absolute path to get ride of this errors and warnings

    Reply
  8. Sergey Lempert on January 20, 2011

    Does not work for me. Lots of warnings.

    Reply
  9. Ritesh on March 2, 2011

    i need a quick solution. however does it work http://book.cakephp.org/view/108/The-CakePHP-Console ?

    Reply
  10. Jordan on April 15, 2011

    Works great, thanks a million!

    Reply
  11. […] PluginFor several months now I’ve been triggering functions in my CakePHP controllers using crontabs. It’s especially handy for summarizing data and sending out reports via email. I’m […]

    Reply
  12. deepak on June 30, 2011

    Hi dear,

    thanks for posting this…but when i m implementing it and run it in my localhost at command line
    app/webroot/cron_dispatcher.php /crons/users/
    so it is always returing the error
    config – CORE/cake/basics.php, line 61
    require – CORE/cake/libs/model/connection_manager.php, line 27
    App::__load() – CORE/cake/libs/configure.php, line 962
    App::__find() – CORE/cake/libs/configure.php, line 939
    App::import() – CORE/cake/libs/configure.php, line 866
    App::import() – CORE/cake/libs/configure.php, line 808
    require – CORE/cake/libs/model/model.php, line 29
    App::__load() – CORE/cake/libs/configure.php, line 962
    App::__find() – CORE/cake/libs/configure.php, line 939
    App::import() – CORE/cake/libs/configure.php, line 866
    App::__settings() – CORE/cake/libs/configure.php, line 1047
    App::import() – CORE/cake/libs/configure.php, line 824
    ClassRegistry::init() – CORE/cake/libs/class_registry.php, line 138
    Controller::loadModel() – CORE/cake/libs/controller/controller.php, line 509
    Controller::constructClasses() – CORE/cake/libs/controller/controller.php, line 463

    Fatal error: Call to undefined function mysql_query() in /opt/lampp/htdocs/giftpipe/cake/libs/model/datasources/dbo/dbo_mysql.php on line 499

    Reply
  13. mark on July 17, 2011

    @sergey:
    use
    http://book.cakephp.org/view/1110/Running-Shells-as-cronjobs
    this is a good and working documentation for cake1.2/cake1.3

    Reply
  14. Vibha on October 17, 2011

    Hi, I’hv folloed your script

    and I am setting my cronjob as
    */5 * * * * /usr/local/lib/php /home/../cron_dispatcher.php /devices/checkForAlert

    whereas in checkForAlert function of devices controller i’ve just printed ‘hi’ but mail from cronjob only consists of /bin/sh: /usr/local/lib/php: is a directory

    Can you please tell me that is going wrong here…

    Reply
  15. Vibha on October 17, 2011

    Hi, sorry for an inconvenience, I was setting path for php folder instead of php bin…

    Reply
  16. Vibha on October 17, 2011

    Thanx for your code…Its helpful…

    Reply
  17. Chris on November 19, 2011

    Great Article! This really cleared it up for me. This is good for Cake 1.3 . Older versions I think use a much different index.php file

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Pin It on Pinterest

Subscribe To Our Newsletter

Subscribe To Our Newsletter

Join our mailing list to receive the latest news and updates from our team.

You have Successfully Subscribed!

%d bloggers like this: