A Tutorial on how to setup a Cron Job for CakePHP 2.x on shared hosting

in CakePHP/PHP/Web Development

I recently had to setup a cron job on shared hosting for one of my CakePHP projects. And although I have done this often, I always seem to forget the steps and something that should take me 5 minutes end up taking 15-30 minutes. So here is a quick tutorial on how to setup a Cron Job for CakePHP 2.x on shared hosting. In my case, I am using Bluehost but this should work for HostGator or any other shared hosting provider that gives you acces to crons through the cPanel.

The Initial Setup

Before begining the tutorial, its important to understand CakePHP Console and Shells. You can read about them in the CakePHP 2.x Cookbook. Basically, console applications are ideal for handling a variety of background tasks such as maintenance, and completing work outside of the request-response cycle. Using the console, you can create shells for use in the console. What’s really awesome about CakePHP shells is that they provide easy access to your models by using the $uses property, you can define an array of models you want to have access to in your shell. A typical install of CakePHP 2.x will have the Cakeshell executable located in the app/Console/ folder. There are 3 variations of the cakeshell provided in this folder:

  • cake: which is the standard bash version of the cakeshell
  • cake.bat: which is the Windows version of the cakeshell used on Windows environments
  • cake.php: which is the PHP version of the cakeshell used in PHP setups. This is the version we will be using on shared hosting accounts

A Simple Cakeshell Application

For this tutorial, we will be building a simple cakeshell application that sends emails to users who have not confirmed their email address. The shell uses the User model and since it is a mailing shell, it also uses CakePhP’s CakeEmail. Below is the source code for this simple shell script that emails users that have not yet confirmed their email address.

<?php
App::uses('CakeEmail', 'Network/Email');
class UsersUpdateShell extends AppShell {
    public $uses = array('User');

    public function remind_unconfirmed_users() {
       $conditions = array('conditions'=>array('User.email_confirmed'=>false));
	   $unconfirmed_users = $this->User->find('all',$conditions);
	   foreach($unconfirmed_users as $unconfirmed){
		  $this->sendConfirmationEmailRemider($unconfirmed);
	   }
    }
}
?>

I have named the above file UsersUpdateShell.php. This shell, along with any other shell files that are created in CakePHP must be placed in the app/Console/Command/ folder. Therefore, the full path becomes app/Console/Command/UsersUpdateShell.php. This shell will work as-is using the CakePHP console. Now, we want to run it as a cron job on our shared hosting account.

Setting up the Shell as a Cron Job

Now that the shell has been created, we need to add it to our cronjob using cPanel. You first need to find the Cron menu in cPanel. Below is a screenshot of the bluehost cPanel page for cron jobs.

bluehost-cronjob-menu

According to the CakePHP documentation, you should run your shell as a cron job using the following command

cd /full/path/to/app && Console/cake myshell myparam

This does not exactly work for shared hosting and some slight tweeking is required. You need to call a command similar to what CakePHP suggests but keeping in mind the limitations of shared hosting: you need to provide full paths and you probably will not have access to bash. So let’s assume that you installed your application at the root folder of /home/myawesomesite/public_html/, then you will have to setup the following command for your cron job

php -c /home/myawesomesite/public_html/php.ini /home/myawesomesite/public_html/app/Console/cake.php -app /home/myawesomesite/public_html/app -working /home/myawesomesite/public_html/app UsersUpdate remind_unconfirmed_users > /home/myawesomesite/public_html/app/tmp/logs/cron_logs.txt 2>&1

Here is an analysis of the command above:

  • php -c /home/myawesomesite/public_html/php.ini /home/myawesomesite/public_html/app/Console/cake.php tells the comnand line that we will be running a php script called cake.php. I also provide the additional parameter of -c which allows me to specify which configuration file that I want to use. In this example, I created a php.ini configuration file at /home/myawesomesite/public_html/php.ini that I want to use. This is important to do because on some servers, the environment variable register_argc_argv is turned off. If it is turned off, PHP will not be able to read any extra parameters that are required for your Cakeshell to execute and you will get the very frustrating and not very helpful error message: Error: This file has been loaded incorrectly and cannot continue. Please make sure that /lib/Cake/Console is in your system path, and check the cookbook for the correct usage of this command..
  • /home/myawesomesite/public_html/app/Console/cake.php -app /home/myawesomesite/public_html/app corresponds the command to start the cake console and the -app option tells CakePHP where your app folder is located. The -working option tells CakePHP where your working folder is located. The working folder should always be your app folder.
  • UsersUpdate corresponds to the shell to execute
  • remind_unconfirmed_users corresponds to the function to execute
  • > /home/myawesomesite/public_html/app/tmp/logs/cron_logs.txt 2>&1 forces all output to be directed to a logfile that I have setup in the tmp folder under the filename cron_logs.txt. This is optional and not really required but I like to keep my logs clean 🙂

Final notes

