O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Código mantenible, en Wordpress.

1.066 visualizações

Publicada em

Por diversas causas, nos podemos encontrar con el reto de desarrollar plataformas y servicios online que requieren escalabilidad pero que también estén basados Wordpress.

Más allá de instalar plugins o modificar themes desde el backoffice, requerimos trabajar con Wordpress como si fuese un framework tipo Symfony o Laravel, algo para lo que este CMS no está diseñado.

En esta charla veremos qué problemáticas tiene enfrentarse al reto de crear código mantenible con Wordpress, usando patrones como la inyección de dependencias, soluciones como composer y herramientas que estamos acostumbrados a encontrar no en una solución de CMS, sino en frameworks, más adecuados para esta tarea.

Publicada em: Tecnologia
  • Seja o primeiro a comentar

Código mantenible, en Wordpress.

  1. 1. Código mantenible, con WordPress Asier Marqués @asiermarques
  2. 2. De qué va esta charla Introducción a los conceptos básicos de desarrollo con WordPress Abrir perspectiva sobre buenas prácticas sobre este CMS Mostrar código mantenible, cercano al que crearíamos con Symfony2, Silex o Laravel
  3. 3. /me Asier Marqués simettric.com & 4visionshq.com linkedin.com/in/asier @asiermarques
  4. 4. El 23% de Internet utiliza WordPress.
  5. 5. • techcrunch.com • thenewyorker.com • BBC America • Time Inc • Fortune
  6. 6. • Google Ventures • The walking dead • The rolling stones
  7. 7. Beneficios • Es un CMS muy conocido, muchos usuarios ya saben utilizar su backoffice • Existe una gran cantidad de plugins • Existe una gran cantidad de themes • Un mercado amplio
  8. 8. Puntos negativos • Una base de desarrollo obsoleta • Gran cantidad de plugins que no tienen ningún tipo de requisito de calidad • Atado a un esquema de base de datos concreto • Para proyectos cuyo core de negocio se salga de contenido, puede quedarse corto sin un coste de mantenimiento elevado
  9. 9. Cuando leemos en los requisitos que el proyecto debe programarse sobre Wordpress…
  10. 10. Guarrindongadas!!!
  11. 11. ¿De qué se compone Wordpress? • Plugins y Themes • Filters y actions • WP_Query y loop • Custom post type y taxonomies
  12. 12. MultiSite • WordPress es multisite • Disponemos de funciones, actions y filters específicos para gestionar los blogs dentro de un network • Casi todas esas funciones son las originales del proyecto Wordpress Mu
  13. 13. http://codex.wordpress.org/WPMU_Functions wpmu_create_blog($domain, $path, $title, $user_id, $meta, $site_id)
  14. 14. Backoffice • Nos permite gestionar nuestro sitio y nuestro contenido • Es totalmente personalizable, podemos • Añadir secciones en el menú • Añadir columnas en las tablas de contenido • Añadir campos, y metaboxes, para usuarios, contenido y terms • Añadir campos y opciones a los menús dinámicos de themes
  15. 15. Post Types • Todo es un Post • Por defecto tenemos contenido de tipo post, page y attachment. • El contenido puede ser jerárquico • El contenido tiene un archivo • El contenido puede tener metainformación
  16. 16. Custom post type register_post_type( 'book', array( 'labels' => array(“name” => “Libros”), 'public' => true, 'rewrite' => array( 'slug' => 'books' ), 'has_archive' => true, 'hierarchical' => false, 'supports' => array( 'title', 'editor', 'thumbnail', 'comments' ) );
  17. 17. Custom post type $product = get_post( $product_id ); $product_color = get_post_meta( $product, “color”, true); $products = get_posts( array( “post_type” => “product” ) ); foreach( $products as $product ){ echo get_the_title( $product ); }
  18. 18. Taxonomies • Todas las taxonomias son terms • Por defecto tenemos los term “tag” y “category” • Los term pueden ser jerárquicos o no • Por defecto no hay soporte de metainformación
  19. 19. Custom taxonomy register_taxonomy( ‘author’, 'book', array( 'hierarchical' => false, 'labels' => array( “name”=> “Autor” ), 'show_admin_column' => true, 'update_count_callback' => '_update_post_term_count', 'rewrite' => array( 'slug' => ‘authors’ ), ));
  20. 20. Custom Taxonomy $terms = get_terms(“talla”, array(“order_by”=>”count”)); foreach( $terms as $term ){ echo $term->name; } $product_terms = wp_get_post_terms( $product, “talla” );
  21. 21. Obtener enlaces get_permalink($post); get_term_link($term, “color”); get_post_type_archive_link( “post_type” ) wp_get_attachment_url( $post->ID ); $src_array = wp_get_attachment_image_src($post->ID, “size”); $image_src = $src_array[0];
  22. 22. Plugins vs Themes • La responsabilidad principal de un theme es la de dotar de un diseño al sitio web • La responsabilidad de un plugin es la de dotar funcionalidad y personalización, sin acoplarse a un theme especifico • Un theme puede actuar adicionalmente como plugin • Los plugins pueden personalizar las funciones core de tipo “pluggables”
  23. 23. Themes
  24. 24. Los archivos más importantes en un theme • styles.css • index.php • header.php y footer.php • functions.php
  25. 25. index.php get_header(“key”); //header-key.php if ( have_posts() ) { while ( have_posts() ) { the_post(); //nuestro código } } get_footer(“key”); //footer-key.php
  26. 26. header.php <html> <head> <?php wp_head(); ?> </head> <body>
  27. 27. footer.php <?php wp_footer(); ?> </body> </html>
  28. 28. Template Hierarchy archive-producto.php -> archive.php -> index.php single-producto.php -> single.php -> index.php taxonomy-color.php -> taxonomy.php -> index.php search.php -> index.php 404.php -> index.php front-page -> index.php home.php -> index.php
  29. 29. http://codex.wordpress.org/Template_Hierarchy
  30. 30. Loop <?php if ( have_posts() ) { while ( have_posts() ) { the_post(); ?> <h2><?php the_title() ?></h2> <p><?php the_content() ?></p> <?php } }
  31. 31. En realidad es un WP_Query <?php global $wp_query; if ( $wp_query->have_posts() ) { while ( $wp_query->have_posts() ) { $post = $wp_query->the_post(); ?> <h2><?php echo get_the_title($post) ?></h2> <p><?php echo get_the_content($post) ?></p> <?php } }
  32. 32. Actions y Filters • Nos podemos suscribir a ellos para modificar y extender Wordpress • Los actions actúan como eventos a los que nos suscribimos para realizar una operación. • Los filters también son eventos, pero nos permiten manipular información o html del template.
  33. 33. Request y ejecución 1. Se recibe la petición HTTP 2. El sistema de routing hace el match de la ruta que coincida con la url de la petición 3. Se crea el objeto WP_Query y las query_vars 4. En base al WP_Query se localiza el template 5. Se retorna el resultado http://codex.wordpress.org/Plugin_API/Action_Reference
  34. 34. Request y ejecución 1. /category/animales = index.php?category=animales 2. new WP_Query( array( “category” => “animales”) ); 3. theme/category.php
  35. 35. Rutas personalizadas add_action('init', function() { add_rewrite_rule( ‘^tasks/([^/]*)/([^/]*)/?’, ’index.php?post_type=“task”&category=$matches[1]&custom=$matches[2]', ‘top' );        add_rewrite_tag('%custom%', '(([^/]*))'); });
  36. 36. Rutas personalizadas Al crear la WP_Query, se incluyen los anteriores parámetros: $wp_query->query_vars[“post_type”] $wp_query->query_vars[“category”] $wp_query->query_vars[“custom”]
  37. 37. Queries WP_Query $wp_query http://codex.wordpress.org/Class_Reference/WP_Query wpdb $wpdb http://codex.wordpress.org/Class_Reference/wpdb
  38. 38. $wp_query = new WP_Query(array( “post_type” => “producto”, “nombre_taxonomy” => “valor”, “posts_per_page” => 20, “meta_query” => array( “relation” => “OR”, array( “meta_key” => “color”, “meta_value” => “azul” ), array( “meta_key” => “precio”, “meta_value” => array(20, 200), “compare” => “BETWEEN”, “type” => numeric ) ) ));
  39. 39. $wp_query = new WP_Query(array( “post_type” => “producto”, “nombre_taxonomy” => “valor”, “posts_per_page” => 20, “meta_query” => array( “relation” => “OR”, array( “meta_key” => “color”, “meta_value” => “azul” ), array( “meta_key” => “precio”, “meta_value” => array(20, 200), “compare” => “BETWEEN”, “type” => numeric ) ) ));
  40. 40. WP_Query //obtenemos el SQL de la consulta $sql = $wp_query->request; //obtenemos los posts de resultados de la consulta $posts = $wp_query->get_posts();
  41. 41. WPDB $posts = $wpdb->get_results( “ SELECT * FROM $wpdb->posts WHERE post_status = ‘publish'" );
  42. 42. WPDB $wpdb->prepare( "SELECT * FROM table WHERE ID = %d", $id ); $wpdb->update( $table, $data_array, $where_array); $wpdb->delete( $table, $where_array );
  43. 43. Templates personalizadas add_filter( 'template_include', function ( $template ) { if ( is_page( get_option(“landing_page_id”) ) ) { $template = __DIR__ . “/../Templates/landing.php“; } return $template; }
  44. 44. function replaceQuery(WP_Query $wp_query){ if( get_option(“landing_page_id”) ){ //cambiamos el loop de la portada $wp_query = new WP_Query(array( “category” => 1 )); //evitamos un loop infinito remove_action(“replaceQuery”); } }; add_action(“pre_get_posts”, “replaceQuery”);
  45. 45. Ajax $.getJSON( ajaxurl, { action: “controller.action” }, function( data ){ });
  46. 46. Ajax: En el Backend add_action('wp_head',function() { ?> <script type="text/javascript"> var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>'; </script> <?php }); add_action( ‘wp_ajax_controller.action’, “callback”); add_action( 'wp_ajax_nopriv_controller.action’, “callback”);
  47. 47. Herramientas • Gestión de librerías: composer • Inyección de dependencias: Symfony o Pimple • Configuración: Yaml y Configuration Component • Assets: Assetic • Templates: Twig
  48. 48. Composer WordPress no ofrece gestión de librerías ni componentes por Composer Por suerte existe el proyecto wpackagist.org
  49. 49. Demo
  50. 50. Inyección de dependencias Nos permite hacer más portable y desacoplado nuestro código. • Pimple • Symfony Dependency Injection
  51. 51. Inyección de dependencias $container[“wp_query”] = function ($c) use ($wp_query) { return $wp_query; }; $container[“blog.repository”] = function ($c) { return new WPBlogRepository($c[“wp_query”]); }; $container[“blog.model”] = function(){ return new BlogModel( $c[“blog.repository”] ); }
  52. 52. Modelo Portable class BlogModel { private $_repository; function __construct(RepositoryInterface $adapter){ $this->_repository = $adapter; } function getPosts($page, $limit=20){ return $this->_repository->getPosts($page, $limit); } }
  53. 53. Assets • Wordpress nos permite registrar y encolar scripts (y css) gestionando sus dependencias • Al llamar al wp_head o wp_footer, los scripts y hojas de estilos se añaden de forma automática al html de la página
  54. 54. Assets wp_enqueue_script( ‘bootstrap', get_template_directory_uri() . '/assets/js/bootstrap.min.js', array('jquery'), '3.0.0', $in_footer = true );
  55. 55. Assetic • Assetic nos permite gestionar de forma más avanzada los assets, uniéndolos y optimizándolos para servirlos en la página. • Mediante el plugin WPAssetic podemos disponer de esta utilidad en nuestro sitio
  56. 56. WP Cron Al activar un plugin o theme, nos permite disparar eventos con una periodicidad concreta register_activation_hook( __FILE__, function() { wp_schedule_event( time(), 'hourly', ‘evento_cada_hora’ ); }); add_action( ‘evento_cada_hora', function(){ });
  57. 57. Rendimiento con Varnish • Varnish es un servicio de proxy-cache que permite servir el resultado del html desde memoria • Podemos actualizar e invalidar la caché de nuestro contenido de forma automática mediante el plugin wp varnish
  58. 58. Pluggable • WordPress permite sobreescribir algunas funciones internas desde nuestros plugins. • Dichas funciones se denominan pluggables
  59. 59. Pluggable Emails if ( !function_exists('wp_new_user_notification') ) { 
 function wp_new_user_notification( $user_id, $plaintext_pass = '' ) { wp_email( “to@example.com”, “asunto”, “cuerpo del mensaje” ); } }
  60. 60. Caché Wordpress tiene una cache clave-valor mediante un conjunto de funciones llamadas transients Utilizan de forma interna el objeto wp_object_cache set_transient( ‘datos_cacheados', $datos, 12 * HOUR_IN_SECONDS );
  61. 61. TDD WordPress test framework: https://github.com/nb/wordpress-tests.git WP Mock https://github.com/10up/wp_mock http://slides.com/jlopezmo/test-driven-development-in-wordpress
  62. 62. Gracias! ¿Preguntas? Asier Marqués @asiermarques asier@simettric.com

×