A site I’m currently building requires a bunch of Cron jobs running daily to bring in and update various bits of data. It’s the first time I’ve needed to do this within the Yii framework, and it was a useful experience figuring out how it works. The Yii documentation located at http://www.yiiframework.com/wiki/91/implementing-cron-jobs-with-yii/ isn’t completely clear, so hopefully this post will help.
Firstly, forget about browser emulation, the best way to implement Cron jobs in Yii is by using Yii’s Console Application (CConsoleCommand) functions.
Essentially this is a separate instance of your application that can be run from the command line rather than as a publicly executable php script.
The first thing to do is to create a new entry or index script – which looks a lot like the index.php file in your public_html or root directory. However, for extra security your new index script can be (and probably should be) placed outside of the public root so you can only access it through the command line.
I called my script cron.php and dropped it on to the server below public_html. The file will look something like this:
// change the following paths if necessary $yii=dirname(__FILE__).'/framework/yii.php'; $config=dirname(__FILE__).'/public_html/protected/config/cron.php'; // remove the following lines when in production mode defined('YII_DEBUG') or define('YII_DEBUG',true); // specify how many levels of call stack should be shown in each log message defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3); require_once($yii); $app = Yii::createConsoleApplication($config)->run();
Two things to notice here. Firstly the $config information comes from a new config file I’ve called cron.php. This is very much like your main.php config file, except it contains a lot less stuff:
return array( 'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..', 'name'=>'Cron', 'preload'=>array('log'), 'import'=>array( 'application.components.*', 'application.models.*', ), // application components 'components'=>array( 'db'=>array( 'connectionString' => 'mysql:host=localhost;dbname=db_name', 'emulatePrepare' => true, 'username' => 'root', 'password' => '', 'charset' => 'utf8', 'enableProfiling' => true, ), 'log'=>array( 'class'=>'CLogRouter', 'routes'=>array( array( 'class'=>'CFileLogRoute', 'logFile'=>'cron.log', 'levels'=>'error, warning', ), array( 'class'=>'CFileLogRoute', 'logFile'=>'cron_trace.log', 'levels'=>'trace', ), ), ), 'functions'=>array( 'class'=>'application.extensions.functions.Functions', ), ), );
Secondly, you’re running Yii’s createConsoleApplication method, rather than firing up the web application.
Once you’ve done that, the next thing is to understand what this createConsoleApplication()->run(); whatsit is doing.
When this function is fired, it looks in /protected/commands for commands to run. A command takes the form of a Class file of the name YourFunctionCommand.php – yes, you must suffix it with Command.php.
Within this Class file you need something like
class VisitorsCommand extends CConsoleCommand { public function run($args) { // Do stuff } }
So this file is called VisitorsCommand.php and the class name is VisitorsCommand – get it?
Now, if you were to fire up your command line interface and run something along these lines:
/usr/bin/php /Users/james/Dropbox/Sites/mySiteRoot/cron.php
You’ll get a message saying
The following commands are available: - visitors
So now you can do
/usr/bin/php /Users/james/Dropbox/Sites/mySiteRoot/cron.php visitors
And Yii will instantiate your Visitors Class and fire the run() method.
Also… you will notice the run() method accepts a parameter – I’ve called it $args, for the sake of argument.
You can pass parameters into the run method like this
/usr/bin/php /Users/james/Dropbox/Sites/mySiteRoot/cron.php visitors param1 param2 param3
And they’ll end up in your run method as an array. You could for example write one Command class that can perform a variety of functions, or pass a key to validate the user of the Cron.
Within your new Command Class, you can access all your Models as normal to perform whatever functions you require.
Have fun!
