miércoles, 3 de diciembre de 2014

Se ha publicado Symfony 2.6

El pasado 29 de noviembre se publicó la nueva versión 2.6 del popular framework PHP Symfony [EN]. Dicha versión incluye multitud de novedades como por ejemplo la inclusión de las llamadas AJAX en la barra de depuración [EN], el nuevo tema para formularios basado en Bootstrap 3 [EN], el nuevo instalador de Symfony [EN] y así hasta 100 cambios, mejoras y correcciones. Puedes consultar la lista completa de cambios de Symfony 2.6 [EN] y las actualizaciones necesarias para pasar de Symfony 2.5 a 2.6 [EN]. Symfony 2.6 se actualizará hasta julio de 2015 y tendrá soporte hasta enero de 2016.

Siguiendo con Symfony recientemente se ha dado a conocer la hoja de ruta para los próximos Symfony 2.7 [EN], con fecha de lanzamiento prevista en mayo de 2015, que será LTS con soporte hasta mayo de 2019 y la última versión de Symfony 2; y el futuro Symfony 3 [EN] que romperá la compatibilidad con las versiones anteriores pero que no supondrá un cambio trágico como lo fue el paso de Symfony 1 a Symfony 2. Las principales novedades que se conocen de Symfony 3 son que se aumentará el requisito de versión de PHP mínimo a PHP 5.5 o PHP 5.6 y que se eliminará código obsoleto, rompiendo compatibilidad con las versiones anteriores.

Referencias

jueves, 13 de noviembre de 2014

PepePhone, la seguridad informática y los diseños inconsistentes

Pepephone es el operador virtual de telefonía móvil mejor valorado por sus usuarios según diversas encuestas. La principal característica de este OMV, más allá de la competencia de precios, es tener los operadores del servicio de atención al cliente en España (concretamente en Palma de Mallorca). Además según la propia Pepephone sus operadores están entrenados para resolver todos los problemas en una llamada y tienen permisos para hacer todos los cambios en el contrato que pida el cliente, pero en cambio tienen prohibido tratar de venderte nada u ofrecerte cambios de tarifas ni nada parecido. La segunda parte no la discuto ya que jamás ningún operador ha de Pepephone ha intentado colarme un cambio de contrato ni nada similar. En cambio eso de que los operadores están entrenados para resolver los problemas del cliente es... ¡discutible!

Contaré mi caso. El pasado 1 de noviembre tuvimos que dejar la empresa sin actividad (congelada) por problemas que no vienen al caso por lo que llamo al 1212 para solicitar un cambio de titular para poner la línea móvil a mi nombre y cambiar la cuenta bancaria. El operador amablemente me informa que tengo que hacerlo desde el área de cliente de la web de Pepephone. Fallo mío. Acostumbrado a tratar con Movistar, Vodafone o Endesa por ejemplo desde cuyas webs se puede hacer de todo menos lo que necesitas (sea lo que sea), no lo había mirado. Cuelgo y voy al área de clientes de Mi Pepephone. Localizo la opción del cambio de titular enseguida, introduzco todos los datos incluido la fotocopia de mi DNI y meeeeeeeeeeeeec: "el email introducido ya está en uso". Vaya por dios. El email es clave única.

Desde el punto de vista del diseño informático, hacer que el email sea clave única y con ello obligar a cambiar el email al cambiar el titular es algo que yo no haría por diversos motivos, pero cosas más raras se han visto. En fin como no me da la gana cambiar de email, uso una cuenta de GMail y sé que puedo alterar la dirección y seguir recibiendo el correo normalmente, lo que hago es poner nombre.apellidos@gmail.com en lugar de nombreapellidos@gmail.com. El email es distinto para el sistema y yo sigo recibiendo emails en la misma cuenta. Le vuelvo a dar a "enviar" y no ocurre nada. Ni un mensaje de confirmación de envío ni un mensaje de error. ¡Nada! ¿Lo habrá enviado? Vuelvo a pulsar enviar y entonces aparece un mensaje de error: "Solicitud ya en curso".

Confuso. Mucho. Un simple mensaje de "formulario enviado" habría bastado para saber si todo iba bien o sino un email de confirmación. Pero no. Nada de nada. Al día siguiente, mosqueado, repito el proceso con el mismo resultado: la primera vez que pulso el botón no hace nada (el formulario queda con todos los datos en modo edición como si no hubiera hecho nada). La segunda vez me muestra el mensaje "Solicitud ya en curso".

