Feed Tiendas Virtuales
LEE TAMBIÉN:Zen Cart
Currently Browsing: PHP

PHP 5.3 – Publicada

php 5 3 PHP 5.3   PublicadaLos chicos de PHP han publicado hoy la primera versión final de PHP 5.3, que hemos ido descubriendo a lo largo de estos días y que continuaremos destripando poco a poco.

Esta nueva versión de PHP se puede descargar desde la web oficial: descargar PHP 5.3

A disfrutarla!!!

PHP 5.3 – Funciones lambda y Closures

Logo GmailEn programania nos ofrecen un recopilatorio de artículos en los que se opina sobre las ventajas y desventajas que nos proporcionaran las funciones lambda y las closures de PHP 5.3.

La opinión de Luis Artola es un fiel reflejo de la mía propia, pues después de haberme leído todos estos artículos no he conseguido ver claras ventajas de esta "nueva forma de programar".

Otro artículo que he encontrado interesante sobre funciones lambda (funciones anónimas) y closures: Funciones Lambda y Closures, lo que es bullshit y lo que realmente es de provecho

PHP 5.3 – Declarar y usar Namespaces

¿Qué es un namespace?

InfoUn namespace  o espacio de nombres es un medio para organizar/encapsular clases, funciones, constantes… dentro de un entorno, agrupándolas de un modo más lógico y jerárquico, de la misma forma que los directorios agrupan a los archivos dentro de un sistema de ficheros.

Ésta es una característica bastante esperada por los desarrolladores de PHP y llega con el objetivo de ayudar a que no necesitemos prefijar el nombre de nuestras clases con el nombre del paquete al que pertenecen y, por tanto, que podamos tener nombres más cortos. También nos ofrece la posibilidad de declarar varias clases con el mismo nombre y/o que un grupo de desarrolladores pueda trabajar en varios componentes de un mismo proyecto sin que se produzcan colisiones durante la integración.

Los namespaces están especialmente indicados cuando trabajamos en proyectos de gran envergadura, como por ejemplo, un Framework PHP. En algunos Frameworks podemos llegar a encontrar  nombres realmente complejos, por no decir imposibles (Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive).
 

Declarar un namespace en PHP

Al buscar información sobre cómo declarar un namespace en PHP es muy fácil que encontremos varias formas de hacerlo. Esto se debe a que, en un principio, los creadores de PHP optaron por el formato: mi::namespace, pero tanto en las versiones candidatas (RC) como en la versión final de PHP 5.3, el separador que se ha elegido es la barra invertida: mi\namespace. Con este cambio se consiguen evitar problemas como el que se podía producir entre las funciones declaradas dentro de un nombre de espacio y los métodos estáticos de una clase. Sin este cambio de separador, ambas llamadas serían exactamente iguales (mi::namespace) y esto haría que los namespaces no tuviesen mucho sentido.

IMPORTANTE: Los namespaces deben declararse en la parte más alta de nuestro código, siendo las sentencias declare las únicas permitidas. Por ejemplo, la declaración de la codificación del archivo.

declare(encoding='ISO-8859-1');

Ejemplos de declaración de un namespace

Declaración básica

namespace MiEspacio;
 
const CONSTANTE = 1;
class mi_clase { /* ... */ }
function mi_funcion() { echo "Mi Funcion";  }

Declaración de subniveles

namespace MiEspacio\MiSubnivel1\MiSubnivel2;
 
const CONSTANTE = 1;
class mi_clase { /* ... */ }
function mi_funcion() { echo "Mi Funcion"; }

Declaraciones múltiples en un sólo archivo

Cuando se declaran múltiples nombres de espacio en un mismo archivo se recomienda utilizar los corchetes para delimitar el código de cada namespace y se exige que todo el código del archivo vaya dentro de los mencionados corchetes, excepto las sentencias declare que pueden ir fuera.

Si no cumplimos esta regla obtendremos el siguiente mensaje de error:

No code may exist outside of namespace {}

namespace MiEspacio 
{
  const CONSTANTE = 1;
  class mi_clase { /* ... */ }
  function mi_funcion() { echo "Mi Espacio - Mi Funcion"; }
}
 
namespace MiOtroEspacio
{
  const CONSTANTE = 1;
  class mi_clase { /* ... */ }
  function mi_funcion() { echo "Mi Otro Espacio - Mi Funcion"; }  
}

Uso de declare y el espacio de nombres global

declare(encoding='UTF-8');
 
