Wordpress orientado a objetos. Saca tu estúpida lógica de mis plantillas.

Hay dos cosas que siempre me han llamado poderosamente la atención de WordPress, una es el escaso uso que la mayoría de desarrolladores hacen de get_posts() a pesar de lo flexible y fácil de usar que es. La otra es como en WordPress usan objetos en su arquitectura para… bueno, para no usarlos.

WordPress implementa varios objetos como WP_Query o WP_Post, pero ¡sorpresa! Sólo son una colección de atributos públicos desprovistos de métodos. Podemos imaginarnos al señor WordPress con el corazón dividido entre hacer una buena arquitectura y mantenerla accesible, y nada es más accesible que dejar a los desarrolladores de templates acceder libremente a los atributos de un objeto y que se preocupen ellos de la lógica murmurando aquello de que… «Aquí todos somos mayorcitos».

La cuestión es que esto realmente facilita mucho el desarrollo en una primera fase ¿Necesitas la fecha de una publicación? Pues nada, echo $post->post_date; pide y se te dará, todo es felicidad.

O al menos lo sería si todos los atributos de un post llegaran siempre a la plantilla debidamente rellenados, dentro de los parámetros que esperamos, pulcros, alineados y disciplinados como colegiales japoneses… Pero ¿A quién no le ha explotado un template en la cara por asumir que «el usuario SIEMPRE rellenará la featured image» de un post? Esto es algo que debe pasar. Es como un bautismo en WordPress. Por supuesto, esto tiene solución, usar condicionales en la plantilla. Convirtiendo este código potencialmente suicida:


$feat_img = get_the_post_thumbnail_url( $post->ID );
echo ‘<img src="”’" />’;
 

En este otro, mucho más conservador y fiable:


$feat_img = get_the_post_thumbnail_url( $post-&gt;ID );
if ( !empty( $feat_img ) ) {
echo ‘<img src="”’" />’;
} else {
	echo ‘Aquí debería haber una foto detacada’;
}
 

Hay por lo menos dos cosas que están mal en esto último, sin tener en cuenta el tono pasivo-agresivo del mensaje de error.

En primer lugar estamos llevando lógica a la plantilla, que debería ser una vista. Si bien es cierto que es inevitable que esto ocurra en ocasiones, también lo es que todo esfuerzo dedicado a sacar lógica fuera de las plantillas es poco.

En segundo lugar, y esto puede parecer una cuestión filosófica ¿no es acaso la «featured image» de un post… bueno, parte del propio post? ¿No es tan suya como su fecha o su título? Por supuesto que lo es, pero WordPress no lo sirve como parte del post si no que requiere que use una función para pedir la imagen destacada del post. Hay una razón para ello, el post puede, o no, tener dicha imagen que es a su vez otro post (si, esto es así, desprovisto de cualquier glamur, en WordPress todo son posts).

Pero no es así como los profesores de EDAL de todas las facultades de informática del mundo nos enseñaron a usar los objetos, como si fueran structs de C++ con un nombre pomposo. Y dado que no parece que WordPress tenga intención de cambiar esto ¿Porqué no lo hacemos nosotros mismos? Y es a partir de este punto donde nos ponemos técnicos.

Creando nuestra primera clase

Crear nuevas clases e integrarlas en WordPress es tan sencillo como crear shortcodes o activar el editor de menús. Podríamos hacerlo directamente en el fichero functions.php de nuestro template, pero ya que nos vamos a poner papistas crearemos un fichero nuevo y lo incluiremos. Primero porque es más elegante (mucho más, donde irá a parar) y segundo porque, por definición, una clase debería estar siempre en un archivo para ella sola.

Así que creamos nuestro fichero, por ejemplo… post_basic.php y lo incluimos en nuestro functions.php


require_once ( TEMPLATEPATH . '/functions/classes/post_basic.php' );
 

Una vez en él creamos nuestra clase…


