Programador PHP freelance

01 Apr, 2014

Aproximación a CodeIgniter

Posted by: admin In: Desarrollo

Codeigniter logo

Codeigniter logo

Uno de los desarrollos que me han encargado últimamente es la ampliación de un portal desarrollado en CodeIgniter. Como buen programador freelance una de las cosas que me define es que disfruto cada vez que debo de acercarme a una nueva tecnología.

En este caso conocía el framework pero aún no había tenido la oportunidad de utilizarlo. Lo primero que diré es que es un framework con una cierta antigüedad, lo cual tiene ventajas y desventajas.

Implementa MVC (Model-View-Controller) lo cual es una buena noticia. La documentación es buena y de hecho recomiendo la lectura del tutorial de introducción donde podemos ver, mediante ejemplos prácticos, como funciona el framework, implementando páginas estáticas y una gestión de noticias contra base de datos.

Otra de las ventajas es que Internet está llena de información. Una búsqueda del nombre del framework en Stackoverflow nos devuelve 27.000 resultados, lo cual no está nada mal. También se puede interpretar como que CodeIgniter genera muchas dudas… pero quiero ser optimista ;-)

El sistema implementa helpers, libraries y drivers. Estos últimos, una especie de librerías desarrolladas con programación orientada a objetos, lo cual permite posteriormente, desarrollar clases hijas que heredan de la clase madre y implementan funcionalidad concreta. Aparentemente, librerías mejoradas y con las ventajas de la OPP.

Se me ocurre que un buen ejemplo de utilización sería la implementación de un driver TPV genérico del cual heredarían clases hijas específicas para cada TPV concreto (Sermepa, Pasat, etc…)

En principio todavía es pronto para dar un veredicto final pero quiero destacar dos cosas que no me han gustado.

El sistema presume de utilizar el patrón de diseño Active Record de una forma particular pero incluso en la Wikipedia podemos ver que su implementación se aleja bastante de lo deseado. Personalmente soy un gran aficionado a este patrón, el cual conocí mientras desarrollaba con PEAR. En este caso no es cierto que el modelo lo implemente.

Por otro lado el enrutado debe ser definido en un array para cada una de las acciones de los controladres, lo cual da cierta flexibilidad, pero comparado con Zend, por ejemplo, pienso que pierde comodidad. En este último el funcionamiento es el contrario. Si se hace una llamada a una acción dentro de un controlador, el sistema busca dicha acción y simplemente se devuelve un erroro la acción por defecto en el caso de no encontrar la acción. No necesitamos definir cada ruta para cada acción. Se hace implícitamente.

Desconozco si CodeIgniter plantea el enrutado así por una cuestión de performance pero entiendo que no debería de afectar. Si hago una llamada a un ruta es porque existe una acción que responde a ella.

Yo seguiré profundizando en la criatura… mientras tanto me gustaría conocer vuestra opinión. Ahí está la caja de comentarios ;-)

28 Feb, 2014

Resetear la contraseña de Drupal con Drush

Posted by: admin In: Desarrollo

Logo de Drush

La receta de hoy es breve pero muy útil.

Seguro que más de una vez has necesitado resetear/reiniciar la contraseña de algún usuario Drupal.

Puedes atacar a la base de datos directamente pero con Drush es mucho más sencillo:

drush user-password USERNAME –password=”PASSWORD”

Además, seguro que haciendo pruebas, alguna vez has bloqueado tu cuenta por número máximo de intentos de acceso. Drush es tu amigo y vuelve a ayudarte, esta vez atacando a la base de datos.

Este comando desbloquea al usuario:

drush php-eval ‘db_query(“DELETE FROM `flood`”);’

 

 

 

 

26 Feb, 2014

Crear módulos en Drupal con Module Builder

Posted by: admin In: Desarrollo

Dejo aquí un módulo de Drupal que me ha parecido interesante.

Como programador Drupal, en ocasiones necesito programar módulos a medida para cubrir alguna funcionalidad que no puedo cubrir con el Core o con los módulos existentes.

En esos casos, Module Builder nos permite crear el skeleton o scaffolding del módulo que deseamos desarrollar permitiendo además incluir el código base para los hooks que queremos manipular, entre otras ventajas.

Puede ejecutarse como un módulo más dentro del propio Drupal y crear el módulo deseado con un formulario visual pero según comentan en la documentación, la versatilidad más potente se encuentra al ejecutarlo desde Drush.