namespace MiEspacio 
{
  const CONSTANTE = 1;
  class mi_clase 
  {
    public static function hola ()
    {
      echo "Hola";
    } 
  }
  function mi_funcion() { echo "Mi Funcion"; } 
}
 
// Espacio Global
namespace 
{
  session_start();
  MiEspacio\mi_funcion();
  MiEspacio\mi_clase::hola();
  echo MiEspacio\CONSTANTE;
}

Usar un namespace en PHP

Para realizar la llamada a un namespace deberemos aplicar las misma reglas que aplicamos cuando accedemos a un recurso dentro de nuestro sistema de archivos.

Ruta relativa

/* Crea una instancia de MiEspacio\mi_clase */
$resultado = new mi_clase();
$resultado::hola();
 
mi_clase::hola();
mi_funcion();
 
/* Crea una instancia de MiEspacio\MiSubnivel1\MiSubnivel2\mi_clase */       
$resultado = new MiSubnivel1\MiSubnivel2\mi_clase();
$resultado::hola();
 
MiSubnivel1\MiSubnivel2\mi_clase::hola();
MiSubnivel1\MiSubnivel2\mi_funcion();
/* Espacio de nombres actual - Uso de la constante __NAMESPACE__ */
namespace MiEspacio;
 
echo __NAMESPACE__; // SALIDA: MiEspacio
/* Espacio de nombres actual - Uso de la constante __NAMESPACE__ */
namespace 
{
  // No devuelve nada si nos encontramos en el namespace global
  echo __NAMESPACE__; // SALIDA: 
}
/* Espacio de nombres actual - Construcciones dinamicas con __NAMESPACE__ */
namespace MiEspacio;
 
function get($clase)
{
  $nombre = __NAMESPACE__ . '\\' . $clase;
 
  // Devulve una nueva instancia de la clase MiEspacio\$clase
  return new $nombre;
}
/* Espacio de nombres actual - Uso de la palabra clave namespace */  
namespace MiEspacio;
 
// Realiza una llamada a la funcion MiEspacio\mi_funcion()
namespace\mi_funcion();
 
// Realiza una llamada a la funcion MiEspacio\MiSubnivel1\MiSubnivel2\mi_funcion()
namespace\MiSubnivel1\MiSubnivel2\mi_funcion();
 
// Realiza una llama al metodo estatico hola() de la clase MiEspacio\mi_clase
namespace\mi_clase::hola();
 
// Asigna el valor de la constante MiEspacio\Constante a la variable $mi_constante
$mi_constante = namespace\CONSTANTE;

Ruta absoluta

$resultado = new \MiEspacio\MiSubnivel1\MiSubnivel2\mi_clase();
\MiEspacio\MiSubnivel1\MiSubnivel2\mi_clase::hola();

Espacio Global

// Crea un nueva instancia de la clase global Exception
$exception = new \Exception('error');

Alias e importación

PHP ofrece la posibilidad de referirse a un namespace mediante un Alias y la posibilidad de importarlo utilizando el operador use.

Los alias se pueden crear sobre una clase o sobre un namespace, pero no existe la posiblidad de crear alias sobre una función o una constante:

Podemos crear alias:

  • Sobre una clase
  • Sobre un namespace

No podemos crear alias:

  • Sobre una función
  • Sobre una constante
namespace NuevoEspacio;
 
/* Mediante el alias conseguimos acortar el nombre del namespace */
use MiEspacio\MiSubnivel1\MiSubnivel2\mi_clase as MiClase;
 
/* Cuando no se indica un alias se toma el nombre del namespace o de la clase */
/* Equivale a: use MiEspacio\MiSubnivel1\MiSubnivel2 as MiSubnivel2; */
use MiEspacio\MiSubnivel1\MiSubnivel2;
 
/* Importamos una clase global */
use \ArrayObject;
 
/* Nueva instancia de NuevoEspacio\MiClase */
$mc = new namespace\MiClase;
 
/* Nueva instancia de MiEspacio\MiSubnivel1\MiSubnivel2\mi_clase */
$mc = new MiClase;
 
/* Llamamos a la funcion MiEspacio\MiSubnivel1\MiSubnivel2\mi_funcion() */
MiSubnivel2\mi_funcion();
 
/* Creamos una nueva instancia de ArrayObject */
/* Sin la importacion: use \ArrayObject; creariamos una instancia de NuevoEspacio\ArrayObject; */
$arrobj = new ArrayObejct (array(1));
 