class post_basic {

private $ID = false;

function __construct( $post_id ) {
	$post = get_post( $post_id );
	$this->ID = $post->ID;
}

function get_ID() {
	return $this->ID;
}
}
 

De momento nuestra clase no es gran cosa, de hecho sólo tiene el atributo ID del post, pero tenemos ya el germen de una arquitectura mucho más robusta.

Para empezar nuestros atributos pasan a ser privados (nada de entrar a coger las cosas a tontas y a locas, nuestro objeto será el que las sirva a partir de ahora) con lo que desde la vista sólo podremos pedirlos a través de su función get.

Luego tenemos el constructor, en este «construiremos» (¡sorpresa!) el objeto en sí, o sea, lo instanciaremos para usarlo en la plantilla. Aquí podemos ver el primer cambio con respecto a la arquitectura «tu tira que casi seguro que está bien» de WordPress, ya que empezamos a hacer comprobaciones.

Primero le pedimos a WordPress un objeto WP_Post a partir de un ID (que es lo mismo que ya estaba ocurriendo hasta ahora ) pero en lugar de pasarlo a las bravas comprobamos que efectivamente no nos ha devuelto un false (o sea, que todo ha ido bien) y si es así, guardamos el ID del WP_Post en nuestro post_basic.

En, por ejemplo, nuestra plantilla del single.php instanciaremos el objeto


$post_basic = new post_basic( $post->ID );
 

Con lo que para mostrar el ID en la plantilla en lugar de pintar el atributo


$post->ID
 

usaremos una función que nos la pase


$post_basic->get_ID();
 

Y en este punto puede que nadie esté demasiado impresionado… Y con razón, el ID siempre debería estar ahí ¿No? O sea… Si no podemos asumir eso en un WordPress mejor recoger y poner una mercería. Pero sigamos añadiendo atributos, con sus métodos


class post_basic {

private $ID = false;
private $title = false;
private $publish_date = false;

function __construct( $post_id ) {
	$post = get_post( $post_id );
	$this->ID = $post->ID;
	$this->title = $post->post_title;
$this->publish_date = get_post_time( 'U', true, $post->ID );
}


function get_ID() {
	return $this->ID;
}

function get_title() {
	return $this->title;
}

function get_publish_date( $format = ‘U’ ) {
	return date( $format, $this->publish_date );
}
}
 

 

Y esto ya tiene otra pinta… y muchas nuevas posibilidades debido a que las funciones get, como funciones que son, admiten parámetros que modifiquen su comportamiento (esto es algo que jamás conseguiríamos de un atributo). En este ejemplo, pasamos un string de formato de la función date() de PHP para controlar el formato de salida de la fecha de publicación.

Así, para mostrar en el front esto:



<h1>Título del post</h1>
12 de marzo de 2017
Con la arquitectura de WordPress sería algo así:
<pre><code>
echo ‘

<h1>’ . $post-&gt;post_title . ‘</h1>
’; echo ‘

’ . get_post_time( 'j de F de Y', true, $post-&gt;ID ) . ‘

’;
 

Mientras que con nuestro objeto y sus métodos sería algo como:


$post_basic = new post_basic( $post->ID );
echo ‘

<h1>’ . $post_basic&gt;get_title() . ‘</h1>
’; echo ‘