Una vez instalado, y con esta simple línea de código, crearemos el skeleton de nuestro módulo Drupal contestando a las preguntas que nos hará el builder.

drush mb my_module menu cron form_alter –write

En este caso creamos un módulo my_module con los hooks de menu, cron y form_alter.

 

Si son raras las ocasiones en las que programas un módulo a medida puede no compensarte utilizar el builder. Si personalizas muchos módulos, se convierte en una herramienta más que interesante.

Cómo siempre, me gustaría conocer las herramientas que usáis. La caja de comentarios de más abajo es vuestra ;-)

LoginExisten varios formas de integrar el login mediante redes sociales en Drupal 7 pero después de analizar unas cuantas me quedo con la que integra HybridAuth.

 

HybridAuth es una librería PHP que hace de wrapper o envoltorio de las APIs de la gran mayoría de redes sociales, entre ellas las más famosas, como Twitter, Facebook, Linkedin,…

Nos permite acceder a los perfiles de usuario, listado de amigos, activity, publicación de contenidos,… y por ente la posibilidad de que el usuario haga login mediante la red social. Esto nos abstrae y agiliza el desarrollo, sobretodo si vamos a atacar varias plataformas.

 

En el caso que me ocupaba esta vez, necesitaba integrar el login con redes de Facebook, Twitter i Linkedin. El módulo es bastante sencillo de configurar, siendo más costoso definir las apps en las respectivas redes que la propia configuración en Drupal. Una vez logado, el módulo de Drupal utilizaba parte de la información del perfil facilitado por HybridAuth para cargar esa información en el perfil del usuario Drupal a crear. En concreto, el portal Drupal utiliza unas imágenes bastante grandes para el perfil, lo cual era un problema tanto en Twitter como en Linkedin ya que las imágenes facilitadas por defecto son miniaturas, de dimensiones reducidas, que al ser importadas quedaban pixeladas.

Buceando un poco en el código se puede descartar que sea un problema del módulo. Este hace su trabajo. Ante una petición de login, pasa la llamada a la libreria de HybridAuth y esta se encarga de hablar con la API correspondiente y recuperar la info del perfil del usuario.

En el caso concreto de Twitter, dentro de Hybrid/Providers/Twitter.php, podemos encontrarnos con el método responsable de recuperar la imagen de perfil. El método es getUserProfile() y dentro de él podemos detectar fácilmente donde se recupera la susodicha

$this->user->profile->photoURL    = (property_exists($response,’profile_image_url’))?$response->profile_image_url:”";

 

Preguntando al todopoderoso Google nos encontramos con que existe la posibilidad de recuperar la imagen original simplemente modificando la URL que nos devuelve el API de Twitter.

Aquí tenéis la URL original que apunta a la versión por defecto que devuelve Twitter.

http://pbs.twimg.com/profile_images/330029542/avatar_normal.jpg

Si eliminamos el sufijo ‘_normal’ pasamos a tener la imagen original

http://pbs.twimg.com/profile_images/330029542/avatar.jpg

Con esto, podemos modificar la línea que comentaba más arriba para forzar a la librería a recuperar la imagen original.

$this->user->profile->photoURL    = (property_exists($response,’profile_image_url’))?str_replace(‘_normal’, ”, $response->profile_image_url):”";

 

El caso de Linkedin es un poco diferente. Debemos de modificar la llamada a la API para pedirle que nos envíe la imagen original. Aquí tenéis la llamada original y la modificada:

$response = $this->api->profile(‘~:(id,first-name,last-name,public-profile-url,picture-url,email-address,date-of-birth,phone-numbers,summary)’);

$response = $this->api->profile(‘~:(id,first-name,last-name,public-profile-url,picture-url,picture-urls::(original),email-address,date-of-birth,phone-numbers,summary)’);

y posteriormente tratar la respuesta para aislar dicha imagen. Aquí os pego el código original y el modificado:

$this->user->profile->photoURL    = (string) $data->{‘picture-url’};

 

if( $data->{‘picture-urls’} && $data->{‘picture-urls’}->{‘picture-url’} ){
$photoURL = (array) $data->{‘picture-urls’}->{‘picture-url’};
$this->user->profile->photoURL = (string) $photoURL[0];
}
else{
$this->user->profile->photoURL = (string) $data->{‘picture-url’};
}

 