/* Importacion multiple en una sola linea */
use MiEspacio\MiSubnivel1\MiSubnivel2\mi_clase as MiClase, MiEspacio\MiSubnivel1\MiSubnivel2;

Fuente: PHP.net

Instalar PHP 5.3 en Windows (Xampp)

PHP 5.3 en Windows (Xampp)La versión final de PHP 5.3 está a la vuelta de la esquina y, desde hace unos días, disponemos de su primera versión candidata: PHP 5.3 RC1.

Algunas de las novedades más importantes que encontraremos en esta versión de PHP son las siguientes:

 

  • Nombres de espacios (namespaces). Su principal ventaja, evitar colisiones entre nombres de clases.
  • Driver nativo de MySql para PHP (mysqlnd)
  • Phar. Encapsulación de archivos o bibliotecas en un sólo archivo, al estilo JAR de Java
  • Funciones Lambda y Closures
  • Soporte mejorado para Windows con versiones para VC6 (Visual Studio 6 Compiler) y VC9 (Visual Studio 2008 Compiler)

 Si deseamos probar esta primera versión candidata sobre Windows, podemos aprovechar las facilidades que nos ofrece el software Xampp para montar un servidor local y, realizando algunas modificaciones sobre la configuración, disponer de las ventajas de PHP 5.3.

Los pasos a seguir para instalar PHP 5.3 sobre Xampp serían los siguientes:

  • Descargar los binarios de PHP 5.3 para windows. Para descargar otra versión, consultaremos la página de descarga de para windows.
  • Descomprimir el archivo zip en C:\xampp\php\php5.3RC1
  • Crear una copia de C:\xampp\apache\conf\ en C:\xampp\apache\conf5.3RC1\
  • Crear el directorio C:\xampp\apache\logs5.3RC1\
  • Cambiar la configuración del servidor en el nuevo directorio creado (conf5.3RC1).
    Modificar el archivo: conf5.3RC1\httpd.conf:

    • Cambiar: Listen 80 por Listen 8080
    • Buscar y reemplazar todas las referencias de conf/ por conf5.3RC1/
    • Buscar y reemplazar todas las referencias de logs/ por logs5.3RC1/
    • Cambiar el PidFile: PidFile logs-php5.3.0alpha3/httpd.pid
    • Activar el módulo (eliminar el ; que aparece delante): LoadModule rewrite_module modules/mod_rewrite.so
  • En el archivo conf5.3\extra\httpd-ssl.conf:
    • Cambiar: Listen 443 por Listen 4343
  • En conf5.3\extra\httpd-xampp.conf:
    • Eliminar la línea: LoadModule php5_module "C:/xampp/apache/bin/php5apache2.dll"
    • Reemplazar lo anterior por:
      • #Configuracion de PHP 5.3RC1:
        #Precarga el archivo dll del interprete de PHP
        #para que Apache pueda encontrarlo, aunque no
        #se encuentre en la ruta
        LoadFile "C:/xampp/php/php5.3RC1/php5ts.dll" 
        
        #Carga el modulo sapi para Apache
        LoadModule php5_module
        "C:/xampp/php/php5.3RC1/php5apache2_2.dll" 
        
        #Indica el directorio en el que se encuentra el
        #archivo php.ini
        PHPIniDir "C:/xampp/php/php5.3RC1"
  • En conf5.3\extra\httpd-vhosts.conf: Configurar los puertos y los VirtualHosts (no obligatorio):

    NameVirtualHost *:8080

    <VirtualHost *:8080>
      DocumentRoot "C:/xampp/htdocs/" ServerName localhost
    </VirtualHost>
    <VirtualHost *:8080>
        DocumentRoot "C:/xampp/htdocs/sergioguerrero/" ServerName sergioguerrero.local
    </VirtualHost>

  • Configurar PHP 5.3: en C:\xampp\php\php5.3RC1 renombrar el archivo php.ini-production a php.ini
  • Configurar el archivo php.ini:
    • Activar las extensiones:
    • Cambiar display_errors = Off por display_errors = On
    • Cambiar: extension_dir = './' por extension_dir = 'C:\xampp\php\php5.3RC1\ext\' (con comillas simples)
  • Arrancar el servicio de apache desde la consola (cmd):
    • apache -f .\conf5.3RC1\httpd.conf
  • Si optamos por instalar el servicio:
    • Instalar: apache -k install -n Apache2.2-5.3RC1 -f .\conf5.3RC1\httpd.conf
    • Arrancar: net start Apache2.2-5.3.RC1

Si trabajamos con Windows Vista e intentamos instalar el servicio, puede que nos aparezca el siguiente mensaje de error:

(OS 5)Acceso denegado.  : Failed to open the WinNT service manager

Ejecutar CMD como Admin
En ese caso debemos recordar que, antes de ejecutar el comando de instalación, deberemos abrir la consola de símbolo de sistema con permisos de administración. Para ejecutar la consola como administrador, podemos realizar los siguientes pasos: 

  • Abrimos el menú de inicio de Windows y escribimos: CMD en la caja que aparece en la parte inferior del menú.
  • En la lista de resultados (Programas) nos debería aparece el programa (CMD) y presionando el botón derecho sobre este nos debería aparecer la opción: Ejecutar como administrador (ver imagen).
  • Ahora, ya podemos realizar los pasos de instalación y ejecución del servicio de Apache sin problemas.

Para ver si hemos realizado los cambios correctamente, pondremos la siguiente URL en nuestro navegador: http://localhost:8080/xampp/phpinfo.php.

Cortar texto sin cortar las palabras ni los tags HTML (truncate)

Cortar texto con HTML

En algunas ocasiones nos encontramos ante la necesidad de tener que mostrar por pantalla un extracto de un texto largo. Por ejemplo, cuando deseamos mostrar una parte de la última noticia de un blog o mostrar un extracto de la descripción de un producto en una tienda virtual.

La solución aplicada en la mayoría de ocasiones a la hora de cortar un texto (truncar) se reduce a mostrar los x primeros caracteres del mismo. Solución no muy adecuada ya que no se tiene en cuenta si estamos cortando alguna palabras, si estamos cortando alguna etiqueta HTML o si estamos produciendo HTML mal formado (ejemplo: etiquetas sin cerrar; <p>HTML mal formado ya que faltaría el tag </p>).

Obtener un extracto de un texto plano – Versión simple:

// Definimos el texto
$_noticia = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
 
// Obtenemos un extracto de los 150 primeros caracteres
$_extracto = substr($_noticia, 0, 150);
 
// Mostramos el extracto por pantalla
echo $_extracto;
 
// La salida:
// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis n

Obtener un extracto de un texto HTML – Versión simple:

// Definimos el texto
$_noticia_html = "<p><strong>Sergio Guerrero est&aacute; cortando este texto</strong></p>";
 
// Obtenemos un extracto de los 10 primeros caracteres
$_extracto_html = substr($_noticia_html, 0, 10);
 
// Mostramos el extracto por pantalla
echo htmlentities($_extracto_html);
 
// La salida:
// <p><strong

Como se puede observar en los ejemplos anteriores, esta forma de obtener un extracto de un texto nos puede ocasionar problemas realmente importantes, especialmente cuando cortamos textos con etiquetas HTML.

Una solución más adecuada a este problema la podemos obtener reutilizando funcionalidades implentadas y probadas en algunos Frameworks PHP. En este caso, reutilizaremos una función de CakePHP.

Cake PHP logoCakePHP

root / trunk / cake / x.x.x.x / cake / libs / view / helpers / text.php

Donde x.x.x.x equivale a la versión actual del framework

Para obtener la versión más reciente del código mostrado a continuación, podemos acceder al sistema de control de versiones (trac) de Cake PHP y obtener la última revisión.

Trac de Cake PHP

