Prestashop – Análisis técnico

Esta historia empieza porque llevo unos días intentado montar una API pública en Ulabox, que a la larga servirá para servir la web, comunicarse con el backoffice, aplicaciones de Iphone, Android, etc…

La verdad es que Symfony2 me simplifica mucho la vida, pero nuestra base de datos actual sigue estando basada en Prestashop y aún hay mucha acción de Modelos que sigue funcionando con las funciones de esta plataforma y la API tiene que usar estos métodos para ser coherente con el sistema actual. Y la verdad es que Prestashop es un absoluto desastre a nivel programación y arquitectura técnica.

Dies all around

Estamos en 2011. Pero el mundillo PHP todavía arrastra miserias de hace 7 años, cuando no había PHP5, no había excepciones y lo único que se podía hacer era sobreescribir la función trigger_error o hacer dies para terminar nuestros scripts ante algún error. Eso valía en aquellos tiempos donde las páginas web eran un simple catálogo, un área de noticias y la cutre zona de administración, pero actualmente hacer dies ante un error de BBDD es un suicidio.

Y algunos diréis, pero y por qué? Si WordPress, Drupal, PHPBB y muchos libros de PHP avanzado dicen que esa es la manera correcta! Pues bien, ese es el gran mal de la comunidad PHP. Mucha gente aprende a programar webs en PHP cogiendo el código de estas plataformas que están en todas partes o leyendo algún libro de apoyo. Y todo esto está mal! Aún hay libros de PHP5.3 que rezan:

<?php
 if(!$db = @mysql_connect('localhost', 'root', ''))
   die('Error conectando a BBDD');
?>

Esto funciona correctamente, pero cuando tenemos todo un Prestashop, esto está en las profundidades del ObjectModel.php, al cual se llama desde todas partes y nuestro cliente, que quiere que gastar un dineral en nuestro gran e-commerce, verá por pantalla este fantástico error que tan poca confianza da al dar un número de VISA.

No solo eso, un die da un HTTP Status: 200 OK. Vamos que para Google, el nuevo contenido de nuestro catálogo de productos es este texto y así nos indexará mientras no se levante la BBDD.

Es muchísimo mejor ante este tipo de errores hacer un throw new Exception(‘Error BBDD’, 500); y en nuestro bootstrap recoger estos errores (400, 403, 500, etc…) y lanzar el header correspondiente para que Google no lo interprete como un 200. Otra cosa que me gusta hacer es que ante un error 500, que se suele asociar a sistema, es una buena práctica grabar en logs y/o enviar un mail al administrador del sistema, informando de lo que ha pasado y en qué condiciones.

Quedaría algo así:

<?php
// En el ObjectModel.php o Mysql.php (y lo mismo en las querys, etc...)
 if(!$db = @mysql_connect('localhost', 'root', ''))
   throw new Exception('Error conectando a BBDD', 500);
 
// Y el bootstrap, algo como
try {
  // Aquí irían el autoload, el bootstrapping, 
  // la carga de clases y el proceso MVC
} catch(Exception $ex) {
 
    switch ($ex->getCode()) {
        case 403:
            header('HTTP/1.0 403 Forbidden');
            echo '<h2>Access denied</h2>';
            break;
        case 404:
            header('HTTP/1.0 404 Not Found');
            // Aquí podríamos displayar una de esas páginas molonas de 404
            // De hecho esto se hace en Prestashop en el archivo 404.php
            break;
        case 400:
            header('HTTP/1.0 400 Bad Request');
            // Aquí ya depende... normalmente esto son parámetros mal enviados pero puede ser un
            // intento de SQL Injection, XSS, ... podéis enviar un mail al admin con el contenido
            // de $_SERVER, $_POST y $_GET por si las moscas
            break;
        case 500:
            header('HTTP/1.1 500 Internal Server Error');
            // Esto puede ser un error motivado por muchas causas, conveniente avisar de alguna manera
            // como comento en el punto anterior
            break;
        default:
            header('HTTP/1.1 500 Internal Server Error');
            // Como lo anterior
            break;
    }
}
 
