Writing Cron Jobs and Command Line Scripts in CodeIgniter
4 min read

Writing Cron Jobs and Command Line Scripts in CodeIgniter

Writing Cron Jobs and Command Line Scripts in CodeIgniter

Building a command line interface into your application can be a way to add extra utility to your application. Adding cron jobs (a.k.a. scheduled tasks) to your CodeIgniter application can provide additional utility. In this article, we’ll show you how to set up both in a CodeIgniter application by writing a simple appointment reminder, which will remind people if they have an appointment scheduled a day in advance.

Running Code Via The Command Line

You can access all CodeIgniter controller methods via the command line. Let’s start with a simple controller:

<?php
class Hello extends CI_Controller
{
  public function index()
  {
    echo "Hello, World" . PHP_EOL;
  }
  public function greet($name)
  {
   echo "Hello, $name" . PHP_EOL;
  }
}

From the application root folder, to call the index function we can do the following:

php index.php hello

By passing the name of the controller to index.php, we can invoke the index method of the controller. If we want to invoke other methods, we can pass them as the next arguments. Any arguments proceeding those will be passed as arguments to the method we are calling. So, to get the output of “Hello, Glenn” from this controller, we would run the following:

php index.php hello greet Glenn

Detecting command line requests

You may want to write controller methods that behave differently based on whether or not they are accessed via the command line. you can do this by using the input library, which has a function called is_cli_request() to detect if a request to a controller is from the command line or not. Here is an example if you want to make a method only accessible via command line:

 <?php public function greet($name) { if(!$this->input->is_cli_request())
      {
          echo "greet my only be accessed from the command line";
          return;
      }
      echo "Hello, $name" . PHP_EOL;
  }

Setting up the Appointment Reminder

Let’s say we have a system where people can book appointments. We would like to send them a reminder a day in advance that they have an appointment coming up. In this tutorial, we will set up a command line script Let’s set up our appointment reminder files. First let’s start by building the table.

CREATE TABLE appointments (
  id int auto_increment primary key,
  email varchar(255) not null default '',
  start_time datetime
  is_reminded tinyint(1) not null default 0
);

Now, we’ll write a model that will perform the two primary data functions we need for this appointment reminder: a way to fetch all appointments on a particular day and a way to mark appointments that have recieved reminders so that we do not send multiple reminder emails:

class Appointment_model extends CI_Model
{
  public function get_days_appointments($day)
  {
    $day_start = date('Y-m-d 00:00:00', $day);
    $day_end = date('Y-m-d 23:59:59', $day);
    return $this->db->select('*')
      ->from('appointments')
      ->where('start_time <', $day_start) ->where('start_time >', $day_end)
      ->get()->result();
  }
  public function mark_reminded($appointment_id)
  {
    return $this->db->where('id', $appointment_id)->update('appointments', array('is_reminded' => 1));
  }
}

Now that we can handle all the data transactions through the model. Let’s write a controller so we can access this through the command line. In this example, we will put the logic in the index() function, since that is all this controller does. Personally, I like to put all of my command line scripts inside a folder named ‘cli’ inside of the controllers folder.

<?php class Reminders extends CI_Controller { public function __construct() { parent::__construct(); $this->load->library('input');
    $this->load->library('email');
    $this->load->model('Appointment_model');
  }
  public function index()
  {
    if(!$this->input->is_cli_request())
  {
      echo "This script can only be accessed via the command line" . PHP_EOL;
      return;
  }
  $timestamp = strtotime("+1 days");
  $appointments = $this->Appointment_model->get_days_appointments($timestamp);
  if(!empty($appointments))
  {
      foreach($appointments as $appointment)
      {
          $this->email->set_newline("\r\n");
          $this->email->to($appointment->email);
          $this->email->from("youremail@example.com");
          $this->email->subject("Appointment Reminder");
          $this->email->message("You have an appointment tomorrow");
          $this->email->send();
          $this->Appointment_model->mark_reminded($appointment->id);
      }
  }
  }
}

Whenever you call this command line script, it will set an email to all people who have an appointment the next day. It will also mark their appointments as reminded to ensure that we do not send multiple emails to the same individual for the same appointment.

Setting up a Cron Job (Scheduled Task)

We would like to call this command line script once a day, at 1 pm. You can edit the cron jobs your server runs with the following command:

crontab -e

each line of the crontab file takes six arguments, which are, in order:

  • minutes (0 to 59)
  • hours (0 to 23)
  • day of month (1 to 31)
  • month (1 to 12)
  • day of week (0 – 6)
  • command (command to be executed)

you can use commas to seperate multiple values (so 1,3,5 in the day of week field will be every Monday, Wednesday, and Friday) , dashes to represent ranges(so 09-17 in the hour field means every hour on the hour from 9am to 5pm) and * for wildcards. (so * in the hours fields means every hour on the hour)

Since we would like this script to run once a day at 1pm, our new entry into the crontab file would look like this:

0 13 * * * php [application_path]/index.php cli/reminders

And now we can send out appointment reminders once a day. This Article Has a lot of good examples for other ways to set up your scheduled tasks.

I also have a small helper file I use in CodeIgniter to make formatting output easier. You can check it out over on Github.

cli_helper on Github