Un apunte final… Para jugar con las diferentes APIs podéis utilizar la consola de Apigee. Lleva implementada el API de las principales redes sociales lo cual os resultará muy cómodo a la hora de localizar las llamadas o testear de forma rápida la respuesta. Priceless.

07 Oct, 2013

Desindexar un subdominio en Google

Posted by: admin In: SEO

robots.txt felt robot

Se me ha dado el caso de necesitar desindexar un subdominio de desarrollo que era un clón del dominio de producció. El subdominio ha llegado a indexar más pàginas que las propias de producción, y teniendo en cuenta que replica contenidos, esto es un problema, si tenemos en cuenta que los buscadores, en especial Google, lo pueden considerar contenido duplicado, lo que puede implicar sanciones en el posicionamiento.

Parece ser que una opción pasa por añadir redirecciones 301 al subdominio de forma que todas las URLs sean redirigidas a su equivalente en el dominio de producción, pero este proceso es lento. Hablamos de semanas o incluso meses en el caso de cantidades considerables de URLs.

La alternativa es dar de alta el dominio en las Webmaster Tools, verificarlo y realizar una petición de eliminación de contenido desde la propia herramienta. En concreto lo podemos hacer desde el menú Google Index > Remove URLs

En esta sección nos encontraremos con un botón para crear una nueva petición de borrado de URLS. Nos pedirá que introduzcamos la URL a eliminar. Ya que deseamos eliminar todas las páginas del subdominio, hay que dejar el campo en blanco. En este punto seguramente notemos un pequeño ataque de ansiedad al imaginar que este proceso desindexe, no sólo el subdominio, sino también el dominio de producción, con lo catastrófico que puede ser para el SEO de la página principal. No pasará, así que coge aire y se valiente ;-)

Lo siguiente que habrá que responder es si queremos eliminar la indexación únicamente o también la caché de las páginas. En nuestro caso, evidentemente, deseamos borrarlo todo.

Eliminar URLs

 

 

 

 

Una vez enviada la petición, por mi propia experiencia, Google viene a tardar apenas 3 horas en desindexar el subdominio por completo. Algo que es de agradecer porqué nos permite corregir errores en URLs de forma rápida.

Como rezan en las propias páginas de soporte de Webmaster Tools, el proceso de eliminado por petición tiene una durabilidad, después de la cual Google vuelve a indexar aquello que sea indexable por lo que recomiendan que indiquemos por las vías habituales que URLs deben de ser indexadas y cuales no.

Si deseamos evitar que un subdominio se indexe por completo, una buena opción es la configuración del fichero robots.txt, situado en la raíz del subdominio, y que debería de contener lo siguiente:

User-agent: *
Disallow: /

Con esto le decimos a todos los bots que no indexen nada de lo que cuelga del directorio raíz y cerramos el proceso.

 

Esto es un snippet que no tiene mayor complejidad pero que puede venir muy bien para modificar el password de algún usuario de WordPress desde la consola de MySQL o un PHPMyAdmin.

UPDATE `wp_users`
SET `user_pass` = MD5(‘contraseña’)
WHERE `user_login` = ‘usuario’
LIMIT 1;

Jungle Air Mail Service from the Jungle Cruise 2nd Floor Overflow QueueRevisando mi servidor dedicado, después de un problema con el spam, he visto que el lifetime de los emails en la cola de salida del Qmail no está definido.

El queuelifetime se define como el número de segundos que un mensaje se mantendrá en la cola de salida antes de ser descartado. Cuando un mensaje no puede recepcionarse por el destino, el servidor se lo guarda en la cola para volver a intentar el envío más tarde. Los reintentos de envío se repiten varias veces hasta que este consigue ser enviado o se produce un timeout definido por el queuelifetime.

Parece ser que el valor por defecto es de 7 días, lo cual es bastante tiempo, y puede ser un problema en situaciones extraordinarias.

Algunas consideraciones al respecto de cual puede ser un buen valor.

Si los DNS de nuestro destinatario han sido modificados, técnicamente la propagación puede llegar a tardar 48 horas. En la práctica estos tiempos suelen ser bastante menores pero conviene tenerlo en cuenta.

