R – Cron Jobs in a Zend Framework 1.8+ application

cronzend-framework

I am using Zend Framework 1.9.6. I want to start using cron jobs. I am new to this so I'm not quite sure how to do this.

I'm thinking it would be a good idea to store my crons in /myapp/scripts or /myapp/application/cronjobs. What do you think? (my application only has a default module)

Once I've decided on a place to store them, how would I go about creating a script? Let's say that I want to access a database, check for changes, and send an email as a report. I would need to use some Zend_Db components, and Zend_Mail components, as well as read the default config values. I guess I might even want to Bootstrap the application? But I won't need any views so I don't know if that would be the best idea. I don't know. What should I do, and how can I do it? Again, I am using version 1.9.6 and created my application with the Zend_Tool command-line script.

I think there's enough information online about how to add the cron job to the crontab file. (My web host also offers a tool to make this really easy, so I'm not so much interested in this part).

Have you done this in a 1.8+ application? Do you have an example script you could share?

Solution

Since posting this question, I have started a new job and become more comfortable working with Zend Framework. Here's what we've been doing at the company I now work for. I'm not saying this is a best practice, or ideal, but this information may be helpful to someone.

  • Create a top level bin directory to store all command line scripts.
  • Create a "CLI bootstrap" file that can be included in any command line scripts which will bootstrap the application so that you have easy access to your models just like you would if you were working with a controller.
  • All of our cron job scripts live in the bin directory so they are not publicly accessible. Also, since they are command line scripts, they do not make use of controllers or views. They are mostly simple little procedural scripts. Our cron jobs are managed manually, so we don't always remember which cron jobs we have scheduled to run.

Best Solution

I found it easiest to have the exact same configuration as my main site by having a function that created the application shared across all cronjobs and the site.

I did it this way as although there is probably quite a bit more overhead, it didn't matter as much (extra couple of milliseconds on a cronjob are nothing) and as the setup was exactly the same I never ran into any issues using shared code. For example, add database config is in exactly the same place, and if I added another namespace (as you can see I have done), I could do it globally.
The one thing that you could consider doing is using a different bootstrapper, which would reduce the cost as you don't bootstrap the views (which the cron jobs have no need for)

My setup function is (called by cronjobs and the main application):

function createApplication() {
    require_once 'Zend/Application.php';
    $application = new Zend_Application(
            APPLICATION_ENV,
            CONFIG_PATH . '/application.ini'
    );
    $application->bootstrap();

    $autoloader = Zend_Loader_Autoloader::getInstance();
    $autoloader->registerNamespace('Search_');

    return $application;
}

So as mentioned, in my cronjobs, I don't call $application->run()

However, as mentioned, you could use diffrent bootstraps for the cronjobs to avoid setting up the views. Before $application->bootstrap() is called, you need to call $application->setBootstrap()

 /*
  * @param $path the path to Bootstrap.php, if not set it will default to the 
  *             application bootstrap
  * @return Zend_Application
  */
function createApplication($path = null) {
    require_once 'Zend/Application.php';
    $application = new Zend_Application(
            APPLICATION_ENV,
            CONFIG_PATH . '/application.ini'
    );

    if ( $path ){
        $application->setBootstrap($path);
    }
    $application->bootstrap();

    $autoloader = Zend_Loader_Autoloader::getInstance();
    $autoloader->registerNamespace('Search_');

    return $application;
}
Related Question