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.
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
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. 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. Cuando leemos en los requisitos que el proyecto
debe programarse sobre Wordpress…
11. ¿De qué se compone
Wordpress?
• Plugins y Themes
• Filters y actions
• WP_Query y loop
• Custom post type y taxonomies
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
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. 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
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
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”
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. 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. 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. Request y ejecución
1. /category/animales = index.php?category=animales
2. new WP_Query( array( “category” => “animales”) );
3. theme/category.php
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”]
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();
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”);
50. Inyección de dependencias
Nos permite hacer más portable y desacoplado
nuestro código.
• Pimple
• Symfony Dependency Injection
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. 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.
54. 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
56. 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
57. 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(){
});
58. 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
59. Pluggable
• WordPress permite sobreescribir algunas
funciones internas desde nuestros plugins.
• Dichas funciones se denominan pluggables
60. 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” );
}
}
61. 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 );