title: How to run a cron job on a CodeIgniter controller that all the URL does is run a query from an API, update the DB & send emails (from within CI)?
body: <p>I have a web application that runs a query on an api, gets new information, changes the variables in the database and sends emails if needed (compares old and new variables).  </p>
  
  <p>I work with Ubuntu Server, and I tried several variations to run this. </p>
  
  <p>my controller looks like this:</p>
  
  <pre><code>class Cli_only extends CI_Controller {
  
      public function __construct() {
  
         parent::__construct();
          is_cli() OR show_404(); // If cronjob ! 
  
         $this-&gt;load-&gt;model('kas_model');
  
          // Sets the server not to have a time out. 
          ini_set('max_execution_time', 0); 
          ini_set('memory_limit', '-1');      
          // Expand the array displays
          ini_set('xdebug.var_display_max_depth', 5);
          ini_set('xdebug.var_display_max_children', 256);
          ini_set('xdebug.var_display_max_data', 1024);
      }
  
  
  
      // This function has to run every day using a corn job. 
      public function cron_job(){
          // does stuff...
      }
  </code></pre>
  
  <p>So at first I tried using the regular 'curl' command on my cronjob: </p>
  
  <p><code>15 15 * * * http://10.0.1.666/tools/Cli_only/cron_job</code></p>
  
  <p>and I got this error in the log file: </p>
  
  <pre><code>Dec 6 15:30:01 MYserver CRON[1134]: (root) CMD (curl http://10.0.1.66/tools/Cli_only/cron_job) 
  Dec 6 15:30:02 MYserver CRON[1133]: (CRON) info (No MTA installed, discarding output)
  </code></pre>
  
  <p>running a quick google on this and I noticed that I have to install "postfix" on my server, and I did. I restarted cron and get: </p>
  
  <pre><code>Dec  6 16:26:01 MYserver cron[2663]: (root) RELOAD (crontabs/root)
  Dec  6 16:26:01 MYserver CRON[2703]: (root) CMD (curl http://10.0.1.666/tools/Cli_only/cron_job)
  Dec  6 16:26:01 MYserver postfix/pickup[2479]: 23430102E11: uid=0 from=&lt;root&gt;
  Dec  6 16:26:01 MYserver postfix/cleanup[2707]: 23430102E11: message-id=&lt;20151206142601.23430102E11@MYserver&gt;
  Dec  6 16:26:01 MYserver postfix/qmgr[2480]: 23430102E11: from=&lt;root@MYserver&gt;, size=2058, nrcpt=1 (queue active)
  Dec  6 16:26:01 MYserver postfix/local[2709]: 23430102E11: to=&lt;root@MYserver&gt;, orig_to=&lt;root&gt;, relay=local, delay=0.02, delays=0.01/0/0/0, dsn=2.0.0, status=sent (delivered to mailbox)
  Dec  6 16:26:01 MYserver postfix/qmgr[2480]: 23430102E11: removed
  </code></pre>
  
  <p>Still, no changes on the DB - and if there were - CodeIgniter has a working mailing configurations that should work from just running the URL.</p>
  
  <p>I tried running things like this: </p>
  
  <pre><code>14 16 * * * wget -O - http://10.0.1.666/tools/Cli_only/cron_job &gt;/dev/null 2&gt;&amp;1
  
  14 16 * * * curl -O - http://10.0.1.666/tools/Cli_only/cron_job &gt;/dev/null 2&gt;&amp;1
  
  14 16 * * * GET -O - http://10.0.1.666/tools/Cli_only/cron_job &gt;/dev/null 2&gt;&amp;1
  </code></pre>
  
  <p>which I don't really know what they do - and still don't work. </p>
  
  <p><strong>EDIT:</strong> </p>
  
  <p>Just for being clear, if I run the controller on my browser, everything works perfectly! </p>
  
  <p>This is all of my code in the controller, the <em>cron_job()</em> function is right after the __construct() function: </p>
  
  <pre><code>&lt;?php 
  
  
  class Cli_only extends CI_Controller {
  
      public function __construct() {
  
         parent::__construct();
         is_cli() OR show_404(); // If cronjob ! 
         //if (!$this-&gt;input-&gt;is_cli_request()) show_error('Direct access is not allowed');          
  
         $this-&gt;load-&gt;model('kas_model');
  
          // Sets the server not to have a time out. 
          ini_set('max_execution_time', 0); 
          ini_set('memory_limit', '-1');      
          // Expand the array displays
          ini_set('xdebug.var_display_max_depth', 5);
          ini_set('xdebug.var_display_max_children', 256);
          ini_set('xdebug.var_display_max_data', 1024);
      }
  
  
  
      // This function has to run every day using a corn job. 
      public function cron_job(){
  
          // 1. Run the query that gets the table data from the DB('from kas table')
          $data['table'] = $this-&gt;kas_model-&gt;get_kas_table();
  
          // 2. Go through each row.
          foreach ( $data['table'] as $row ) {
  
              // 3.1. But first, get vars! 
              $kas_id            = $row-&gt;kas_id;
              $kas_key       = $row-&gt;kas_key; 
              $kas_id_aaa        = $row-&gt;kas_id_aaa;
              $kas_id_bbb    = $row-&gt;kas_id_bbb;
              $kas_rank1_aaa     = $row-&gt;kas_rank1_aaa;
              $kas_rank2_aaa     = $row-&gt;kas_rank2_aaa;
              $kas_rank1_bbb = $row-&gt;kas_rank1_bbb;
              $kas_rank2_bbb = $row-&gt;kas_rank2_bbb;
  
              // 3.2. move to yesterday to make place for a new query result.
              $this-&gt;kas_model-&gt;move_tod_to_yes($kas_id, $kas_rank2_aaa, $kas_rank2_bbb);
  
              // 3.3. Run the key query again for today on each one of the keys and insert to DB. 
              if ( ($kas_id_aaa != 0) || ( !empty($kas_id_aaa) ) ) {
                  $aaa_rank_today     = $this-&gt;get_rank_aaa_by_id_and_kw($kas_id_aaa, $kas_key);
              } 
  
              if ( ($kas_id_bbb != 0) || ( !empty($kas_id_bbb) ) ) {
                  $bbb_rank_today = $this-&gt;get_rank_bbb_by_id_and_kw($kas_id_bbb, $kas_key);
              }
  
              // 3.4. Add the new rank to rank2 in the DB.
              $this-&gt;kas_model-&gt;add_new_today($kas_id, $aaa_rank_today, $bbb_rank_today);
  
              // 4. Check difference as Sag described : 
              $msg = ''; 
              $send = FALSE;
              // First if: aaa
              if ( ($aaa_rank_today &gt; 10 ) &amp;&amp; ( $kas_rank2_aaa &lt; 30 ) &amp;&amp; ( ( abs( $aaa_rank_today - $kas_rank2_aaa ) ) &gt; 10) ) {
                  $msg .= 'aaa:&lt;br&gt; ( (Today &gt; 10 ) &amp;&amp; ( Yesterday &lt; 30 ) &amp;&amp; ( ( |Today - Yesterday| &gt; 10) ) ==&gt; True. &lt;br&gt;&lt;br&gt;';
                  $send = TRUE;
              }
  
              // Second if: aaa
              if ( ( ($kas_rank2_aaa &lt; 5) &amp;&amp; ($aaa_rank_today &gt; 10) ) || ( ($aaa_rank_today &lt; 5) &amp;&amp; ($kas_rank2_aaa &gt; 10) ) ) {
                  $msg .= 'aaa: &lt;br&gt;  ( ( (Yesterday &lt; 5) &amp;&amp; (Today &gt; 10) ) || ( (Today &lt; 5) &amp;&amp; (Yesterday &gt; 10) ) ) ==&gt; True. &lt;br&gt; &lt;br&gt;';
                  $send = TRUE;
              }
  
              // First if: bbb
              if ( ($bbb_rank_today &gt; 10 ) &amp;&amp; ( $kas_rank2_bbb &lt; 30 ) &amp;&amp; ( ( abs( $bbb_rank_today - $kas_rank2_bbb ) ) &gt; 10) ) {
                  $msg .= 'bbb: &lt;br&gt; ( (Today &gt; 10 ) &amp;&amp; ( Yesterday &lt; 30 ) &amp;&amp; ( ( |Today - Yesterday| &gt; 10) ) ==&gt; True. &lt;br&gt;&lt;br&gt;';
                  $send = TRUE;
              }
  
              // Second if: bbb
              if ( ( ($kas_rank2_bbb &lt; 5) &amp;&amp; ($bbb_rank_today &gt; 10) ) || ( ($bbb_rank_today &lt; 5) &amp;&amp; ($kas_rank2_bbb &gt; 10) ) ) {
                  $msg .= 'bbb: &lt;br&gt; ( ( (Yesterday &lt; 5) &amp;&amp; (Today &gt; 10) ) || ( (Today &lt; 5) &amp;&amp; (Yesterday &gt; 10) ) ) ==&gt; True. &lt;br&gt; &lt;br&gt;';
                  $send = TRUE;
              }
  
              $this-&gt;send_mail($kas_id_aaa, $kas_id_bbb, $msg, $send, $aaa_rank_today, $bbb_rank_today, $kas_rank2_aaa, $kas_rank2_bbb, $kas_key);
  
          }
  
  
  
      }
  
  
  
  
  
  
      // Gets aaa categorys Ranking by ID. 
      public function get_rank_aaa_by_id_and_kw($id, $key, $query_country){
  
          $key_for_url = rawurlencode($key);
  
          $found = FALSE; 
          $i     = 0;
  
          // Create a stream for Json. That's how the code knows what to expect to get. 
          $context_opts = array(
              'http' =&gt; array(
              'method' =&gt; "GET",
              'header' =&gt; "Accepts: categorylication/json\r\n"
          ));
          $context = stream_context_create($context_opts); 
  
          while ($found == FALSE) {
  
              // aaa Query
              $json_query_aaa = "https://api.example.com:666/aaa/ajax/research_key?category_id=$id&amp;term=$key_for_url&amp;page_index=$i&amp;country=$query_country&amp;auth_token=tokentokentoken";
              // Get the Json
              $json_query_aaa = file_get_contents($json_query_aaa, false, $context); 
              // Turn Json to a PHP array
              $json_query_aaa = json_decode($json_query_aaa, true);
              // Finally, the main categorys array. 
              $json_query_aaa = $json_query_aaa['key']['phone_categorys']['category_list'];
  
              if ( count($json_query_aaa) &gt; 2 ) {
  
                  for ( $j=0; $j&lt;count($json_query_aaa); $j++ ) {
  
                      if ( $json_query_aaa[$j]['id'] == $id ) {
                          $found = TRUE;
                          $rank  = $json_query_aaa[$j]['rank'] + 1;
                          break;
                      }
  
                      if ($found == TRUE){
                          break;
                      }
                  }
  
                  $i++;
  
              } else {
  
                  $rank = "none"; 
                  break;
  
              }
          }
  
           return $rank;
      }
  
  
      // Gets bbb categorys Ranking by ID. 
      public function get_rank_bbb_by_id_and_kw($id, $key, $query_country){
  
          $key_for_url = rawurlencode($key);
  
          $found = FALSE; 
          $i     = 0;
  
          // Create a stream for Json. That's how the code knows what to expect to get. 
          $context_opts = array(
              'http' =&gt; array(
              'method' =&gt; "GET",
              'header' =&gt; "Accepts: categorylication/json\r\n"
          ));
          $context = stream_context_create($context_opts); 
  
          while ($found == FALSE) {
  
              // aaa Query
              $json_query_bbb = "https://api.example.com:666/bbb/research_key?category_id=$id&amp;term=$key_for_url&amp;page_index=$i&amp;country=$query_country&amp;auth_token=tokentokentoken";
              // Get the Json
              $json_query_bbb = file_get_contents($json_query_bbb, false, $context); 
              // Turn Json to a PHP array
              $json_query_bbb = json_decode($json_query_bbb, true);
              // Finally, the main categorys array. 
              $json_query_bbb = $json_query_bbb['key']['phone_categorys']['category_list'];
  
              if ( count($json_query_bbb) &gt; 2 ) {
  
                  for ( $j=0; $j&lt;count($json_query_bbb); $j++ ) {
  
                      if ( $json_query_bbb[$j]['id'] == $id ) {
                          $found = TRUE;
                          $rank  = $json_query_bbb[$j]['rank']+1;
                      }
  
                  }
  
              $i++;
  
              } else {
  
                  $rank = "none"; 
                  break;
  
              }
  
          }
  
          return $rank;
      }
  
  
  
  
      // Sends to email the results 
      public function send_mail($id_aaa, $id_bbb, $msg, $send, $aaa_rank_today, $bbb_rank_today, $aaa_rank_yesterday, $bbb_rank_yesterday, $kas_key){
  
          if ($send) {
  
              $ci = get_instance();
              $config['protocol']  = "smtp";
              $config['smtp_host'] = "ssl://smtp.gmail.com";
              $config['smtp_port'] = "465";
              $config['smtp_user'] = "myEmail@example.pro"; 
              $config['smtp_pass'] = "assword";
              $config['charset']   = "utf-8";
              $config['mailtype']  = "html";
              $config['newline']   = "\r\n";
              $config['crlf']      = "\r\n";
              $config['validate']  = FALSE;
  
              $ci-&gt;load-&gt;library('email');
              $ci-&gt;email-&gt;initialize($config);
  
              $ci-&gt;email-&gt;from('myEmail@example.pro', 'key Alerting System (KAS)');
              $list = array('myEmail.do@gmail.com', 'sag@example.pro');
              $ci-&gt;email-&gt;to($list);
              $this-&gt;email-&gt;reply_to('no-reply@example.pro', 'KAS Alert');
              $ci-&gt;email-&gt;subject('KAS Alert!');
              $ci-&gt;email-&gt;message("key: $kas_key &lt;br/&gt;&lt;br/&gt; aaa ID:$id_aaa &lt;br&gt; bbb ID: $id_bbb &lt;br&gt;&lt;br&gt;&lt;br&gt; $msg&lt;br&gt;&lt;br&gt; aaa Rank Today: $aaa_rank_today&lt;br&gt; aaa Rank Yesterday: $aaa_rank_yesterday&lt;br&gt;&lt;br&gt; bbb Rank Today: $bbb_rank_today&lt;br&gt; bbb Rank Yesterday: $bbb_rank_yesterday");
              $ci-&gt;email-&gt;send();
  
          } 
  
      }
  
  
      function test(){
          echo 'banana'; 
      }
  
  
  }
  </code></pre>
  
  <p>EDIT #2: </p>
  
  <p>This works fine when not having <code>is_cli() OR show_404();</code> in the construct function. But I do want this controller to work only from a cronjob</p>
  
  <p>I get the same result with: </p>
  
  <p><code>if (!$this-&gt;input-&gt;is_cli_request()) show_error('Direct access is not allowed');</code></p>