Lazy Loading en PHP

6
73

p>Lazy Loading es un patrón de diseño que se utiliza mucho programación

En que consiste?

Su implementación en PHP consiste en no incluir las clases a utilizar en nuestro proyecto.

Como las reconoce?

De esto se trata Lazy Loading, cuando necesitas de una clase es recien cuando la llama. Este proceso lo realizamos con la función mágica que trae PHP5 __autoload($nombreClase), en un POST anterior escribí un completo ejemplo para su uso.

Que de bueno tiene este patrón?

Al no incluir todas las clases el inicio de cada pagina php, estamos ahorrando un proceso, ganando un poco de performance y obteniendo un código mas limpio en nuestra aplicación.

Ejemplo de Código

primero cambiaremos nuestras Clases con el mismo nombre del archivo(como en Java).
Si tenemos una Clase Clientes(), nuestro archivo podría llamarse Clientes.php, Clientes.class.php, ClientesClass.php, lo importante es que el nombre de la clase aparezca completo en el archivo.

function __autoload($class_name)
{
	//direfentes rutas separas por ","
    $include_path = '/lib,/include,/class';
    $include_path_tokens = explode(',', $include_path);
    foreach($include_path_tokens as $prefix)
    {
      $path[0] = $prefix . '/' . $class_name . '.php';
      $path[1]= $prefix . '/' . $class_name . '.class.php';
      foreach($path as $thisPath)
      {
        if(file_exists($thisPath))
        {
          require_once $thisPath;
          return;
        }
      }
    }
}

Con esto nos olvidaremos de muchos includes que bajan la performance en nuestras aplicaciones.

Recursos

6 COMMENTS

  1. Esta interesante tu codigo, pero solo funcionaria para archivo de clases que se encuentran en un solo nivel de directorios.
    Que sucedería si estaría almacenado una carpeta dentro de otra y asi…
    Por ejemplo:
    ventas/productos/*.php
    ventas/cliente/*.php
    rrhh/usuarios/*.php
    rrhh/personal/otro/*.php
    Para aquella solución creo que deberías plantear el formato largo de nombre de las clases (paquete1_subpaq2_nombreClase ) o sino el uso namespaces que ya se incluye en PHP 5.3…
    tambien el autoload de SPL sería bueno revisar

    • Tienes mucha razón, como hay un estandar de código por Zend para las clases que dependen de otro, los nombre de clases y el nombre de archivos quedarían algo así:
      – class/ventas/productos/*.php (Ventas_Productos_*.php)
      – class/rrhh/usuarios/*.php (Rrhh_Usuarios_*.php)
      el agregado a la función seria reemplazar los “_” por separadores de directorio, de esta manera.

      $class_name = str_replace('_','/',$class_name);
      

      y la función seria así:

      function __autoload($class_name)
      {
          //para clases con subniveles
          $class_name = str_replace('_','/',$class_name);
          //diferentes rutas separas por ","
          $include_path = '/lib,/include,/class';
          $include_path_tokens = explode(',', $include_path);
          foreach($include_path_tokens as $prefix)
          {
              $path[0] = $prefix . '/' . $class_name . '.php';
              $path[1]= $prefix . '/' . $class_name . '.class.php';
              foreach($path as $thisPath)
              {
                  if(file_exists($thisPath))
                  {
                      require_once $thisPath;
                      return;
                  }
              }
          }
      }
      

      Sobre los namespaces que trae PHP 5.3 seria una buena idea, estare investigando mas, y también sobre las funciones SPL de PHP. Muy constructivo tu comentario, Muchas gracias!

    • Los he provado en todos los navegadores(firefox,ie,safari,chrome) y no he tenido ningun problema. Pero voy a testear varias vece hasta encontrar el bug porque me ha comentado este suceso otra persona tambien. Gracias por la observacion
      Saludos.

  2. Hola amigo
    Muy bueno su articulo acabo de cambiar todo mis paginas con a la function __autoload($class_name), realmente se ve mas limpio el código.
    Tuve que un hacer unos pequeño cambio no se si eso es lo mas eficiente pero no se me ocurrió otra idea por lo menos funciona es referente a las rutas. Que se pierde de rutas cuando entre a un directorio.
    Tengo algo asi MVC:
    /clase_php
    /controlador
    /html2pdf
    /adodb
    /vistas
    /imagen
    /ccs
    /js
    Index.php
    Lo que se me ocurrió después de varias horas sin logar nada fue usar ($_SERVER[‘PHP_SELF’] y contar si ahí mas de dos / es que nos estoy en el raiz de mi sitio y con eso funciona perfectamente
    //direfentes rutas separas por “,”
    if(substr_count($_SERVER[‘PHP_SELF’], ‘/’)>2) {
    // esto si no estoy en el raiz
    $include_path = ‘../clases_php,../html2pdf_v4.01’;
    } else {
    // estoy en el raiz
    $include_path = ‘clases_php,html2pdf_v4.01’;
    }
    Con eso me funciona eso es por que cuando estoy en un directorio debo usar ../ /contorlador/config.php de lo contrario /contorlador/config.php estoy en index.php que es el raíz.
    Saludos desde Venezuela
    Muchas gracias

  3. Es mejor utilizar spl_autoload_register(). Esta funcion permite registrar mas de una funcion __autoload para ser invocada. Ademas, me parece que lo ideal seria encapsular el patron en una clase Loader, que se encargue de registrar en un hash todas las posibles rutas hacia los archivos que contienen nuestras clases y al momento de la instanciacion, se recorran esas rutas para encontrar la clase correspondiente.
    Claro, tambien habria que estudiar el impacto sobre el desempeno, y como optimizarlo, pero me parece que por ahi van los tiros.

Comments are closed.