Otro caso. Si se produce un problema en el servidor del destinatario, en el caso en que no esté monitorizado o se produzca un viernes a la madrugada y el soporte no actúe hasta el lunes, pueden llegar a pasar más de 48 horas. Si además tenemos en cuenta el tiempo de resolución, podemos estar hablando de incluso 3 o 4 días.

Pueden presentarse otras situaciones similares lo que me hace pensar que un valor entre 3 o 5 días puede ser acertado.

Para configurar este valor hay que crear un fichero con el lifetime  en segundos que deseemos. Os dejo aquí un ejemplo donde, desde el shell, se fija el queuelifetime a 3 días. Está basado en un servidor con Plesk por lo que seguramente las localizaciones de los ficheros sea diferente a una instalación Linux estandar. Seguramente necesitaréis el usuario root.

echo “259200″ > /var/qmail/control/queuelifetime

Y luego, claro, hay que reinciar el servicio.

/etc/init.d/qmail restart

 

Si tenéis otras consideraciones al respecto de como elegir un lifetime adecuado, soy todo oídos. No os cortéis.

 

Anotaciones

Un compañero desarrollador, David Martínez Martí, me comenta que el RFC recomienda un queuelifetime de 4 días. Por otro lado, añade también que el Qmail tiene hardcodeado 7 días como valor máximo, por lo que aunque configuráramos un valor superior, nunca se aplicaría.

Habitualmente las contraseñas en los proyectos web son guardadas en la base de datos de forma encriptada en un formato hash. Con esto evitamos guardar en claro dichas contraseñas. El algoritmo de encriptación además suele ser bastante básico, com aplicar un MD5 o similar.

En algunos proyectos, no obstante, añaden cierta complejidad incorporando un valor adicional a la formula de encriptación. Es el caso de Prestashop que desde sus orígenes utiliza una cadena definida en el fichero config/settings.php. Dicha variable queda definida en ese fichero como _COOKIE_KEY_

Cuando deseamos resetear o modificar las contraseñas necesitamos regenerar los hash que se guardan en la bases de datos. En el caso de Prestashop deberemos de incorporar el valor antes comentado.

En los proyectos que muevo muchas veces clonar el entorno de producción en un entorno de desarrollo con la finalidad de realizar ampliaciones. Y muchas veces necesitas poder logarte con varios usuarios con roles diferentes, entre ellos el de administrador, el resto de empleados o los usuarios clientes. La forma más cómoda que he encontrado de trabajar es la de resetear o cambiar todas las contraseñas al mismo valor.

Os adjunto un script que he preparado para facilitar esto último. Es muy intuitivo. Si lo copiáis en el directorio config y lo ejecutáis desde consola o bien por URL, modificará todas las contraseñas a la definida en la variable $passwd.

<?php
require_once ‘settings.inc.php’;

$link = mysqli_connect(_DB_SERVER_, _DB_USER_, _DB_PASSWD_, _DB_NAME_);

if (!$link) {
die(‘Connect Error (‘ . mysqli_connect_errno() . ‘) ‘
. mysqli_connect_error());
}

$passwd = ‘NoVaInternet’;
$md5 = md5(_COOKIE_KEY_ . $passwd);
$link->query(“UPDATE ” . _DB_PREFIX_ . “employee SET passwd = ‘$md5′”);
$link->query(“UPDATE ” . _DB_PREFIX_ . “customer SET passwd = ‘$md5′”);

mysqli_close($link);
?>

Chains
InnoDB, en MySQL, aportó en su día lo que muchos esperábamos: cumplir, entre otras cosas, con aquel concepto tan académico de integridad referencial que nos permitía estar seguros de que los datos estaban bien ligados entre ellos (siempre y cuando nuestro diseño fuera acertado, claro está ;-) )

Esto es bastante útil pero da algunas pegas en el día a día del programador. En concreto nos puede pasar que intentemos importar una copia de base de datos sobre una existente y nos encontremos con este error:

Cannot delete or update a parent row: a foreign key constraint fails.

Lógico, si lo pensamos. Tenemos las relaciones monitorizadas y ya no se puede eliminar al tun tun.

¿Solución?

Como estamos restaurando una base de datos entera no queremos mantener ninguno de los datos anteriores por lo que la restricción puede ser obviada sin ningún problema.

¿Forma de hacerlo?

Decirle a MySQL que desactive temporalmente la comprobación de la integridad con la siguiente orden:

SET FOREIGN_KEY_CHECKS=0;