?>

Uso de variables global

Con lo poco que cuesta hacer un objeto con variables de sistema y tenerlo todo ahí controlado… pues no global $errors que me traigo la variable y ale… a funcionar! Ojalá algún día se considere la instrucción global algo DEPRECATED

¿Transacciones?

El engine por defecto al instalar Prestashop con MySQL es InnoDB. Y el encoding UTF-8. Algo hemos avanzado respecto a épocas más oscuras. Pero claro, tenemos InnoDB y no usamos las transacciones! Ni se hace START TRANSACTION, ni COMMIT / ROLLBACK… que es un e-commerce! Que mueve dinero!

Y si peta la vuelta de Sermepa o Paypal a medio proceso? El cliente ha pagado pero no nos hemos enterado! Y se generan pedidos fantasma y este tipo de cosas tan chulas que hacen tener que cuadrar a mano los pagos con las múltiples plataformas de pago.

Validate

La idea de tener una clase estática para las validaciones, en sí no es mala, pero hay muchas expresiones regulares incorrectas o cuanto menos, no 100% rigurosas con las Specs. Además, desde PHP 5.2 existe filter_var que nos soporta la mayoría de cosas que se comprueban a mano. Tambén tenemos las funciones ctype_* para muchas cosas… pues no, expresion regular a mano, y encima no del todo fina (por ejemplo la de los mails)

Acoplamiento total de Smarty

Smarty2 ha servido muy bien a la comunidad desde hace muchos años. Pero se ha hecho mayor. Hay muchos engines de templating nuevos, mucho mejores y más rápidos (Twig, Smarty3). No es que sea muy grave y seguro que con un poco de tunning se puede adaptar. Bien es cierto que si quieres dar una solución cerrada hay que escoger uno y Smarty v2 sigue siendo el más usado.

Todo es public en los objetos

Esto puede ser cómodo, pero desde el punto de vista de la programación orientada a objetos, solo debe ser público aquello que sea necesario… y el resto funciones protected/private solo accedidas desde donde toca. Se usan clases, sí, pero muy a lo PHP4.

Y podríamos seguir y seguir…

Ideas finales

Hay quien dice que criticar a Prestashop es solo una opinión. Hay quien dice que todo esto son detalles. Y bien es cierto que hay cosas mucho más graves que otras.

Pero para mí es una vergüenza que un e-commerce no use transacciones y control de errores. Una cosa es un sistema de foros, un blog personal… pero una tienda, que mueve dinero, donde la gente pone sus visas y sus ahorros debe estar bien hecha. Por lo menos el sistema de pagos, control de stocks, etc… y esto sin transacciones y con dies sencillamente no es así.

Como punto positivo, es cierto que Prestashop te lo descargas y con un poco de tunning que te puede hacer cualquier empresilla puedes tener una tienda bastante digna. Y si es solo un añadido a una tienda física, o no vas a tener nunca más de 10 pedidos al día, etc… puede valer ya que no vas a invertir 10mil euros en construir algo mínimamente decente.

También es cierto que si eres una Startup, necesitas inversores. Y si necesitas inversores, deben creer en el proyecto. Y para creer, tienes que poder vender, mientras no puedes vender no eres más que humo. Por tanto, no es una mala solución arrancar con un Prestashop tuneadito mientras buscas inversión, y empiezas a hacer la plataforma de verdad.

Pero si la tienda crece, tienes un problema. De escalabilidad, de transaccionalidad y de control de tus datos. Y en ese momento tienes una deuda técnica muy grande ya que no es fácil huir de Prestashop a algo bien hecho.

Mucha gente se dedica a tunear estas plataformas cambiando los CSS, haciendo algún modulito y todo va bien, son expertos en maquillar Prestashop. Pero nadie se mira las tripas, que es donde está realmente el negocio, y ahí es donde Prestashop y todas estas plataformas prefabricadas son un desastre.

You may also like...