That’s all there is to setting up a cron job through Cakeshell. Keep in mind that I do not cover the actual aspect of managing when the cron actually runs. This should be straightforward, especialy with the graphical interface on Cpanel. Note that, depending on your hosting provider and your setup, you may have to modify the permission of the file app/Console/cake to 754 so that it can actually be executed. You will also notice that I store my output to a file called /home/myawesomesite/public_html/app/tmp/logs/cron_logs.txt. If you don’t want to log your script outputs, then Bluehost suggest sending the output to /dev/null 2>&1 instead. And that’s all there is to setting up cron jobs on shared hosting with CakePHP 2.x

Tags:

Mifty Yusuf is a Montreal-based software developer who enjoys playing with new web technologies as well as comic books and illustrations. He beleives that, no matter what the question is, the answer is always Batman!

10 Comments

  1. Hi Mifty, Thanks for your effort in sharing knowledge with others.
    Can you please share with me the content of the php.ini file you said you created in the analysis above(php -c /home/myawesomesite/public_html/php.ini).
    I was working on cron-job on a shared host few month a ago i had to abandon it and seek for an alternative. I seem to follow similar steps as you did but i guess i lost out of it in the php.ini part as you have explain.i hope you would kindly find time to respond to my question. Thanks

  2. Thanks for the response Mifty,
    how do i get to turn On register_argc_argv.

    You explained you had to turn it On in your case by creating a new php.ini file. what does the new php.ini looks like

    I think this might just be the last this i will have to do to get jron job to work on my shared hosting plan.

    • My new php.ini file looks exaclty like the old one, other than the fact that I turned on this paramater. What I would suggest is that you copy your current php.ini file and update the line containing this value. In my new php.ini, it is exactly like my old php.ini except with the following modified line:

      register_argc_argv = On
      
  3. Thank alot Miffy, cron now works on my site.
    Thanks for always responding to my questions.

    Cakephp tuts on yours site has been of great help to me.
    I will also appreciate if you can do a quick tutorial on the new Google reCAPTCHA 5.0, i just like it but googles docs is not detail enough.

  4. Hi Mifty,
    I have tried the procedure you have discussed above for my CakePhp 3.2 Application. Initially I used the command you have mentioned above but it gives the entire php page and gives a 500 Internal Server Error. Then I have changed the command to this

    /home/user/public_html/bin/cake -app /home/user/public_html/src vimeo update_thumb > /home/user/public_html/logs/shell_logfile.log 2>&1

    and my Cake shell is running and gives this output to my log file

    Welcome to CakePHP v3.2.2 Console
    —————————————————————
    App : src
    Path: /home/user/public_html/src/
    PHP : 5.5.38
    —————————————————————
    Current Paths:

    * app: src
    * root: /home/user/public_html
    * core: /home/user/public_html/vendor/cakephp/cakephp

    Available Shells:

    [Migrations] migrations

    [Proffer] proffer

    [CORE] i18n, orm_cache, plugin, routes, server

    [app] console, vimeo

    To run an app or core command, type `cake shell_name [args]`
    To run a plugin command, type `cake Plugin.shell_name [args]`
    To get help on a specific command, type `cake shell_name –help`

    X-Powered-By: PHP/5.5.38
    Content-type: text/html

    but the Shell file and function I have passed as parameter is not executing. I have asked to the hosting provider about environment variable register_argc_argv and they said it’s already woking.
    Please help me
    Thanks in advance

  5. Hi,

    Great tutorial however, my cron job wont run properly because I get the error message in my log

    2017-10-14 21:34:02 Error: Fatal Error (64): Cannot use ‘String’ as class name as it is reserved in [/home/allfan5/public_html/allfans/lib/Cake/Utility/String.php, line 25]
    2017-10-14 21:34:02 Error: [FatalErrorException] Cannot use ‘String’ as class name as it is reserved
    Stack Trace:
    #0 /home/allfan5/public_html/allfans/lib/Cake/Error/ErrorHandler.php(203): ErrorHandler::handleFatalError(64, ‘Cannot use ‘Str…’, ‘/home/allfan5/p…’, 25)
    #1 /home/allfan5/public_html/allfans/lib/Cake/Core/App.php(929): ErrorHandler::handleError(64, ‘Cannot use ‘Str…’, ‘/home/allfan5/p…’, 25, Array)
    #2 /home/allfan5/public_html/allfans/lib/Cake/Core/App.php(902): App::_checkFatalError()
    #3 [internal function]: App::shutdown()
    #4 {main}

    I am using CakePHP 2.5 running on PHP 5.5. I have verified that my code in my shell works correctly because I have dumped it into a normal controller and ran it without a problem. So there is some issue with how the cron called or how it operates. I copied your example and changed the path to my app to my shared hosting location and I changed the body of the shell method to my own code (which again works fine when executed outside of the shell).

  6. I wouldn’t recommend shared hosting because it has poor performance and security. I would recommend you to host CakePHP on a vps instead. VPS like DigitalOcean and Linode are quite affordable. If you don’t know how to setup a vps, then you can use platform, like Cloudways, for that.

Leave a Reply

Your email address will not be published.

*

Latest from CakePHP

Go to Top