Error call-time – Pasando por Referencia en PHP


Recién esta mañana me di a la tarea de revisar el código de un amigo que hace más de un mes me había pedido ayuda en varios errores el error.log de apache le estaba mostrando. Mayormente todos eran problemas de sintaxis y falta de validación en algunas valores de retorno. Luego de explicarle y espero él haber entendido me llamó la atención uno en particular.

Call-time pass-by-reference has been deprecated in line …

Como era un Warning (PHP 5.3.x) la aplicación funcionaba perfectamente. ¿Que cosa son las variables por referencia? No son más que variables que se le pasan como parámetro a una función y durante el transcurso de la misma su valor va a variar y por supuesto puede ser accesible nuevamente una vez terminado el método, sin la necesidad de retornarla. Para que lo entiendan mejor les voy a poner un ejemplo con exactamente la misma sintaxis que provoca el Warning.

  <?php
    function foo($var)
    {
        $var++;
        return true;
    }

    $a = 5;
    foo(&$a);
    echo $a; // El valor de $a es 6
  ?>

Como se dan cuenta la función foo() recibe una variable como parámetro, la cual incrementa en 1 y devuelve cualquier valor de retorno el cual en este caso es booleano. La variable que tenía valor 5 antes de ser ejecutada la función se incrementa en 1 y luego de ejecutado el método su valor es 6. ¿Simple verdad? Bueno aunque no está mal en concepto, en PHP 5.3.x nos avisa que la funcionalidad de pasarle valores referenciados cuando llamamos la función será removida, quiere decir que en versiones de PHP >5.4.x ya ocurrirá un FATAL ERROR, si de esos mismos que tumban nuestro sitio web.

¿Cómo solucionar el problema? pues realmente es bastante sencillo y no hace falta hacernos un lío en la cabeza. Les mostraré el mismo ejemplo con una solución válida manteniendo la misma funcionalidad.

  <?php
    function foo(&$var)
    {
        $var++;
        return true;
    }

    $a = 5;
    foo($a);
    echo $a; // El valor de $a es 6
  ?>

¿Se dieron cuenta que acaba de cambiar? El signo de referencia (&) pasa ahora a ser parte de los parámetros de la función y desaparece de la variable en la acción de ejecutar el método. EL resultado es el mismo. Le dice al intérprete PHP que el valor (cualquiera que sea) que se pase por parámetro será una variable referenciada, es decir que le cambiará el valor de la mismo y la variable no morirá cuando la función termine. A los que han programado en C++ alguna vez esto les debe recordar a los punteros que tantas malas noches nos hicieron pasar.

Esta funcionalidad es sumamente útil, supongamos una función que importe objetos a una lista, solo que la función debe devolver valores booleanos (verdadero en el caso que se importen todos los objetos, falso en caso contrario) y aún así la lista debe tener los objetos obtenidos del XML sin errores. La verdad es que existe por supuesto como en la vida más de una manera de resolver la situación, pero la más simple es esta que discutimos en el día de hoy. Miren el ejemplo traducido a PHP.

<?php
  function inportar(&$lista)
  {
      foreach ($lista as $l) {
    $objeto = xml->item;
    if (!$objeto)
      return false;
    $l = $objeto;
      }
      
      return true;
  }

  $listado = array($producto1, $producto2, $producto3);
  if (importar($listado)) {
    echo 'Todos los productos tienen su objeto';
  } else {
    echo 'Ocurrio algun error y no todos los productos tienen sus objetos';
  }
?>

El ejemplo no es del todo funcional pero si académicamente válido. Traspólenlo a su idea y verán como da resultado. La moraleja del cuento es siempre informarse de los cambios que se realizan con cada versión de PHP o el lenguaje en el que desarrollen. Desarrollar siempre teniendo en cuenta estos detalles y de la mejor manera posible.

Latest posts by Leroy Ley (see all)