Decido dar un voto de confianza a Pepephone, esperando un par de días con la esperanza de que todo funcione bien. Y... sorpresa: ¡lo hace! Un par de días después recibo un email "Te confirmamos que la solicitud de cambio de titular se ha completado con éxito". Y me mandan las nuevas credenciales de acceso, ya con el email nombre.apellidos@gmail.com. Accedo al área de cliente y meeeeeeeeeeeeec: "707 usuario no autorizado". Mi gozo en un pozo. Decido esperar un día más por aquello de que uno es informático y sabe que a veces esas cosas se arreglan "solas" por la noche (cuando pasa el batch, quiero decir). Pero no... ni al día siguiente ni al otro consigo acceder a mi cuenta con las credenciales que me han dado. ¡Aquí nada funciona a la primera!

¿Qué hago ahora? Lo primero será llamar a esos super-operadores de Pepephone, ¿no? Llamo, explico mi problema y el operador empieza a preguntar: DNI, email, número de teléfono, dirección,... número de cuenta. "¿Número de cuenta? Pues ni idea. Estoy en la calle y en estos momentos no tengo forma de saber el número de cuenta". "Pues si no me dice el número de cuenta no puedo resetearle el password, señor". "¿Y no tienes alguna otra forma? Ya te he dado el email, el teléfono, el dni... y lo único que quiero es que me mandéis otra password". "Pues no, señor. Si no me dice todos los datos yo no puedo hacer nada, pero si quiere puede enviar un mail a pepephone@pepephone.com y pedírselo a mis compañeros".

¿Un email? ¡Ya! ¡Seguro que sí! Venga, no pierdo nada: Escribo el email y lo envío. Nos vamos a reír. Cuatro horas después me contestan (se han dado prisa): "Lamentablemente, en la solicitud que nos han remitido, el email solicitado pertenece a otro cliente ya existente. Con el fin de poder atender a la petición que nos habían remitido le agradeceríamos que nos indicasen un correo electrónico alternativo para incluir en su perfil de usuario". Esta vez me lo esperaba. Si no escribo "desde" nombre.apellidos@gmail.com no me resetean el password.

Cabreado ya entro en Mi Pepephone, busco la opción de he olvidado mi contraseña, introduzco ***sólo*** el DNI y el email y dos minutos después recibo el email con la nueva clave de acceso. Y funciona.

Lo que he escrito hasta aquí no es más que un mensaje-pataleta digno de ForoCoches.com. Desde luego llamar al 1212 sin haber buscado antes en Internet fue un error de looser deluxe. Nota mental: borrar el 1212 de la memoria del teléfono (para lo que sirve). Ahora viene la moraleja:

Lo que quería ilustrar con este ejemplo es como algunas empresas pueden complicar innecesariamente un proceso sencillo como es el asignar una nueva clave de acceso, mareando al usuario y haciéndole perder el tiempo. Si para resetear el password desde Internet sólo necesito el email y el dni, ¿Por que para pedirlo por teléfono me tienen que pedir el número de cuenta? Y respecto al email, ¿Qué más da la dirección desde la que escriba? Como si eso no se pudiera simular. ¿Por que los procesos empresariales no son consistentes? Según mi experiencia eso ocurre por falta de coordinación entre departamentos. Es más que habitual que en una empresa relativamente grande no haya nadie que tenga una visión de conjunto de los procesos empresariales relacionados con las TIC (tecnologías de la información y la comunicación) de forma que el mismo proceso funcione de forma diferente dependiendo de que departamento lo ejecute. Y eso es un error.

Las causas de esa descoordinación entre departamentos pueden ser muchas, pero yo apuesto como culpable principal por la externalización salvaje de los servicios de las TIC. A corto plazo puede suponer un ahorro considerable para el empresario, pero si externalizas todo el departamento de informática pierdes conocimiento funcional porque el personal externo suele tener una rotación más elevada que el personal interno. Externalizar la programación por ejemplo puede estar bien siempre que mantengas a los jefes de proyecto y analistas en nómina. No digo que ese haya sido el caso de Pepephone. Hablo de experiencias personales.

domingo, 2 de noviembre de 2014

Symfony 2 avanzado: Cómo pasar el 'locale' a un servicio

Muchas aplicaciones Symfony 2 son multiidioma gracias a la capacidad del popular framework para manejar las traducciones. En este contexto la variable locale contendrá el identificador del idioma. Desde el controlador es muy sencillo obtener el locale a partir del request; basta pedirlo: $this->get('request')->getLocale(). En cambio no es tan sencillo inyectar el locale en el constructor de un servicio debido a los diferentes ámbitos (scopes) que pueden tener los servicios.