/**
* Truncates text.
*
* Cuts a string to the length of $length and replaces the last characters
* with the ending if the text is longer than length.
*
* @param string  $text String to truncate.
* @param integer $length Length of returned string, including ellipsis.
* @param mixed $ending If string, will be used as Ending and appended to the trimmed string. Can also be an associative array that can contain the last three params of this method.
* @param boolean $exact If false, $text will not be cut mid-word
* @param boolean $considerHtml If true, HTML tags would be handled correctly
* @return string Trimmed string.
*/
function truncate($text, $length = 100, $ending = &#39;...&#39;, $exact = true, $considerHtml = false) {
    if (is_array($ending)) {
        extract($ending);
    }
    if ($considerHtml) {
        if (mb_strlen(preg_replace(&#39;/<.*?>/&#39;, &#39;&#39;, $text)) <= $length) {
            return $text;
        }
        $totalLength = mb_strlen($ending);
        $openTags = array();
        $truncate = &#39;&#39;;
        preg_match_all(&#39;/(<\/?([\w+]+)[^>]*>)?([^<>]*)/&#39;, $text, $tags, PREG_SET_ORDER);
        foreach ($tags as $tag) {
            if (!preg_match(&#39;/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s&#39;, $tag[2])) {
                if (preg_match(&#39;/<[\w]+[^>]*>/s&#39;, $tag[0])) {
                    array_unshift($openTags, $tag[2]);
                } else if (preg_match(&#39;/<\/([\w]+)[^>]*>/s&#39;, $tag[0], $closeTag)) {
                    $pos = array_search($closeTag[1], $openTags);
                    if ($pos !== false) {
                        array_splice($openTags, $pos, 1);
                    }
                }
            }
            $truncate .= $tag[1];
 
            $contentLength = mb_strlen(preg_replace(&#39;/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i&#39;, &#39; &#39;, $tag[3]));
            if ($contentLength + $totalLength > $length) {
                $left = $length - $totalLength;
                $entitiesLength = 0;
                if (preg_match_all(&#39;/&[0-9a-z]{2,8};|&#[0-9]{1,7};|[0-9a-f]{1,6};/i&#39;, $tag[3], $entities, PREG_OFFSET_CAPTURE)) {
                    foreach ($entities[0] as $entity) {
                        if ($entity[1] + 1 - $entitiesLength <= $left) {
                            $left--;
                            $entitiesLength += mb_strlen($entity[0]);
                        } else {
                            break;
                        }
                    }
                }
 
                $truncate .= mb_substr($tag[3], 0 , $left + $entitiesLength);
                break;
            } else {
                $truncate .= $tag[3];
                $totalLength += $contentLength;
            }
            if ($totalLength >= $length) {
                break;
            }
        }
 
    } else {
        if (mb_strlen($text) <= $length) {
            return $text;
        } else {
            $truncate = mb_substr($text, 0, $length - strlen($ending));
        }
    }
    if (!$exact) {
        $spacepos = mb_strrpos($truncate, &#39; &#39;);
        if (isset($spacepos)) {
            if ($considerHtml) {
                $bits = mb_substr($truncate, $spacepos);
                preg_match_all(&#39;/<\/([a-z]+)>/&#39;, $bits, $droppedTags, PREG_SET_ORDER);
                if (!empty($droppedTags)) {
                    foreach ($droppedTags as $closingTag) {
                        if (!in_array($closingTag[1], $openTags)) {
                            array_unshift($openTags, $closingTag[1]);
                        }
                    }
                }
            }
            $truncate = mb_substr($truncate, 0, $spacepos);
        }
    }
 
    $truncate .= $ending;
 
    if ($considerHtml) {
        foreach ($openTags as $tag) {
            $truncate .= &#39;&#39;;
        }
    }
 
    return $truncate;
}

Ejemplo de uso

CakePHP

truncate($_noticia_html, 10, &#39;...&#39;, false, true);

Los parámetros que acepta la función son los siguientes:

  • $text: texto completo, texto sobre el que deseamos obtener el extracto.
     
  • $length: número de caracteres que deseamos obtener para nuestro extracto. Empezando por el principio. Este es un parámetro opcional y por defecto su valor es de 100 caracteres.
     
  • $ending: cadena que colocaremos al final del extracto. Parámetro opcional con un valor por defecto igual a '…'.
     
  • $extract: parámetro que indica si deseamos obtener un extracto sin evitar que las palabras queden cortadas. Por defecto, cierto (true) que indica que no nos importa que las palabras se corten. Con falso (false) evitaremos que se corten.
     
  • $considerHtml: este último parámetro es el que nos va a permitir indicar si deseamos generar código HTML correcto o si por el contrario no nos preocupa que nuestro extracto contenga una estructura incorrecta de tags HTML. Por defecto, el valor de este parámetro será falso (false) y por lo tanto, nuestro extracto pude contener código HTML mal formado. Con un valor igual a cierto (true) generaremos un extracto con código HTML correcto.
// Definimos el texto
$_noticia_html = "<p><strong>Sergio Guerrero est&aacute; cortando este texto</strong></p>";
// Obtenemos un extracto con los 10 primeros caracteres
$_extracto_html = truncate($_noticia_html, 10, &#39;...&#39;, false, true);
//&nbsp;Mostramos el resultado por pantalla
echo htmlentities ($_extracto_html);
 
//&nbsp;La salida:
// <p><strong>Sergio...</strong></p>

Este ejemplo de uso demuestra como podemos reutilizar fácilmente el código de los Frameworks PHP para mejorar nuestras aplicaciones.

Actualización – 29-01-2010

El repositorio de CakePHP ha sido movido a GitHub: http://github.com/cakephp

Página 2 de 3«123»