Ver Mensaje Individual
  #1 (permalink)  
Antiguo 03/09/2015, 01:12
Avatar de chronos682
chronos682
 
Fecha de Ingreso: febrero-2004
Ubicación: Tunja - Boyacá - Colombia
Mensajes: 627
Antigüedad: 20 años, 2 meses
Puntos: 69
[Aporte] Seudo Cron Job

Hay mucha ocasiones en las que no podemos usar Cron Jobs desde nuestro servidor, bien sea porque es gratuito y tiene limitaciones con ciertas funciones o estrictamente están deshabilitados los Cron Jobs o porque no sabemos como configurarlos, es por eso que decidí hacer este código para tratar en lo posible de solucionar el problema.

El Seudo Cron Jobs consiste en que cada vez que un usuario abra cualquiera de las páginas que componen nuestro website, lo primero que se haga sea verificar si alguna de las tareas programadas se cumplió y ejecutarla guardando la fecha y hora actual para que comience de nuevo el conteo.

Lo primero que hay que hacer es crear una tabla en la BD que se llame Cron:

Código MySQL:
Ver original
  1. CREATE TABLE IF NOT EXISTS `Cron` (
  2.   `ID` int(11) NOT NULL,
  3.   `Nombre` varchar(30) NOT NULL,
  4.   `Last` varchar(30) NOT NULL,
  5.   `Intervalo` int(11) NOT NULL
  6.  
  7.  
  8. ALTER TABLE `Cron`
  9.   ADD PRIMARY KEY (`ID`),
  10.   ADD UNIQUE KEY `Nombre` (`Nombre`);
  11.  
  12.  
  13. ALTER TABLE `Cron`

Luego se deben agregar las tareas que se quieran realizar, especificando cada cuanto se deben ejecutar (el intervalo debe estar en segundos):

Código MySQL:
Ver original
  1. INSERT INTO `Cron` (`ID`, `Nombre`, `Last`, `Intervalo`) VALUES (NULL, 'MiTarea', '1', '86400');

Reemplazar MiTarea por el nombre que le quieran dar a la tarea (no se pueden repetir) y 86400 por la cantidad de segundos que se deben completar (86400 corresponde a 24 hs).

Luego se debe crear un archivo llamado cron.php que va a contener el siguiente código:

Cron.php
Código PHP:
Ver original
  1. <?php
  2.     //Aquí la conexión a la BD, reemplazar por sus respectivos datos de conexión
  3.     define("DB_SERVER", "localhost");
  4.     define("DB_USER", "root");
  5.     define("DB_PASS", "root");
  6.     define("DB_NAME", "Prueba");
  7.     $mysqli = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
  8.    
  9.     //Función para actualizar el TimeStamp de la última ejecución
  10.     function ActualizarTime($dbID, $mySQL)
  11.     {
  12.         $nowTime = Time();
  13.         $sql= "UPDATE Cron SET  Last='{$nowTime}' WHERE ID='{$dbID}'";
  14.         $result = $mySQL->query($sql);
  15.         if ($result == false) echo "Se produjo un error al actualizar la tarea <br>";
  16.         return $result;
  17.     }
  18.  
  19.     //Se seleccionan todas las tareas que estén registradas en la tabla
  20.     $sql = "SELECT * FROM Cron";
  21.     $result = $mysqli->query($sql) or die(mysqli_error());
  22.     $iNumReg= mysqli_num_rows($result);
  23.     if ($iNumReg > 0)
  24.     {
  25.         //Se recorre una a una las tareas
  26.         while ($rowEmp = $result->fetch_assoc())
  27.         {
  28.             $dbTime = $rowEmp['Last'];
  29.             $dbInterval = $rowEmp['Intervalo'];
  30.             $dbNombre = $rowEmp['Nombre'];
  31.             $dbID = $rowEmp['ID'];
  32.             $nowTime = time();
  33.             //Se determina la diferencia de tiempo en segundos entre la última ejecución
  34.             //y la fecha y hora actual
  35.             $difTime = $nowTime - $dbTime;
  36.             //Se determina si se cumplió el intervalo establecido en la tabla (en segundos)
  37.             if ($difTime >= $dbInterval)
  38.             {
  39.                 //Se determina la acción a realizar de acuerdo al Nombre de la tarea
  40.                 switch ($dbNombre)
  41.                 {
  42.                     case 'MiTarea':        
  43.                         if (ActualizarTime($dbID, $mysqli) == true)
  44.                         {
  45.                             //Aquí va el código de la acción que se realizará al alcanzar
  46.                             //el tiempo establecido
  47.                             echo "Se ejecutó tarea {$dbID} con nombre {$dbNombre}<br>";
  48.                             //La anterior línea se puede borrar, es sólo para verificación durante el debug
  49.                         }
  50.                     break;
  51.                     //Agregar tantos case como sean necesarios
  52.                 }
  53.             }
  54.             else
  55.             {
  56.                 echo "Tarea {$dbID} tiempo {$difTime} de {$dbInterval} segundos.<br>";
  57.                 //La anterior línea se puede borrar, es sólo para verificación durante el debug
  58.             }
  59.         }
  60.     }
  61. ?>

Se deben colocar tantos Case como registros hayan en la tabla Cron y en cada case colocar el código de lo que se quiera realizar p ej verificar si hay registros a eliminar cada cierto tiempo o enviar un correo electrónico al administrador con alguna estadística, etc.

Por último agregar al principio del código de cada uno de los archivos php del website lo siguiente:

Código PHP:
Ver original
  1. <?php
  2.     include ("cron.php");
  3. ?>

Así, cada vez que se abra una página se ejecutará el código de cron.php y si no colocan ningún echo (que es lo ideal) será completamente transparente para el usuario. Espero haya sido de ayuda.

PD: Se podría hacer una modificación, para en vez de agregar tantos Case se pueda llamar a una función desde un string. Para esto tendrían que agregar un nuevo campo a la tabla Cron de la BD que se llame Funcion que sea del tipo varchar y en ese campo escribir el nombre exacto de la función p ej MiFuncion. Luego colocar este código en cron.php en vez del anterior:

Código PHP:
Ver original
  1. <?php
  2.     //Aquí la conexión a la BD, reemplazar por sus respectivos datos de conexión
  3.     define("DB_SERVER", "localhost");
  4.     define("DB_USER", "root");
  5.     define("DB_PASS", "root");
  6.     define("DB_NAME", "Prueba");
  7.     $mysqli = new mysqli(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
  8.    
  9.     //Aquí se colocarían las funciones que se quieran realizar
  10.     function MiFuncion()
  11.     {
  12.         //Aquí va el código a ejecutar p ej enviar un correo
  13.         echo "Se envió el correo<br>"; //Esta línea se puede borrar
  14.     }
  15.  
  16.     //Función para actualizar el TimeStamp de la última ejecución
  17.     function ActualizarTime($dbID, $mySQL)
  18.     {
  19.         $nowTime = Time();
  20.         $sql= "UPDATE Cron SET  Last='{$nowTime}' WHERE ID='{$dbID}'";
  21.         $result = $mySQL->query($sql);
  22.         if ($result == false) echo "Se produjo un error al actualizar la tarea <br>";
  23.         return $result;
  24.     }
  25.  
  26.     //Se seleccionan todas las tareas que estén registradas en la tabla
  27.     $sql = "SELECT * FROM Cron";
  28.     $result = $mysqli->query($sql) or die(mysqli_error());
  29.     $iNumReg= mysqli_num_rows($result);
  30.     if ($iNumReg > 0)
  31.     {
  32.         //Se recorre una a una las tareas
  33.         while ($rowEmp = $result->fetch_assoc())
  34.         {
  35.             $dbTime = $rowEmp['Last'];
  36.             $dbInterval = $rowEmp['Intervalo'];
  37.             $dbNombre = $rowEmp['Nombre'];
  38.             $dbFuncion = $rowEmp['Funcion'];
  39.             $dbID = $rowEmp['ID'];
  40.             $nowTime = time();
  41.             //Se determina la diferencia de tiempo en segundos entre la última ejecución
  42.             //y la fecha y hora actual
  43.             $difTime = $nowTime - $dbTime;
  44.             //Se determina si se cumplió el intervalo establecido en la tabla (en segundos)
  45.             if ($difTime >= $dbInterval)
  46.             {
  47.                 if (ActualizarTime($dbID, $mysqli) == true)
  48.                 {
  49.                     //Se llama a la función definida en la tabla Cron
  50.                     call_user_func($dbFuncion);
  51.                     echo "Se ejecutó tarea {$dbID} con nombre {$dbNombre}<br>";
  52.                     //La anterior línea se puede borrar, es sólo para verificación durante el debug
  53.                 }
  54.             }
  55.             else
  56.             {
  57.                 echo "Tarea {$dbID} tiempo {$difTime} de {$dbInterval} segundos.<br>";
  58.                 //La anterior línea se puede borrar, es sólo para verificación durante el debug
  59.             }
  60.         }
  61.     }
  62. ?>

Cualquiera de las dos formas funcionan bien. Cualquier comentario es bienvenido o si hay alguna otra manera de hacerlo se aceptan aportes.
__________________
Si te gustó la respuesta dale +1

HERNÁN G. SIABATO M.
[email protected]