’ . $post_basic-&gt;get_publish_date( 'j de F de Y’) . ‘

’;
 

Nuevamente sigue sin ser muy impresionante, pero si que tiene un aspecto mucho más estructurado… ya no llamamos a funciones aquí y allá sin relación, si no que pedimos a nuestro objeto que nos vaya entregando sus atributos. Pero demos un giro más y añadamos la featured image que ha provocado todo esto… Ha llegado el momento de subir el volumen al 11



class post_basic {

    private $ID = false;
    private $title = false;
    private $publish_date = false;
    private $feat_image = false;

    function __construct( $post_id ) {
    	$post = get_post( $post_id );
    	$this-&gt;ID = $post-&gt;ID;
    	$this-&gt;title = $post-&gt;post_title;
        $this-&gt;publish_date = get_post_time( 'U', true, $post-&gt;ID );
        $feat_img_id = get_post_thumbnail_id( $post_id );
        if ( $feat_img_id ) {
        	$this-&gt;feat_image = get_post_thumbnail_id( $post-&gt;ID );
        }
    }
    
    function get_ID() {
    	return $this-&gt;ID;
    }

    function get_title() {
    	return $this-&gt;title;
    }

    function get_publish_date( $format = ‘U’ ) {
    	return date( $format, $this-&gt;publish_date );
    }

    function get_feat_image_id() {
    	return $this-&gt;feat_image; 
    }

    function get_feat_image_url( ) {
    	if ( $this-&gt;get_feat_image_id() ) {
    		return wp_get_attachment_image_src( $this-&gt;get_feat_image_id() );
        } else {
        	return false;
        }
        return $response;
    }

    function get_image_html() {
    	if ( $this-&gt;get_feat_image_id() ) {
    	    return '<img src="' . $this-&gt;get_feat_image_id() . '" />';
        } else {
            return false;
        }
    }
}
 

Y esto, por fin, ya es algo útil. Debido a que los objetos nos permiten usar sus propios métodos dentro de ellos mismos, podemos crear varias funciones que devuelvan un atributo en diferentes fases. En este caso, como atributo hemos guardado sólo el ID de la imagen (dado que en WordPress todos son posts, todo tiene ID ).

Después crearemos una función que nos devuleva la URL a partir de ese ID, y finalmente una tercera que nos devuelva el HTML que queremos pintar a partir de dicha URL. Volviendo al caso anterior.

Para pintar esto (controlando los errores):


<img src="”my_feat_image.jpg”" />
<h1>Título del post</h1>
12 de marzo de 2017
 

Con la arquitectura de WordPress sería algo así


$feat_img = get_the_post_thumbnail_url( $post-&gt;ID );
if ( !empty( $feat_img ) ) {
echo ‘<img src="”’" />’;
}
echo ‘

<h1>’ . $post-&gt;post_title . ‘</h1>
’; echo ‘

’ . get_post_time( 'j de F de Y', true, $post-&gt;ID ) . ‘

’;
 

Mientras que nuestro objeto y sus métodos sería algo como


$post_basic = new post_basic( $post-&gt;ID );
echo $post_basic-&gt;get_image_html();
echo ‘

<h1>’ . $post_basic&gt;get_title() . ‘</h1>
’; echo ‘

’ . $post_basic-&gt;get_publish_date( 'j de F de Y’) . ‘

’;
 

Como podéis ver, no dejamos de comprobar que la imagen exista, esa lógica no puede desaparecer, pero ahora ya no está en nuestro template, sino que se encuentra en nuestro objeto. Esto tiene la ventaja de dejar un HTML más limpio, más fácil de leer y mantener.

Por otra parte, desplaza las lógicas a un solo punto. Cambiar el comportamiento cuando no haya imagen y servir una por defecto, por ejemplo, nos obligaría a revisar todos los puntos en que las pintamos, mientras que usando objetos solo tendríamos que preocuparnos de hacer el cambio en ese punto.

Y eso es todo de momento, este ha sido el primero de una serie de artículos sobre los objetos en que ahondaremos mucho más profundo. Por ahora, sólo hemos arañado la superficie ¡toma topicazo! De las posibilidades que nos ofrecen para modificar la arquitectura de WordPress y hacerla mucho más robusta, sostenible y lo más importante… ¡Con toda esa estúpida lógica lejos de nuestras plantillas!

Aritz Álvarez es desarrollador senior en el departamento de Frontend de Cloud District.

INFORMACIÓN IMPORTANTE SOBRE COOKIES

Este sitio web utiliza cookies propias y de analítica para mejorar tu experiencia. Algunas de estas cookies son imprescindibles para que el site funcione correctamente.
Puedes ver más información sobre las cookies en nuestra Política de privacidad.

Aceptar