Guía 65 – Cálculos «en vuelo» con programación en el Server

En algunos casos me habéis preguntado cómo calcular «en vuelo» diferencias entre fechas y otros cálculos, que ya estaban resueltos en la programación PHP del Server.

Últimamente se me ha consultado cómo hacer el cálculo de días entre 2 fechas, que está resuelto en la Guía 21, pero online (en la misma pantalla donde se está introduciendo las fechas.

Aunque os he contestado que utilizando la Guía 21 y la Guía 27, se podía hacer, a las personas que se lo he comentado, les costaba mucho hacerlo, por ello he decidido hacer este ejercicio, para ver si así os es más sencillo utilizar la solución.

Objetivo

La forma habitual de programación es que todo lo que tenga que realizarse en el navegador se haga con JavaScript, pero algunas veces interesa utilizar los cálculos que ya están implementados en el server.

Este ejemplo muestra cómo es fácil de utilizar los cálculos realizados en el Server en formularios Online. Se hace utilizando Ajax, para comunicar procesos del Front-end (navegador) con procesos del Back-end (servidor).

DEMOhttps://fhumanes.com/date_diference2/ 
Usuario: admin/admin

Solución técnica

Se ha utilizado el JavaScript API de PHPRunner para poner «Disabled» los campos que van a ser calculados, para que el usuario no pueda modificarlos directamente.

A través de este API se controla cuándo se cambian los campos de fecha y cuando son cambiados se ejecuta una función de JavaScript que a través de Ajax se pasan los datos de las fechas al Server y en PHP se calcula los diferentes días. En ese proceso de cálculo se accede a la base de datos para recoger los días que son festivos.

Las parte más significativa del código son:

  • La parte de JavaScript que se codifica en el evento » JavaScript onLoad event»:
var ctrl_date_init = Runner.getControl(pageid, 'date_init');
var ctrl_date_end = Runner.getControl(pageid, 'date_end');

var ctrl_natural_days = Runner.getControl(pageid, 'natural_days');
var ctrl_business_days = Runner.getControl(pageid, 'business_days');
var ctrl_holidays = Runner.getControl(pageid, 'holidays');
var ctrl_weekdays = Runner.getControl(pageid, 'weekdays');

// Set Disabled field Calculated
ctrl_natural_days.setDisabled();
ctrl_business_days.setDisabled();
ctrl_holidays.setDisabled();
ctrl_weekdays.setDisabled();


this.on('beforeSave', function(formObj, fieldControlsArr, pageObj){
  var init = ctrl_date_init.getValue();
  var end = ctrl_date_end.getValue();
  if ( init > end ) {
      alert("It is necessary that the initial date is less than or equal to the end date");
      Runner.delDisabledClass(pageObj.saveButton ); // Activate again, button SAVE
      return false;
  } else {
    // Set Enabled field Calculated
    ctrl_natural_days.setEnabled();
    ctrl_business_days.setEnabled();
    ctrl_holidays.setEnabled();
    ctrl_weekdays.setEnabled();

      return true;
  }
});

function calcule_days(ctrl_1, ctrl_2) {
  pdate1 = ctrl_1.getStringValue(); // We collect the value of the field from the form
  pdate2 = ctrl_2.getStringValue(); // We collect the value of the field from the form

  if ( pdate2 >= pdate1 ) { // The dates are correct and the end is equal to or greater than the initial
        // Setting function and receives response with AJAX
        $.ajax({
            type: 'POST',  //  SEND with POST method
            url: './ajax_calcule_days.php',  // Destination file (the PHP that manages the data)
            data: { date1: pdate1,date2: pdate2 }, // Data that are sent
            async: false,
            success: function(msg) {  // Function that runs if everything has gone well
                console.log("respuesta: "+msg);
                msgArr = msg.split(";");
                if ( msgArr[0] == '1' ) { // Is OK
              
                  $('input[id^="value_natural_days_"]').val(msgArr[2]);
                  $('input[id^="value_business_days_"]').val(msgArr[3]);
                  $('input[id^="value_holidays_"]').val(msgArr[4]);
                  $('input[id^="value_weekdays_"]').val(msgArr[5]);
                  /* It does not work
                   ctrl_natural_days.setValue = msgArr[2];
                   ctrl_business_days.setValue = msgArr[3];
                   ctrl_holidays.setValue = msgArr[4];
                   ctrl_weekdays.setValue = msgArr[5];
                 */
                } else { // Is KO
                    alert(msgArr[2]);
                }
            },
            error: function (jqXHR, textStatus, errorThrown){ // Function that runs if something has gone wrong
                // We show the message with the error that has been produced
                alert("The following error occured: "+ textStatus +" "+ errorThrown);
            }
    });
  }
}

// --------------------------------------------------------------------------
// Change value of  Days
ctrl_date_init.on('change', function(e){
  calcule_days(ctrl_date_init, ctrl_date_end);
 });

ctrl_date_end.on('change', function(e){
  calcule_days(ctrl_date_init, ctrl_date_end);
 });
  • La parte de cálculo del Server «ajax_calcule_days.php»:
<?php

require_once("include/dbcommon.php"); // DataBase PHPRunner

if (!isset($_POST['date1'])) { //  Control of the call and verification of the existence of the parameter
  echo("0;;Please provide a Date Initial");
  die();
}
if (!isset($_POST['date2'])) { //  Control of the call and verification of the existence of the parameter
  echo("0;;Please provide a Date End");
  die();
}
$Dinit = $_POST['date1'];
$Dend = $_POST['date2'];

/*
  echo "1;$maxValor;Ok, Good answer";
} else {
  echo "2;$maxValor;Error, the Valor is not correct";
}
*/

// Control of the dates
if ( $Dinit > $Dend ) {
  echo("0;;Please provide a Date End > Date Init");
  die();
}		

// Retrieve the holidays of the period
$holidays = array();
$rs = DB::Query("SELECT * FROM date_holidays where holiday between '$Dinit' and '$Dend'");
while( $data = $rs->fetchAssoc() )
{
  $holidays[] = $data['holiday'];
}

// Control of afforded dates
/*
$rs = DB::Query(
"SELECT * FROM date_permissions
where `date_user_id` = $id_user and  (( date_init >= '$Dinit' and date_end <= '$Dend')
or (date_init < '$Dinit' and date_end >= '$Dinit' )
or (date_init > '$Dinit' and date_init <= '$Dend'))"
);
while( $data = $rs->fetchAssoc() )
{
  $message = "Some days of this range are already requested";
  return false;
}
*/
//  Count the days of between dates
$count_N = 0;
$count_B = 0;
$count_H = 0;
$count_W = 0;

$start = strtotime($Dinit);
$end = strtotime($Dend);
while(date('Y-m-d', $start) <= date('Y-m-d', $end)){
  $count_N += 1;
  $string_init = date('Y-m-d', $start);
  if (in_array($string_init, $holidays)) {
    $count_H += 1; // Is holiday
  } else {	
    $d_w = date('N', $start); 
    $count_B += $d_w < 6 ? 1 : 0; //  Is Business 
    $count_W += $d_w < 6 ? 0 : 1; // Is weekend
  }
  $start = strtotime("+1 day", $start);
}

echo("1;;$count_N;$count_B;$count_H;$count_W");

Con este mismo método se puede hacer casi todo lo que necesitemos.

Para cualquier duda o ayuda, contactar conmigo a través de mi email [email protected]

Os facilito el proyecto y sus datos, para que podáis instalar en vuestros PC y podáis hacer todas la modificaciones que necesitéis.

Adjuntos

Archivo Tamaño de archivo Descargas
zip PHPRunner 10.7 y backup de datos 57 KB 127

Blog personal para facilitar soporte gratuito a usuarios de React y PHPRunner