Cronjobs in CakePHP 2.*.* in 5 steps

Written on 30 August 2012, 07:34pm

Tagged with: , ,

Just adapting a solution from 2006 to the 2012 version of CakePHP ๐Ÿ™‚
Calling controller actions from cron and the command line

Step 1: copy app/webroot/index.php to app/cron.php

Step 2: edit app/cron.php
Change the last 3 lines of code as follows:

//---------THESE LINES:
	App::uses('Dispatcher', 'Routing');

	$Dispatcher = new Dispatcher();
	$Dispatcher->dispatch(new CakeRequest(), 
		new CakeResponse(array('charset' => Configure::read('App.encoding'))));

//-----------CHANGE TO:
	App::uses('Dispatcher', 'Routing');

	define('CRON_DISPATCHER',true); 

	if($argc == 2) { 
		$Dispatcher = new Dispatcher();
		$Dispatcher->dispatch(new CakeRequest($argv[1]), 
			new CakeResponse(array('charset' => Configure::read('App.encoding'))));
	}

Step 3: create Controller/CronController.php

 class CronController extends AppController {

	public function beforeFilter() {
	    parent::beforeFilter();
	    $this->layout=null;
	}

	public function test() {
		// Check the action is being invoked by the cron dispatcher 
		if (!defined('CRON_DISPATCHER')) { $this->redirect('/'); exit(); } 

		//no view
		$this->autoRender = false;

		//do stuff...

		return;
	}
}

Step 4: Run your cron using the command line:

# php ./app/cron.php /cron/test

Step 5: Test that loading the same script in browser is not allowed (for security reasons):
http://yourdomain/cron/test redirects to http://yourdomain/

Comments (44)

  1. romain Gires — September 11, 2012 at 09:51

    hi

    must also change, since it rises to the level constant

    
    line 38		define('ROOT', dirname(dirname(dirname(__FILE__))));
    to			define('ROOT', dirname(dirname(__FILE__)));
    
    line 45		define('APP_DIR', basename(dirname(dirname(__FILE__))));
    to			define('APP_DIR', basename(dirname(__FILE__)));
    
    line 66		define('WEBROOT_DIR', basename(dirname(__FILE__)));
    to			define('WEBROOT_DIR', basename(__FILE__));
    
    line 70		define('WWW_ROOT', dirname(__FILE__) . DS);
    to			define('WWW_ROOT', __FILE__ . DS);
    

    croogo 1.4.3
    cakephp 2.2.1

    best regard
    romain Gires

    Reply

    • Agbaje Olalekan — December 30, 2015 at 23:20

      Thank you for saving me the stress – Romain Gires. Your comment made all the difference.

      Reply

  2. e — October 1, 2012 at 14:22

    hi i cant run cron job in cpanel plz help
    i think error in command line

    Reply

  3. Kundan — December 2, 2012 at 19:29

    Thanks For article.

    Really helpful.

    Reply

  4. Pilinet — January 17, 2013 at 10:37

    I followed the instruction step by step (I changed too the ROOT and APP constants), but it’s not working. I create a test function to write some outputs on the screen. The shell doesn’t show any error, but the function it’s not been executed. It recognizes the controller and the function (if I write a wrong name it shows and error message) but it doesn’t show me the output.

    I’ve been digging into all the code and in Controller.php, in the startupProcess function, if I comment out this line it’s working perfectly and shows me the outputs. But of course I can’t leave this line comment out.

    
    public function startupProcess() {
    		$this-gt;getEventManager()-gt;dispatch(new CakeEvent('Controller.initialize', $this));
    		// $this-gt;getEventManager()-gt;dispatch(new CakeEvent('Controller.startup', $this));
    }
    

    Any idea what it can be the problem??

    Reply

    • Dorin M — January 17, 2013 at 11:21

      Can you post the relevant bits of code somewhere? (app/cron.php and Controller/YourCronController.php)
      You shouldn’t change the Cake’s internal Controller.php; at least not for implementing this ๐Ÿ™‚

      Reply

  5. Pilinet — January 17, 2013 at 11:41

    This is my cron_dispatcher.php

    
    	if (!defined('DS')) {
    		define('DS', DIRECTORY_SEPARATOR);
    	}
    
    	if (!defined('ROOT')) {
            define('ROOT', dirname(dirname(__FILE__)));
        }
    
        if (!defined('APP_DIR')) {
            define('APP_DIR', basename(dirname(__FILE__)));
        }
    	if (!defined('WEBROOT_DIR')) {
    		define('WEBROOT_DIR', basename(dirname(__FILE__)));
    	}
    	if (!defined('WWW_ROOT')) {
    		define('WWW_ROOT', dirname(__FILE__) . DS);
    	}
    
    	if (!defined('CAKE_CORE_INCLUDE_PATH')) {
    		if (function_exists('ini_set')) {
    			ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
    		}
    		if (!include('Cake' . DS . 'bootstrap.php')) {
    			$failed = true;
    		}
    	} else {
    		if (!include(CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) {
    			$failed = true;
    		}
    	}
    	if (!empty($failed)) {
    		trigger_error("CakePHP core could not be found.  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);
    	}
    	
    	App::uses('Dispatcher', 'Routing');
    	define('CRON_DISPATCHER',true);
    	$Dispatcher = new Dispatcher();
    	$Dispatcher->dispatch(new CakeRequest($argv[1]), new CakeResponse(array('charset' => Configure::read('App.encoding'))));
    

    And this is my Controller/CronController.php:

     class CronController extends AppController {
    	 
    	public function beforeFilter() {
    				parent::beforeFilter();
    				$this->layout=null;
    	}	
       public function test() {
    			//if (!defined('CRON_DISPATCHER')) { $this->redirect('/'); exit(); }
    			echo ('hello');        
    			die;
    		}
    }
    

    And invoke test action by the console like this:
    php cron_dispatcher.php /Cron/test

    I have no response. No errors, nothing
    Dont worry, I just was changing the Cake controller only to check where the execution was stopped, but I didn’t commit those changes .

    Thank you for your time.

    Reply

    • Dorin M — January 17, 2013 at 11:56

      From which path are you running the php command?

      Reply

      • Pilinet — January 17, 2013 at 11:57

        From the app folder, where I have located the cron_dispatcher.php

        • Dorin M — January 17, 2013 at 12:03

          What happens if you load the url from your browser?
          Instead of echo() do a debug() (make sure your debug level is >1 in core.php) and comment the die. Something like:

          public function test() {
              if (!defined('CRON_DISPATCHER')) { $this->redirect('/'); exit(); }
              debug(ROOT);
          }
          

        • Dorin M — January 17, 2013 at 12:05

          Also check if it works with lowercase ‘cron’:
          php cron_dispatcher.php /cron/test
          What Cake and PHP version are you using?

          • Pilinet — January 17, 2013 at 12:20

            If I execute it in the browser I get the “Hello” output, or if I do a debug I get the path of my controller
            /app/Controller/CronController.php (line 11)
            The result is the same with lower case.
            I’m using PHP 5 and CakePHP 2.2

        • Dorin M — January 17, 2013 at 12:26

          Strange.
          I’ll have a better look on this later today

          • Pilinet — January 17, 2013 at 12:28

            Yes, really strange, for me has no sense. I’m going nuts with this.
            Thank you very much, I really appreciate your help ๐Ÿ™‚

          • Pilinet — January 17, 2013 at 14:22

            These are the values that the constants have. In case the problem is in there
            ROOT = absoloute path to my root directory
            APP_DIR = app
            WWW_ROOT = absolute path to my webroot directory
            WEBROOT_DIR = webroot

  6. Pilinet — January 17, 2013 at 15:01

    It’s solved!! I need to specific allow the action in the controller. I don’t really understand why for me it’s not working without it, but at least, it’s working ๐Ÿ™‚

    function beforeFilter() {
    	$this->Auth->Allow('test');		
    }
    

    Anyway, thank you so much for your attention.

    Reply

    • Dorin M — January 17, 2013 at 15:02

      Ok, so it was because of the authentication module.
      Good to know it’s solved ๐Ÿ™‚

      Reply

  7. Mahesh Ramasamy — January 25, 2013 at 13:13

    Hi,

    I put my cron job in CronController.php. I set a cron in my bluehost server to execute the php file. is this correct to run cron job in cakephp? If i put a cron.php in /app root what will happen?

    Reply

    • Dorin M — January 25, 2013 at 14:18

      Please re-read the post. It’s all there ๐Ÿ™‚

      Reply

  8. Mahesh Ramasamy — January 25, 2013 at 13:48

    how to set cron command if put my app like doman.com/sub-folder/cakephp 2.2/app/webroot?

    Reply

    • Dorin M — January 25, 2013 at 14:21

      It doesn’t matter how your Cakephp is set up. The important thing is to put the cron.php inside the app/ folder. Of course, in the cron command you need to adapt the paths:
      php /home/youruser/path/to/app/cron.php /cron/test

      Reply

  9. jatin — February 12, 2013 at 12:23

    i found “No input file specified.” in output . can any one help me please

    Reply

  10. Vipul — September 5, 2013 at 07:23

    Thanks Dorin,
    It worked perfectly on cakephp 2.3 after changing ROOT paths as suggested by Romain. Thanks to both of you for such apt and quick article.

    Reply

  11. Michael — December 5, 2013 at 18:18

    I’ve got this to a stage where it will echo “test” at the command line. I can’t get a database connection to work however. Continues to return “could not find driver” when i try a manual PDO connection, and MysqlConnectionExemption when I try the standard loadModel route.

    Any suggestions?

    Reply

  12. Martin Bean — March 6, 2014 at 10:49

    Or you could just create a Console task and leave the core PHP files alone. Console tasks were made for this exact scenario.

    Reply

  13. Neeraj — April 2, 2014 at 11:38

    Hello Dorin,

    I used your code for a cron job in cakephp, it was working great. But after 3 weeks, it start giving me a error of “Undefined variable $argc” which is used in “if($argc == 2)”.

    Can you please explain and resolve this issue? i shall be very much thankful to you for this.

    Reply

    • Martin Bean — April 2, 2014 at 11:42

      Because Dorinโ€™s not used the best approach for Cron jobs in CakePHP. Take a look at Consoles and Shells in CakePHPโ€™s official Cookbook: http://book.cakephp.org/2.0/en/console-and-shells.html

      Reply

      • Neeraj — April 2, 2014 at 12:08

        Thanks Martin,

        i understand its not a official standard but the Consoles and Shell are confusing to me. I tried that but i didn’t find the solution in there. Can you help me in there?

      • Martin Bean — April 2, 2014 at 12:14

        @Neeraj What exactly did you find confusing about the documentation on Console and Shells?

      • Dorin Moise — April 2, 2014 at 21:08

        @Martin – you’re right about the approach. It’s not the best one, but it certainly worked and was relatively easy to implement two years ago.
        If I had to start over I would certainly give the Console and Shells a try.
        Thanks for pointing this out!

  14. Neeraj — April 2, 2014 at 12:21

    Well the documentation used the command-line introduction and i am not that much good in there. I tried it but i found it difficult to create and use.

    Commands like.. $ cd /path/to/cakephp/app and $ Console/cake . I know they are declaring the path to folders and files but i can’t debug anything in there.

    As i never used Command Line functionality So i can’t go deeper in there.

    Reply

    • Dorin Moise — April 2, 2014 at 20:58

      @Neeraj
      Here is a Linux command cheat sheet – hope you find it useful!

      Reply

      • Neeraj — April 11, 2014 at 06:50

        Thanks Dorin, for the wonderful help.

  15. Pearline — May 5, 2014 at 13:28

    If you have to warning some sort of long term contract, it
    really is well-advised which you look at in which agreement to see anything that stands out.
    An online marketing system is the perfect way to get started online,
    because you get to build your list and get educated at the same time.
    A skilled SEO campaigner knows to ease out a complex site and re-structure
    it to suit real users as well as search engines.

    Reply

  16. Jimesh — May 23, 2014 at 14:42

    I am using cakephp 2.4.7.

    I have copy index.php to cron.php in webroot.

    I ran cron using command prompt. Cron works fine but i got an error like HTTP_HOST and other variable is not define in boostrap.php. My code in boostrap.php is like below,

    if($_SERVER["HTTP_HOST"] == "localhost") {
    	define("PROJECT_DIR"					, "warehouse");
    	define("DEVEL"							, 1);
    	define("HTTP_PATH"						, "http://" . $_SERVER["HTTP_HOST"] . "/warehouse/");
    	define("HTTPS_PATH"						, "http://" . $_SERVER["HTTP_HOST"] . "/warehouse/");
    	define("HTTP_ADMIN_PATH"				, "http://" . $_SERVER["HTTP_HOST"] . "/warehouse/admin/");
    }
    

    If I remove code from boostrap.php, cron is display blank.

    Reply

  17. Chandni — December 5, 2014 at 13:39

    hello I am following your instructions but when I type in command
    php cron.php /Cron/test or php cron.php /cron/test
    I got the below error :
    Could not open input file: cron.php
    and when I am trying using url test like : http://mydomain.com/cron/test
    then I am getting : Missing Controller error
    Please HELP!!

    Reply

  18. Tanvir — February 11, 2015 at 11:06

    I’m using CakePHP 2.5.x and trying the same, but getting Missing controller error.

    I tried –
    php cron.php cron/test
    php -q cron.php cron/test

    both gives me the following:

    Missing Controller
    Error: TestController could not be found.

    NEED URGENT HELP

    Reply

    • Martin Bean — February 11, 2015 at 22:53

      Have you tried reading the error message? It tells you exactly what the error is: TestController could not be found.

      Reply

      • Tanvir — February 12, 2015 at 14:57

        Why do I need a TestController? I already have a CronController and that worked in all my provious projects in 2.x until I got the 2.5.x – and now it’s showing the error. This is my CronController, running the code should give me 10 Hello:

        $this->layout = null;
        		$this->autoRender = false;
        		if (!defined('CRON_DISPATCHER')) {
        		
        		}
        	}
        	/**
        	 * to run this from command line run this:
        	 * php -q app/cron.php cron/test
        	 */
        	public function test() {
        		//no view
        		$this->autoRender = false;
        
        		for($i = 1; $i <= 10; $i++) {
        			echo "{$i}. hello\r\n";
        		}
        		exit;
        		return;
        	}
        }
        

  19. 私はこれをお楽しみください。あなたが高品質の記事を書くことに運ぶしてください。

    Reply

  20. Jairo Jose Rodriguez — November 18, 2016 at 16:11

    You have to change three points.

    1. Remember that to name the controllers in cakephp, you must follow the conventions, in this case you must modify the name of CronController.php to CronsController.php

    2. In the cron.php file you must modify the following line: $ Dispatcher-> dispatch (new CakeRequest ($ args [1]), new CakeResponse (array ( ‘charset’ => Configure :: read ( ‘App.encoding ‘)))); by
    ย  $ Dispatcher-> dispatch (new CakeRequest ( ‘/ Crons / indexes’), new CakeResponse (array ( ‘charset’ => Configure :: read ( ‘App.encoding’))));

    If you look at I’m passing in the initialization of the object the path of my controller and method.

    3. In the cronjobs you configured you must specify that you are not sending parameters, but simply calling the php file to execute a task. As follows:
    php /home/tusuariocpanel/public_html/youtApp/app/cron.php

    This works for me wonderfully and I’m using cakephp 2.6.

    regards

    Reply

  21. harendar tomar — July 27, 2017 at 12:05

    Hello, i did what your article says and run the command from terminal it gives the error
    PHP Fatal error: Class ‘App’ not found in app-path-here/cron.php on line 90
    cron.php code
    dispatch(new CakeRequest($argv[1]), new CakeResponse(array(‘charset’ => Configure::read(‘App.encoding’))));
    }

    Reply

    • harendar tomar — July 27, 2017 at 12:06

      dispatch(new CakeRequest($argv[1]), new CakeResponse(array(‘charset’ => Configure::read(‘App.encoding’))));
      }

      Reply

  22. Agueda — August 14, 2019 at 23:03

    Tirana: EDFA. ROSA, Samuel. Like i said though I have played.

    Reply

Leave a response