Sin embargo hay un truco para hacerlo:

<service
    id="mylocale"
    class="Symfony\Component\HttpFoundation\Request"
    factory-service="request"
    factory-method="getLocale">
</service>

<service
   id="myservice"
   class="%myservice.class%">
   <argument type="service" id="mylocale" on-invalid="null" />
</service>

Es decir, primero creamos un service factory que acceda al Request para obtener el locale y luego inyectamos el service factory en nuestro servicio. el parámetro on-invalid="null" es muy importante para solucionar aquellos casos en que el Request no existe; como por ejemplo los comandos de consola. Al implementar la clase hay que tener en cuenta que es posible que recibamos null en lugar del locale.

class MyService
{
    /**
     * @var string
     */
    private $locale;

    /**
     * @param string $locale
     */
    public function __construct($locale = null)
    {
        $this->locale = $locale;
    }

    // (...)
}

viernes, 31 de octubre de 2014

Javascript avanzado: objetos, clases y prototipos. Introducción

Javascript es un lenguaje muy completo y muy complejo de aprender, sobre todo la parte referente a objetos, clases, herencia, prototipos, etc. Y esto es porque si bien Javascript no soporta de forma nativa esos conceptos de la orientación a objetos que tan claros están en otros lenguajes como Java, C++ o PHP, todos ellos pueden simularse con las funciones nativas del lenguaje.

Por ello voy a iniciar una serie de artículos sobre Javascript Avanzado.


Creación de un objeto simple

var stack = {
    elements: [],
    push: function(elem) {
        this.elements.push(elem);
    },
    pop: function() {
        var elem = this.elements.pop();
        return elem;
    }
};

En Javascript se puede usar la notación JSON para crear objetos sin tener que crear antes una clase. En el ejemplo creamos un objeto llamado stack que tiene un array de elementos y dos métodos: push() y pop(). La variable resultante es directamente un objeto. La mayoría de los lenguajes orientados a objeto no permiten crear objetos sin haber creado antes una clase, pero Javascript sí.

NOTA: Es innecesario crear un objeto stack en Javascript pues la clase Array ya tiene las funciones push() y pop() de forma nativa, pero me sirve para ilustrar el ejemplo.

stack.push(1);
stack.push('string');
stack.push({ id: 1, name: 'test' });
console.log(stack.pop());

Como se ve podemos usar directamente los métodos del objeto stack, pero en cambio no podemos crear nuevos objetos stack, ya que stack es un objeto y no una clase. Por lo tanto el siguiente código dará error:

var s = new stack;

Además en este tipo de objetos simples todos los métodos y miembros son públicos, lo cual quiere decir que podríamos acceder directamente a la lista de elementos elements, lo cual no suele ser correcto desde el punto de vista de la programación orientación a objeto.


Añadiendo miembros y métodos a un objeto simple

Javascript, a diferencia de otros lenguajes de programación orientados a objetos más tradicionales permite añadir nuevos miembros y métodos a un objeto simple tras su creación. Por ejemplo:

stack.top = function() {
    if(this.elements.length < 1) {
        return null;
    }
    else {
        return this.elements[this.elements.length - 1];
    }
};

Así añadimos el método top() al objeto stack que funcionará exactamente igual que si lo hubiéramos puesto desde el principio.


Creación de una clase

En Javascript no podemos crear una clase como tal, pero sí que podemos simularlo mediante una función. Sí, sí... has leído bien: una función. Esa función además funciona como constructor de la clase. Veamoslo con el mismo ejemplo:

var Stack = function() {
    var elements = [];
    this.push = function(elem) {
        elements.push(elem);
    },
    this.pop = function() {
        var elem = elements.pop();
        return elem;
    }
};

En el constructor de la clase Stack inicializamos un array de elementos y definimos las funciones push() y pop(). Ahora Stack es una clase, no un objeto y por lo tanto no podemos hacer lo siguiente:

Stack.push('elem1');
console.log(Stack.pop());

La forma correcta de hacerlo sería creando primero un objeto de clase Stack.

var st = new Stack;
st.push('elem1');
console.log(st.pop());

Además se da el caso de que ahora el miembro elements es privado lo cual significa que no puede ser accedido desde fuera de la clase.


Añadiendo miembros y métodos a una clase Javascript

Anteriormente vimos como añadir métodos a un objeto Javascript. Aquí también podemos añadir miembros y métodos directamente al objeto st, pero como la variable elements no es un miembro de la clase no podremos acceder a ella. Tendríamos que hacer que la variable elements fuera un miembro de la clase

var Stack = function() {
    this.elements = [];
    this.push = function(elem) {
        this.elements.push(elem);
    },
    this.pop = function() {
        return this.elements.pop();
    }
};

var st1 = new Stack;

st1.top = function() {
    if(this.elements.length < 1) {
        return null;
    }
    else {
        return this.elements[this.elements.length - 1];
    }
};

st1.push('e1');
console.log(st1.top());

Hemos añadido el método top() al objeto st que funcionará como si se hubiera añadido en la definición de la clase (función constructora). Sin embargo ese método es exclusivo del objeto st y no estará disponible para otros objetos Stack. ¿Y podemos añadir un método a una clase? Sí; a través del prototipo:

Stack.prototype.top = function(){
    if(this.elements.length < 1) {
        return null;
    }
    else {
        return this.elements[this.elements.length - 1];
    }
};

Ahora tanto st1 como cualquier otro objeto de clase Stack creado con posterioridad tendrán top() entre sus métodos.


Herencia de clases en Javascript

El concepto de la herencia en Javascript también es extraño si estas acostumbrado a otros lenguajes orientados a objeto. Al no existir clases como tales tampoco hay palabras clave como extends o implements. La herencia se hace asignando el prototipo de una función (clase) a otra. Pero la explicación detallada la vamos a dejar para otro artículo.


Referencias

miércoles, 22 de octubre de 2014

Más sobre Composer

El otro día os hablaba de Composer el gestor de dependencias para proyectos en PHP que permite incorporar a nuestros proyecto en PHP multitud de librerías, gestionando sus dependencias de forma magistral. Pues hoy he encontrado el artículo Composer, gestor de dependencias para PHP que amplía la información que yo mismo puse aquí. Os recomiendo su lectura.

Actualización (23/10/2014): Los chicos de desarrolloweb.com han publicado hoy una segunda parte del artículo de Composer llamada Cómo Instalar Composer, donde se detallan las distintas formas de instalar Composer en los más populares sitemas poerativos: Windows, Linux, Max OSX, ...

jueves, 16 de octubre de 2014

Función javascript para formatear un número de teléfono

El título de este artículo lo dice todo: Función javascript para formatear un número de teléfono. Así pues ahí va:

String.prototype.formatPhone = function(sep) {

    if(typeof sep == 'undefined') {
        sep = ' ';
    }

    var num = this.replace(/[^\d\+]/g, '');
    var len = num.length;

    if(len < 7) {
        return num;
    }
    else if(len < 10) {
        return num.replace(
            /(\d{1,3})(\d{3})(\d{3})/,
            '$1' + sep + '$2' + sep + '$3'
        );
    }
    else {
        return num.replace(
            /(\d+)(\d{3})(\d{3})(\d{3})/,
            '$1' + sep + '$2' + sep + '$3' + sep + '$4'
        );
    }
};

Y para usarlo...

    var phone = '[+34] 93 6665544'.formatPhone(' ');
    document.write(phone);

Resultado: +34 936 665 544.

lunes, 13 de octubre de 2014

Manual de buenas prácticas en Symfony2

Me acabo de enterar a través del fabuloso blog Symfony.es de Javier Eguiluz de la presentación del manual oficial de buenas prácticas para desarrollar aplicaciones en Symfony2. Si estás interesado puedes descargarlo en formato PDF en inglés o en español, aunque el propio Javier advierte que el contenido cambiará en los próximos días pues por ahora sólo se ha publicado una versión preliminar. También puedes consultar on-line el manual en Español.

Se trata de una serie de reglas que configuran un conjunto de buenas prácticas que recomiendan desde SensioLabs y que han sido aprobadas por el propio Fabien Potencier. Puedes estar de acuerdo o no con esta guía por lo que si eres desarrollador experto no es necesario que las sigas. Tampoco es obligatorio modificar un proyecto existente para seguirlas. Sin embargo me parece una gran ayuda especialmente para principiantes y para proyectos nuevos. Personalmente no estoy totalmente de acuerdo con todas pero me parece muy interesante especialmente las recomendaciones sobre como crear el bundle de aplicación, y donde poner los recursos como las vistas o las traducciones.