7 Responses

  1. Cristian Martín says:

    Totalmente de acuerdo. Antes de ponerme con symfomy perdí seis meses tuneando drupal. Acabé viendo lo mismo que tú.

  2. Ricard, ante todo, gracias por el análisis tan riguroso que has hecho sobre Prestashop. La verdad, que tras leerlo, es dificil estar en desacuerdo con lo que dices. Si me gustaría, no obstante, hacer algunos comentarios, ademas de pedir perdón por mi “ladrillo”.

    Dies all around
    Estoy de acuerdo en que a estas alturas, usar die() puede parecer antidiluviano y poco acertado, si bien, en muchas ocasiones es quizás una forma de evitar embarrar mucho el código, todos sabemos que los try-catch aunque muy útiles, usados repetidamente a lo largo de todo el código, puede llegar a convertir el código en algo mas complicado de leer para el programador. No es una excusa, pero quiero pensar que lo han hecho por esa razón.

    Bueno, eso es al menos lo primero que se me vino a la cabeza, hasta que ví la solución que propones: poner el bloque try-catch en el bootstrap y usar los throws en sus respectivas clases hijas a ObjectModel. Genial solución. Deberían implementarla.

    Por comparar, la alternativa mas similar a Prestashop, OpenCart, usa exit()

    Uso de variables global
    Totalmente de acuerdo, como bien dices, global debería estar DEPRECATED. Un Singleton conteniendo las variables “globales” de la aplicación sería a mi parecer, una solución mas elegante y acorde con la POO.

    Acoplamiento total de Smarty
    Aquí, te tengo que decir, que desde la versión 1.4, Prestashop incorpora la opción de usar Smarty3 en lugar de Smarty2. De hecho, han anunciado que en la próxima versión, supongo que en la 1.5, solo estará disponible Smarty3.

    ¿Transacciones?
    El que Prestashop en sus últimas versiones permita hacer una instalación con InnoDB me hace pensar que tienen el uso de transacciones en su hoja de ruta. No obstante, por norma general, Presatshop está concebida principalmente para ser desplegada en servidores compartidos, siendo una solución barata para tener un e-commerce, por experiencia, se que MyISAM tiene un mejor rendimiento en cuanto a velocidad, que InnoDB, al menos con las configuraciones por defecto que puedes encontrar en los hostings compartidos. Otro cantar sería un servidor dedicado donde si que puedes optimizar la configuración de tu base de datos InnoDB de MySQL.

    Todo es public en los objetos
    Totalmente de acuerdo, no tiene sentido y va en contra de la encapsulación y por tanto del sentido final de la POO. Si bien, puedo sospechar a qué se debe, no es la primera ocasión que un programador me comenta que lo hace así (todas las propiedades públicas) porque usan NetBeans, por ejemplo, y cuando están desarrollando, como tengan las propiedades privadas, el NetBeans no le autocompleta tras poner this->
    Quiero pensar que es por eso, aunque no es razón para justificarlo.

    Conclusión
    De acuerdo contigo en todo, como decía me parece un análisis muy acertado y riguroso. Si bien, tenemos que tener en cuenta, a quién se dirige Prestashop, pequeños comerciantes que quieren una herramienta barata y con la que puedan a empezar a vender rápido, nada de soluciones a medida, y hoy por hoy, de entre todas estas herramientas e-commerce, creo que Prestashop es la que mejor desempeña esa función.

    Es una aplicación relativamente nueva, y estoy seguro que todo lo que comentas, son puntos a ir resolviendo, no hay mas que ver las primeras versiones que no tenían ni siquiera el MVC y han ido implementándolo de una forma bastante eficaz.

    ¡Genial tu post Ricard! Ojalá se pudiera encontrar mas información técnica de PrestaShop como esta.

  3. Chema says:

    No te has mirado WordPress? xD

    Lo que no estoy de acuerdo es en el smarty Twig y todos estos sistemas de templates.

    PHP es un sistema de templates! para que reinventar la rueda…que manías…..aaaaaaaaaaaaarrrrrrrrrrrrrggg es que me enerva lo siento xD

    Lo del die() es una guarrada como otras muchas que se hacen cuando se desarrolla software (tanto libre como privado se va saco y no al detalle). No conozco prestashop se que es muy grande y ya podrían arreglarlo joder xD pero osties que es gratis! y fijo que ayuda a muchisima gente!

    Yo los que critican Open Classifieds (yo a lo mio) de esto les digo: Hazlo tu mejor y gratis! (eso es lo que hago ahora mismo por que yo soy de los que se quejan Juas)

    Ánimos con el prestashop, yo estoy en una mucho peor que prestashop te lo garantizo xD y si quieres te invito a verlo un día 😛

    saludos ulaboxero!

  4. Ricard Clau says:

    @José, sobre lo que comentas…
    No entiendo el problema que dices con Netbeans, llevo usándolo hace varios años y siempre me autocompleta bien public, private, static y namespaces con 5.3.
    Por otro lado, el try catch global no es solución mía, la mayoría de frameworks son así! pero como bien dices la gente no lo entiende y empieza a poner try / catchs como locos que no sirven para nada
    En cuanto a MyISAM, es cierto que es más rápido pero los bloqueos de tabla son de toda la tabla, no de una fila como en InnoDB y cuando hay muchas filas, es relativamente fácil que se corrompan las tablas. De nuevo, para cosas pequeñas bien, para cosas serias, InnoDB.
    Desconocía que en 1.4 se puede poner Smarty3, en mi empresa la base es 1.3 y no me fijé en detalle cuando me descargué la última versión para hacer el artículo!

    @chema PHP nació como un sistema de templating pero por ejemplo para escapar una variable hay que hacer echo htmlspecialchars($var, ENT_QUOTES, ‘UTF-8’) mientras que con twig, haces eso con {{ var | e }}. Por otro lado, usar sistema de templating te obliga a seguir la separación entre modelo, vista y controlador. Smarty2 ha quedado desfasado pero Twig es la caña y va muy rápido!
    Ánimos en tumanitas también, el legacy es muy complicado de arreglar!

  5. juanfrasr says:

    Ricard no me te pares a mirar phpbb3 que te va a dar un chungo xd.

    Estas herramientas se crean hace mil y no evolucionan correctamente..

    Suerte

  6. David says:

    Gracias por detallar un poco acerca de este asunto: odio las descripciones tan méramente diáfanas q dan a entender con sencillez o que la herramienta es una maravilla o es un desastre… Actualmente trato en la empresa con el absurdo de la implantación de un CRM como vtiger, que tenerlo lo tiene todo, pero es un ‘cacao maravillao’ fantabulástico. Me quedé muy atrapado cuando comencé a revisarlo superficialmente y descubrí las no se si son 140 tablas, y empeoró cuando comencé a trazar por primera vez un camino para realizar unos cambios… a un entorno basado en popups bastante pobre e incluso ridículo en muchos sentidos… A veces llega el momento de migrar de una rueda de molino a una rueda de automovil , ya que ambas ruedas ofrecen diferentes prestaciones. En consecuencia, pasaré a considerar esa frase como un tópico, ya que no la comparto en la mayoría de casos. Un sistema a medida correctamente planificado es siempre mucho más eficaz y usable que una rueda del montón y del calibre equivocado, en la que apenas se distingue entre la cámara y el parche. Econtrar la inpiración en aplicaciones antiguas y en consecuencia realizar entornos similares es entonces rediseñar la rueda, NO rehacerla, pq cada rueda es muy distinta a las demás, y responde de forma totalmente diferente, hasta q ‘se gasta’ (deja de cubrir las necesidades) y hay q meterle mano, perdiendo todo el tiempo, dinero y entereza técnica que creíamos haber ahorrado: ESO es rehacer la rueda en realidad, a mi modesto entender. Para una startUp… si pretendes ofrecer algo novedoso; que logramos usando una rueda enorme llena de trampillas desatendidas al uso y con un ‘caracter’ complicado de optimizar…

  1. 04/09/2011

    […] Prestashop. Análisis técnico. Lo verdaderamente importante, es que dice claramente y a la cara qué supone esa manera de programar php metiendo die() por todas partes… ¡una guarrería! […]