Enviar datos a una db en cierto día y hora (ojalá sin cronjobs)

publicado por: Anonymous

Necesito enviar a mi base de datos un “1” en cierto día y hora, además enviar un “0” en otro día y hora.

Por ejemplo, Que cuando sea Jueves y sean las 13:30 horas, envíe un “1”, y cuando sea Sábado y sean las 09:00 horas, envíe un “0”.

Esos días,horas y ese “1” / “0” están en la misma tabla, como muestra la imagen:

introducir la descripción de la imagen aquí

Entonces interpretando esas columnas, cuando se cumpla el horario de inicio (Viernes,00:00) se actualiza la columna habilitada con un “1”, cuando se cumpla el horario de termino (Sabado,12:00), se actualiza la columna “habilitada” con un “0”.

Esto es lo que tengo hasta ahora y funciona pero solo cuando recargo el archivo.php en el minuto de coincidencia:

<?php
  date_default_timezone_set("America/Santiago");     
  $hoy = getdate();       

  $dia = $hoy["wday"];
  $dias = ["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"];
  $dia = $dias[$dia];                   //nombre del día actual
  $hora = $hoy["hours"];               //la hora
  $minuto = $hoy["minutes"];               //minutos

  if($hora < 10) $ceroh = "0";         //cero extra por estética de la hora
  else $ceroh = "";                             
  if($minuto < 10) $cerom = "0";         //cero extra por estética de los minutos
  else $cerom = "";

  $diahora = $dia.",".$ceroh.$hora.":".$cerom.$minuto;  //dia y hora actual (dia,hh:mm)

  include 'connect.php';

  foreach($db->query("SELECT inicio,termino FROM `horario_envio`") as $fila){
    $inicio = htmlentities($fila['inicio']);            //hora inicio en la db
    $termino= htmlentities($fila['termino']);           //hora termino en la db
  }

  if($diahora == $inicio){        //si día y hora actual son iguales al campo inicio
    $si = "1";
    $update = $db->prepare("UPDATE `horario_envio` SET habilitada = :si");
        $update->bindValue(':si',$si,PDO::PARAM_STR);
        $update->execute();    //pongo el "1"
  }
  if($diahora == $termino){     //si dia y hora actual son iguales al campo termino
    $no = "0";
    $update = $db->prepare("UPDATE `horario_envio` SET thabilitada = :no");
        $update->bindValue(':no',$no,PDO::PARAM_STR);
        $update->execute();    //pongo el "0"
  }
?>

He investigado en el stackoverflow en inglés y, si he entendido bien, la mayoría sugiere el uso de cron-jobs para tareas similares, también he visto vídeos de su uso y lo que hacen es irse al control panel de su hosting y ahí programan la ejecución de ciertas tareas.

Pero yo no quiero eso, necesito que mi envío de datos se lleve a cabo solo según la hora de inicio y término que mostré más arriba, que están en mi db.

En este post, el usuario @cmc dió tres soluciones, la primera es con cron, la segunda es con un ciclo infinito, lo cual recomendó como última instancia, y la tercera opción es user driven.

Esa tercera opción me llamó más la atención pues no estoy trabajando con grandes cantidades de datos. El problema es que no sé cómo aplicar lo que sugiere el autor de esa respuesta o tal vez simplemente no me sirva, es esto:

// you can simply include a the job this in your page footer, when there is no more output.

<?php

//fetch $last_exec_timestamp from database

if ($last_exec_timestamp < time() + 86400) {
  //set last_exec_timestamp to now in database

  //do something
}

No entiendo cómo podría aplicar eso a mi caso, lo que dice es algo como:

  • incluye esto en el footer de tu página cuando dejen de haber salidas

  • toma la última ejecución de tiempo de la db

  • si ese valor que acabas de tomar, es menor al tiempo actual + 24 horas:

    • setea la última ejecución de tiempo a la hora actual de la db

    • has algo.

En fín, no sé cómo aplicar eso.

Estoy intentando hacer esto en php, pero si no fuera posible y existiera otra vía para hacer lo que describí al principio, igual podría aplicarla, incluso si la única vía fuese cron-jobs.

Gracias por su atención.

EDIT

¿Por qué no me sirve cron?

Los valores “inicio” y “termino” de la tabla que puse arriba controlarán el rango de horas, que son y “deben ser” modificables desde el frontend del sitio, entonces nunca habrá un rango de horas fijo, va a variar dependiendo de lo que elija el administrador desde la plataforma y se inserte en la base de datos.

Ejemplificando un poco: Quiero ofrecer un programa que permita a mi cliente establecer un rango de horas entre las cuales sus empleados podrán enviar ciertos datos a una base de datos. Y no quiero que mi cliente tenga que usar cron cuando quiera cambiar ese horario, sino que lo haga automáticamente desde el frontend.

solución

Debido a las restricciones que esta pregunta presentaba (no usar cron-jobs, no usar mysql event_scheduler por estar deshabilitado en hosting gratuitos) y gracias a las respuestas que me han venido dando los usuarios, hemos concluido que la manera más adecuada de hacer el trabajo que requiero (permitir acciones dentro de un rango temporal), es desarrollar un algoritmo que evalúe si actualmente se está dentro del rango temporal para ejecutar el envío de datos.

Inicialmente expuse la tabla con la cual estaba trabajando, donde quería poner un “1” o un “0” a cierta hora en el campo de la columna “habilitada”:

introducir la descripción de la imagen aquí

Pero ni siquiera necesitaba ese campo, pues para desarrollar un algoritmo que me permita evaluar si actualmente se está dentro del rango de horas predeterminado por los campos “inicio” y “termino”, solo necesito esos dos campos.

Entonces lo que hice fue, primeramente traer esos dos campos a mi archivo php, también se obtuvo el día y la hora actual, entonces con esos tres datos (dia/hora de inicio, actual y de termino) procedo a darle cierta prioridad a todos los días de la semana según el día de inicio, eso me permitirá darle valores numéricos a los días de inicio, actual y termino, considerando también la hora de inicio, actual y termino para llevar a cabo la condición que me dirá si efectivamente se está dentro del rango o no.

Dejo el código por si a alguien le interesa:

<?php 
date_default_timezone_set("America/Santiago");     
$hoy = getdate();       

$dia = $hoy["wday"];
$dias = ["Domingo","Lunes","Martes","Miercoles","Jueves","Viernes","Sabado"];
$dia = $dias[$dia];                  //nombre del día actual

$hora = $hoy["hours"];              //la hora
$minuto = $hoy["minutes"];      //los minutos

if($hora < 10) $ceroh = "0";
else $ceroh = "";

if($minuto < 10) $cerom = "0";
else $cerom = "";

$diahora = $dia.",".$ceroh.$hora.$cerom.$minuto;  //day,time actual

include 'connect.php';

foreach($db->query("SELECT inicio,termino FROM `horario_envio`") as $fila){
  $inicio = htmlentities($fila['inicio']);    //dia,hora de inicio
  $termino= htmlentities($fila['termino']);   //dia,hora de termino
}

$diai = strtok($inicio, ",");                      //obtengo el dia de inicio
$diat = strtok($termino, ",");                 //obtengo el dia de termino

if($diai == "Lunes"){
    $prioridad = array("Lunes","Martes","Miercoles","Jueves","Viernes","Sabado","Domingo");
    $pda = array_search($dia, $prioridad);  //prioridad dia actual
    $pdt = array_search($diat, $prioridad); //prioridad dia termino
}
if($diai == "Martes"){
    $prioridad = array("Martes","Miercoles","Jueves","Viernes","Sabado","Domingo","Lunes");
    $pda = array_search($dia, $prioridad);  //prioridad dia actual
    $pdt = array_search($diat, $prioridad); //prioridad dia termino
}
if($diai == "Miercoles"){
    $prioridad = array("Miercoles","Jueves","Viernes","Sabado","Domingo","Lunes","Martes");
    $pda = array_search($dia, $prioridad);  //prioridad dia actual
    $pdt = array_search($diat, $prioridad); //prioridad dia termino
}
if($diai == "Jueves"){
    $prioridad = array("Jueves","Viernes","Sabado","Domingo","Lunes","Martes","Miercoles");
    $pda = array_search($dia, $prioridad);  //prioridad dia actual
    $pdt = array_search($diat, $prioridad); //prioridad dia termino
}
if($diai == "Viernes"){
    $prioridad = array("Viernes","Sabado","Domingo","Lunes","Martes","Miercoles","Jueves");
    $pda = array_search($dia, $prioridad);  //prioridad dia actual
    $pdt = array_search($diat, $prioridad); //prioridad dia termino
}
if($diai == "Sabado"){
    $prioridad = array("Sabado","Domingo","Lunes","Martes","Miercoles","Jueves","Viernes");
    $pda = array_search($dia, $prioridad);  //prioridad dia actual
    $pdt = array_search($diat, $prioridad); //prioridad dia termino
}
if($diai == "Domingo"){
    $prioridad = array("Domingo","Lunes","Martes","Miercoles","Jueves","Viernes","Sabado");
    $pda = array_search($dia, $prioridad);  //prioridad dia actual
    $pdt = array_search($diat, $prioridad); //prioridad dia termino
}

$pdi = 0;                                    //prioridad dia inicio

$hini = substr($inicio, -5);
$hter = substr($termino, -5);
$hini = (int)str_replace(":", "", $hini);   //obtengo la hora de inicio en números
$hter = (int)str_replace(":", "", $hter);   //obtengo la hora de termino en números
$hact = (int)substr($diahora, -4);       //obtengo la hora actual en números

if(($pda>$pdi or ($pda==$pdi and $hact>=$hini)) and ($pda<$pdt or ($pda==$pdt and $hact<$hter))){
    $sepuede = true;                        //evalúo si el día y hora actual están dentro
}else $sepuede = false;                 // del rango de horas preestablecido

if($sepuede){                         //si se está dentro del rango de horas:
    $rut = $_POST["rut"];             //hago el insert con los datos enviados
    $pedidos = $_POST["pedidos"];
    $update = $db->prepare("INSERT INTO `t...
    $update->execute();
}
else echo "no";

?>

Entonces en el frontend llamo a este archivo con la función $.ajax de JQuery, pasándole los datos que aquí estoy recibiendo mediante POST, si en el success recibo un “no”, daré una alerta para que el usuario sepa que sus turnos no se enviaron por estar fuera del rango de hora.

El código funciona perfectamente, pero cualquier sugerencia para optimizarlo es bienvenida.

Gracias a todos por sus aportes.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *