jueves, 30 de julio de 2009

PHP 5.3, ¿Qué hay de nuevo viejo?


Hace unos días instalé la útlima versión de PHP lanzada el 30 de junio de 2009. Hay muchos cambios, elementos nuevos y obsoletos, varios de ellos esperados para la versión 6.0 pero que, desconozco la razón, los adelantaron.

No hablaré de todos los cambios, obsolencias y nuevas funcionalidades, sino que relataré cuales fueron los cambios que exigieron de mi atención al momento de la instalación. Si quieren más detalles pueden revisar la serie de artículos en IBM developerWorks respecto de PHP 5.3.

Lo primero con lo que me encontré fue con nuevos niveles de error. A los ya existentes se suman E_DEPRECATED y E_USER_DEPRECATED los cuales nos advierten sobre funciones o sintaxis obsoleta. Actualmente trabajo con un framework que yo mismo desarrollé y con CakePHP. Con el primero no tuve problemas respecto a obsolencias pero con el segundo si los tuve ya que en diversas partes asigna por refencia instancias de clases (ver función new). La forma de "resolverlo" (esto hasta que la gente de CakePHP libere una actualización) es realizar un pequeño cambio en la función write, de la clase configure.php ubicada en cake/libs/. Basta con cambiar la línea en donde aparece "error_reporting(E_ALL)" por "error_reporting(E_ALL & ~E_DEPRECATED)". La función debería quedar así:

function write($config, $value = null) {
$_this =& Configure::getInstance();
if (!is_array($config)) {
$config = array($config => $value);
}
foreach ($config as $names => $value) {
$name = $_this->__configVarNames($names);
switch (count($name)) {
case 3:
$_this->{$name[0]}[$name[1]][$name[2]] = $value;
break;
case 2:
$_this->{$name[0]}[$name[1]] = $value;
break;
case 1:
$_this->{$name[0]} = $value;
break;
}
}
if (isset($config['debug'])) {
if ($_this->debug) {
error_reporting(E_ALL & ~E_DEPRECATED);

if (function_exists('ini_set')) {
ini_set('display_errors', 1);
}

if (!class_exists('Debugger')) {
require LIBS . 'debugger.php';
}
if (!class_exists('CakeLog')) {
require LIBS . 'cake_log.php';
}
Configure::write('log', LOG_NOTICE);
} else {
error_reporting(0);
Configure::write('log', LOG_NOTICE);
}
}
}
CakePHP trae un manejador de niveles de error propio, por lo tanto, aunque indiquemos en php.ini el nuevo nivel de error, CakePHP seguirá indicando el mensaje de codigo "Deprecated". Si no trabajan con CakePHP y quieren manejar esto para todas sus aplicaciones y sitios ,el cambio que deben aplicar en el archivo php.ini es agregar & ~E_DEPRECATED a la directiva error_reporting.

Otra novedad es el cambio de la librería de comunicación con MySQL. Hasta la versión 5.2.9 se utilizaba únicamente la librería libmysql la cual estaba desarrollada para C y C++. Ahora se utiliza mysqlnd la cual está desarrollada específicamente para PHP la cual, según dicen y que no he probado empíricamente, mejora el rendimiento en diversos aspectos.

Con libmysql la configuración de instalación PHP típica (hablo de unix/linux) era:

./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql

Pero ahora cambia por:

./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql=mysqlnd --with-mysql-sock=/var/run/mysqld/mysqld.sock


Por último, PHP 5.3 ya no utiliza la función ereg() para trabajar con expresiones regulares, ahora debemos utilizar preg_match() la cual no varía drásticamente en los parámetros de ingreso, permitiendo su reemplazo, en algunos casos, con un rápido buscar/reemplazar.

Este último cambio afecta a la libería para web services NuSoap la cual, lamentablemente, aún no tiene actualización para aumentar la compatibilidad pero si hay un foro abierto al respecto.

En la medida que aparezcan más cosas las iré comentando. Pueden consultar las siguientes fuentes con más información al respecto:

viernes, 24 de julio de 2009

Validador de Rut en Spry (corregido)


En un post anterior publiqué un validador de Rut para el framework javascript Spry. Dicho validador tenía un problema con Internet Explorer 7 (no me pregunten por IE6 porque no me interesa desarrollar para esa versión), el cual fue descubierto por Lester. El problema estaba en que IE no permite manipular strings de la misma forma como lo hace Gecko. En el código publicado, tenía un ciclo de esta forma:
for(i=(elRut.length-1); i>=0; i--){
factor = factor > 7 ? 2 : factor;
suma += parseInt(elRut.[i])*parseInt(factor++);
}

La forma de acceder a cada elemento del primer string del rut era por medio de string[i] pero a IE no le gusta eso, así es que lo cambié por la función charAt() que permite acceder a X parte de un string indicado por la posición del caracter.

El ciclo quedó así:
for(i=(elRut.length-1); i>=0; i--){
factor = factor > 7 ? 2 : factor;
suma += parseInt(elRut.charAt(i))*parseInt(factor++);
}

Adicionalmente cambié el manejo de expresiones regulares al canón de Spry. En resumen el validador quedó así:

'rut':{
 regExpFilter: /^([0-9])+\-([kK0-9])+$/,
 validation: function(value){
 if(value == ''){
  return false;
 }
 var regExp = /^([0-9])+\-([kK0-9])+$/;
 if (!regExp.test(value)) {
  return false;
 }
 var RUT  = value.split("-");
 var elRut = RUT[0]
 var factor = 2;
 var suma = 0;
 var dv;
 for(i=(elRut.length-1); i>=0; i--){
  factor = factor > 7 ? 2 : factor;
  suma += parseInt(elRut.charAt(i))*parseInt(factor++);
 }
 var ret = value.toString();
 dv = 11 -(suma % 11);         
 if(dv == 11){
  dv = 0;
 }else if (dv == 10){
  dv = "k";
 }
 if(dv != RUT[1].toLowerCase()){
  ret= false;
 }
 return ret;
 }
 }

Pueden descargar la versión corregida acá. También está corregida la demo.

¡Gracias Lester por el aviso!