Para activarlo, una vez recuperada la base de datos, con el inverso:

SET FOREIGN_KEY_CHECKS=1;

Si estáis recuperando la base de datos mediante la importación de un fichero SQL, tal vez des de un cliente como phpMyAdmin, una buena opción es integrar los dos comandos anteriores en el propio fichero SQL. El de deshabilitar el principio, y el de habilitar al final.

02 Oct, 2012

Configurar PEAR para un dominio en Plesk

Posted by: admin In: Desarrollo

Ahora mismo arranco los desarrollos con Zend Framework. MVC, robusto, bien pensado, bien documentado, escalable,… y muchas más cosas que a poco que hayamos oído hablar de él, ya nos suenan. La verdad es que lo estoy disfrutando. Pero antes de Zend estuve con otros frameworks, en especial, utilicé mucho PEAR.

PHP PEAR framework

PEAR se organiza por paquetes y la mayor crítica que se le puede hacer es que no es MVC. De hecho yo diría que es un framework a la antigua, con una gran variedad de librerías para realizar casi cualquier cosa. De todas ellas la más destacable para mi, una de las que permiten desarrollar la capa de datos: DB_DataObject. Si tenéis tiempo, os aconsejo que juguéis con ella.

PEAR tiene otra ventaja, para los linuxeros como yo, y es que tiene paquete en la mayoría de distros, por lo que instalar-lo en mi Ubuntu es tan fácil como apt-get install pear.

Y a partir de aquí viene la gracia. Y es que PEAR a su vez tiene un gestor de paquetes que es llamado desde consola por ejemplo así: pear install Auth, con lo que conseguimos instalar el paquete de autorización.

Si utilizamos este sistema para su instalación en un servidor donde alojamos varios proyectos con Plesk, como puede ser la misma máquina de desarrollo o un servidor de producción, tenemos la ventaja de que centralizamos la gestión de los paquetes PEAR y su posterior actualización.

Esto en servidores controlados por nosotros suele ser inmediato y PEAR, una vez instalado, se aplica a todos los dominios que albergue nuestro servidor web. En el caso de Plesk, dada su particular configuración de los planes requiere de ciertos cambios… Y a eso hemos venido.

Cuando necesitamos que un dominio en Plesk pueda acceder al PEAR del sistema necesitamos modificar el include_path del PHP para ese dominio, cosa que se consigue creando/modificando el fichero /var/www/midominio.com/conf/vhost.conf con el siguiente contenido:

<Directory /var/www/vhosts/midominio.com/httpdocs>
php_admin_value include_path “/var/www/vhosts/midominio.com/httpdocs/:/usr/share/pear/”
php_admin_value open_basedir “none”
</Directory>

Si nos fijamos, hemos añadido al include_path el path del PEAR en el sistema. Esta linea, de hecho, es valida para un CentOS mientras que para una Ubuntu suele ser así:

php_admin_value include_path “/var/www/vhosts/midominio.com/httpdocs/:/usr/share/php/”

Comentar que para editar este fichero es necesario tener permisos de root, lo cual seguramente nos obligará a acceder por SSH al sistema.

Una vez realizada esta modificación el siguiente paso es forzar a Plesk para que cargue la nueva configuración, lo que se consigue con el siguiente comando desde el shell:
/usr/local/psa/admin/sbin/websrvmng – -reconfigure-vhost –vhost-name=midominio.com
Esto era cierto para las versiones de Plesk 8 y 9. Para la 10 lo desconozco y para la 11 el comando actualizado es:
/usr/local/psa/admin/sbin/httpdmng –reconfigure-domain midominio.com
Con esto nuestro dominio queda configurado para trabajar con PEAR. Ahora solo queda instalar los paquetes que necesitemos.
pear list nos irá indicando que tenemos ya instalado.
PD. Si también utilizas PEAR tal vez nos interese conocernos ;-)
PD 2. Añadir que este tipo de configuraciones sólo funcionan en aquellos casos donde el PHP se ejecuta como módulo del servidor web Apache y no como CGI. El propio Plesk permite la configuración por dominio de este parámetro.
Tags: , ,

About

ProgramadorPHP.es es el blog profesional de Vicent González i Castells, programador freelance especializado en desarrollo de aplicaciones web. vigoncas@programadorphp.es

CURRÍCULUM

Tags