Crear múltiples shortcodes con una sola función: 3 ejemplos de asesinos
Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)
La potente API Shortcode nos permite crear "snippets" e incluir contenido especial (como funciones PHP o código HTML complejo) en nuestras entradas. Es extremadamente habitual construir funciones separadas para cada shortcode, pero ¿es realmente necesario? En este artículo vamos a ver cómo podemos utilizar más de un shortcode mediante la construcción de una sola función.
En defensa de los shortcodes
Las APIs hacen que WordPress sea uno de los sistemas de gestión de contenido más flexible entre los existentes. Ellas son la razón por la que hay decenas de miles de plugins y temas a nuestra disposición: La enorme comunidad de WordPress es capaz de hacer que WordPress haga saltos mortales y volteretas, gracias sus APIs.
Entre estas APIs, mi favorita es la API Shortcode. Su lógica y validez están siendo cuestionadas, pero creo firmemente que el uso de shortcodes en WordPress tiene una fácil curva de aprendizaje y una vez que se aprenden esas pocas sencillas reglas sobre parámetros y etiquetas de apertura y cierre, hasta los usuarios principiantes pueden disfrutar del uso de los shortcodes. Correcto, no es WYSIWYG pero un novato en WordPress puede tenerlo más difícil a la hora de limpiar el desorden en el caso de que hayan hecho algo mal en un editor WYSIWYG y hayan arruinado el HTML. Es más sencillo comprobar que un shortcode no funciona, eliminarlo y volver a escribirlo.
Pero, por supuesto, esto es sólo una opinión propia. Volvamos al tema: ¡Vamos a construir varios shortcodes con una sola función!
El beneficio de esta técnica
Realmente no es necesario argumentar el beneficio de este método, considera este ejemplo ridículamente largo:
1 |
<?php
|
2 |
function one_half_sc( $atts, $content = null, $tag ) { |
3 |
extract( shortcode_atts( array( |
4 |
// extra classes
|
5 |
'class' => '', |
6 |
'last' => '' |
7 |
), $atts ) ); |
8 |
if ( $class != '' ) |
9 |
$class = ' ' . $class; |
10 |
if ( $last = 'yes' ) |
11 |
$last_class = ' last'; |
12 |
return '<div class="one_half' . $last_class . $class . '">' . do_shortcode( $content ) . '</div>'; |
13 |
}
|
14 |
add_shortcode( 'one_half', 'one_half_sc' ); |
15 |
|
16 |
function one_third_sc( $atts, $content = null, $tag ) { |
17 |
extract( shortcode_atts( array( |
18 |
// extra classes
|
19 |
'class' => '', |
20 |
'last' => '' |
21 |
), $atts ) ); |
22 |
if ( $class != '' ) |
23 |
$class = ' ' . $class; |
24 |
if ( $last = 'yes' ) |
25 |
$last_class = ' last'; |
26 |
return '<div class="one_third' . $last_class . $class . '">' . do_shortcode( $content ) . '</div>'; |
27 |
}
|
28 |
add_shortcode( 'one_third', 'one_third_sc' ); |
29 |
|
30 |
function one_quarter_sc( $atts, $content = null, $tag ) { |
31 |
extract( shortcode_atts( array( |
32 |
// extra classes
|
33 |
'class' => '', |
34 |
'last' => '' |
35 |
), $atts ) ); |
36 |
if ( $class != '' ) |
37 |
$class = ' ' . $class; |
38 |
if ( $last = 'yes' ) |
39 |
$last_class = ' last'; |
40 |
return '<div class="one_quarter' . $last_class . $class . '">' . do_shortcode( $content ) . '</div>'; |
41 |
}
|
42 |
add_shortcode( 'one_quarter', 'one_quarter_sc' ); |
43 |
|
44 |
function two_thirds_sc( $atts, $content = null, $tag ) { |
45 |
extract( shortcode_atts( array( |
46 |
// extra classes
|
47 |
'class' => '', |
48 |
'last' => '' |
49 |
), $atts ) ); |
50 |
if( $class != '' ) |
51 |
$class = ' ' . $class; |
52 |
if( $last = 'yes' ) |
53 |
$last_class = ' last'; |
54 |
return '<div class="two_thirds' . $last_class . $class . '">' . do_shortcode( $content ) . '</div>'; |
55 |
}
|
56 |
add_shortcode( 'two_thirds', 'two_thirds_sc' ); |
57 |
|
58 |
function three_quarters_sc( $atts, $content = null, $tag ) { |
59 |
extract( shortcode_atts( array( |
60 |
// extra classes
|
61 |
'class' => '', |
62 |
'last' => '' |
63 |
), $atts ) ); |
64 |
if ( $class != '' ) |
65 |
$class = ' ' . $class; |
66 |
if ( $last = 'yes' ) |
67 |
$last_class = ' last'; |
68 |
return '<div class="three_quarters' . $last_class . $class . '">' . do_shortcode( $content ) . '</div>'; |
69 |
}
|
70 |
add_shortcode( 'three_quarters', 'three_quarters_sc' ); |
71 |
?>
|
El mismo código (php y HTML) se utiliza una y otra vez en cada función, a excepción de las diferentes clases CSS. Además, los atributos de cada función también son los mismos en todas. Es difícil de leer. Ahora que lo pensamos, si alguna vez tuviéramos que cambiar una característica de estos divs de columna, tendríamos que cambiar las mismas partes en todas las funciones.
¿Qué pasaría si hubiera una variable para obtener la "etiqueta" del shortcode? No es tan sorprendente que la variable se llame $tag y podría utilizarse dentro de nuestras funciones. Esta etiqueta permite comprobar a nuestras funciones la etiqueta del shortcode y comportarse de acuerdo a ella.
Piensa en el ejemplo anterior: Si existe más de una función que proporciona casi la misma funcionalidad, sería lógico (y bastante genial) tener una función para que nuestros shortcodes la usen.
Se me han ocurrido tres buenos ejemplos sobre cómo podemos usar esta técnica. Si se te ocurren más casos de uso mientras lees el artículo, ¡me encantaría que compartieses tus pensamientos con todos los demás en la sección de comentarios que viene a continuación!
Ejemplo 1 Vídeo incrustado
En una de mis primeras publicaciones en Tuts+, expliqué cómo usar un shortcode para incrustar vídeos procedentes de distintas plataformas de vídeo como YouTube, Vimeo o Dailymotion. El código tenía el siguiente aspecto:
1 |
<?php
|
2 |
function vid_sc( $atts, $content = null ) { |
3 |
extract( |
4 |
shortcode_atts( array( |
5 |
'site' => 'youtube', |
6 |
'id' => '', |
7 |
'w' => '600', |
8 |
'h' => '370' |
9 |
), $atts ) |
10 |
);
|
11 |
if ( $site == "youtube" ) { $src = 'http://www.youtube-nocookie.com/embed/' . $id; } |
12 |
else if ( $site == "vimeo" ) { $src = 'http://player.vimeo.com/video/' . $id; } |
13 |
else if ( $site == "dailymotion" ) { $src = 'http://www.dailymotion.com/embed/video/' . $id; } |
14 |
else if ( $site == "yahoo" ) { $src = 'http://d.yimg.com/nl/vyc/site/player.html#vid=' . $id; } |
15 |
else if ( $site == "bliptv" ) { $src = 'http://a.blip.tv/scripts/shoggplayer.html#file=http://blip.tv/rss/flash/' . $id; } |
16 |
else if ( $site == "veoh" ) { $src = 'http://www.veoh.com/static/swf/veoh/SPL.swf?videoAutoPlay=0&permalinkId=' . $id; } |
17 |
else if ( $site == "viddler" ) { $src = 'http://www.viddler.com/simple/' . $id; } |
18 |
if ( $id != '' ) { |
19 |
return '<iframe width="' . $w . '" height="' . $h . '" src="' . $src . '" class="vid iframe-' . $site . '"></iframe>'; |
20 |
}
|
21 |
}
|
22 |
add_shortcode( 'vid', 'vid_sc' ); |
23 |
?>
|
Aunque continúa siendo una práctica que no está tan mal (excepto las 6 instrucciones else if), ahora podemos usar un atributo menos ('site') y crear shortcodes independientes, como este:
1 |
<?php
|
2 |
// Video embed shortcodes
|
3 |
function wptuts_embed_sc( $atts, $content = null, $tag ) { |
4 |
extract( shortcode_atts( array( |
5 |
'id' => '', |
6 |
'w' => '600', |
7 |
'h' => '370' |
8 |
), $atts ) ); |
9 |
switch( $tag ) { |
10 |
case "youtube": |
11 |
$src = 'http://www.youtube-nocookie.com/embed/'; |
12 |
break; |
13 |
case "vimeo": |
14 |
$src = 'http://player.vimeo.com/video/'; |
15 |
break; |
16 |
case "viddler": |
17 |
$src = 'http://www.viddler.com/simple/'; |
18 |
break; |
19 |
case "dailymotion": |
20 |
$src = 'http://www.dailymotion.com/embed/video/'; |
21 |
break; |
22 |
}
|
23 |
if ( $id != '' ) |
24 |
return '<iframe width="' . $w . '" height="' . $h . '" src="' . $src . $id . '" class="iframevideo"></iframe>'; |
25 |
return; |
26 |
}
|
27 |
add_shortcode( 'youtube', 'wptuts_embed_sc' ); |
28 |
add_shortcode( 'vimeo', 'wptuts_embed_sc' ); |
29 |
add_shortcode( 'viddler', 'wptuts_embed_sc' ); |
30 |
add_shortcode( 'dailymotion', 'wptuts_embed_sc' ); |
31 |
?>
|
¿Ves lo que hicimos? Proporcionamos un parámetro $tag para nuestra función en la primera línea (para reemplazar el atributo "site") y usamos una instrucción condicional switch para conseguir un código mejor y más limpio. El resultado de las dos funciones será el mismo, a excepción de que ahora puede utilizarse [youtube id"..."] en lugar de [vid site="youtube" id="..."].
(No utilicé algunos de las plataformas de vídeo en la segunda función. Si necesitas añadir más plataformas, puedes agregar tantos "case" como desees.)
Ejemplo 2 divs de columna
Ah, columnas... son la parte más importante de una cuadrícula CSS, y hacen que sea muy fácil lograr que tu sitio web sea más adaptable, si admiten técnicas de diseño responsivo. Puedes verlas en casi todos los temas de WordPress disponibles en ThemeForest y usan shortcodes... con una práctica similar a nuestro "ejemplo ridículamente largo" al principio de este tutorial.
Como puedes recordar, el código era casi el mismo en las 5 funciones de ese ejemplo. Por lo tanto, sería increíblemente fácil fusionarlos en una sola función y dejar que la variable $tag haga su magia:
1 |
<?php
|
2 |
// Column shortcodes
|
3 |
function wptuts_columns_sc( $atts, $content = null, $tag ) { |
4 |
extract( shortcode_atts( array( |
5 |
// extra classes
|
6 |
'class' => '' |
7 |
), $atts ) ); |
8 |
if ( $class != '' ) |
9 |
$class = ' ' . $class; |
10 |
$last = ''; |
11 |
// check the shortcode tag to add a "last" class
|
12 |
if ( strpos( $tag, '_last' ) !== false ) |
13 |
$tag = str_replace( '_last', ' last', $tag); |
14 |
$output = '<div class="' . $tag . $last . $class . '">' . do_shortcode( $content ) . '</div>'; |
15 |
return $output; |
16 |
}
|
17 |
add_shortcode( 'one_half', 'wptuts_columns_sc' ); |
18 |
add_shortcode( 'one_half_last', 'wptuts_columns_sc' ); |
19 |
add_shortcode( 'one_third', 'wptuts_columns_sc' ); |
20 |
add_shortcode( 'one_third_last', 'wptuts_columns_sc' ); |
21 |
add_shortcode( 'one_quarter', 'wptuts_columns_sc' ); |
22 |
add_shortcode( 'one_quarter_last', 'wptuts_columns_sc' ); |
23 |
add_shortcode( 'two_thirds', 'wptuts_columns_sc' ); |
24 |
add_shortcode( 'two_thirds_last', 'wptuts_columns_sc' ); |
25 |
add_shortcode( 'three_quarters', 'wptuts_columns_sc' ); |
26 |
add_shortcode( 'three_quarters_last', 'wptuts_columns_sc' ); |
27 |
?>
|
Bastante bueno, ¿verdad? ¡Ni siquiera necesitamos usar un switch!
Sin embargo, todavía duplicamos líneas mientras añadimos los shortcodes. ¿Te atreves a ir un paso más allá? Retira las líneas add_shortcode() para reemplazarlo por esto:
1 |
<?php
|
2 |
$tags = array( |
3 |
'one_half', |
4 |
'one_half_last', |
5 |
'one_third', |
6 |
'one_third_last', |
7 |
'one_quarter', |
8 |
'one_quarter_last', |
9 |
'two_thirds', |
10 |
'two_thirds_last', |
11 |
'three_quarters', |
12 |
'three_quarters_last', |
13 |
);
|
14 |
foreach( $tags as $tag ) { |
15 |
add_shortcode( $tag, 'wptuts_columns_sc' ); |
16 |
}
|
17 |
?>
|
Ahora tenemos un código aún más mantenible. Por ejemplo; si tuviéramos que cambiar el nombre de la función, ya no nos molestaríamos en cambiar cada línea.
Ejemplo 3 Listas de entradas
¿Has necesitado alguna vez enumerar algunos artículos antiguos (o futuros) en tus entradas? Claro que sí. Existen un montón de plugins que proporcionan shortcodes, pero la mayoría de ellos requieren que utilices toneladas de atributos que pueden resultar en alguna etiqueta fea y compleja como [posts cat="5,6" author="barisunver" status="private" postsperpage="4" and="so on"].
¿Qué tal si usamos nuestra querida $tag en su lugar? Vamos a intentarlo:
1 |
<?php
|
2 |
// Post list shortcodes
|
3 |
function wptuts_post_lists_sc( $atts, $content = null, $tag ) { |
4 |
global $post; |
5 |
$post_ID = $post->ID; |
6 |
$post_author = $post->post_author; |
7 |
extract( shortcode_atts( array( |
8 |
'number' => 5, |
9 |
'exclude_current' => 'yes', |
10 |
'orderby' => 'date' |
11 |
), $atts ) ); |
12 |
$args = ''; |
13 |
switch( $tag ) { |
14 |
case "latest_posts": |
15 |
// we don't need any arguments to retrieve latest posts :)
|
16 |
break; |
17 |
case "category_posts": |
18 |
$categories = get_the_category( $post_ID ); |
19 |
$first_category = $categories[0]->term_id; |
20 |
$args = 'cat=' . $first_category; |
21 |
break; |
22 |
case "author_posts": |
23 |
$args = 'author=' . $post_author; |
24 |
break; |
25 |
case "future_posts": |
26 |
$args = 'post_status=future'; |
27 |
break; |
28 |
}
|
29 |
$not_in = '&post__not_in[]=' . $post_ID; |
30 |
if ( $exclude_current == 'no' ) |
31 |
$not_in = ''; |
32 |
$get_posts = get_posts( $args . $not_in . '&posts_per_page=' . $number . '&orderby=' . $orderby ); |
33 |
$output = '<ul class="' . $tag . '">'; |
34 |
foreach ( $get_posts as $post ) { |
35 |
$output .= '<li><a href="' . get_permalink() . '" title="' . esc_attr( get_the_title() ) . '">' . get_the_title() . '</a></li>'; |
36 |
}
|
37 |
$output .= '</ul>'; |
38 |
wp_reset_query(); |
39 |
return $output; |
40 |
}
|
41 |
add_shortcode( 'latest_posts', 'wptuts_post_lists_sc' ); |
42 |
add_shortcode( 'category_posts', 'wptuts_post_lists_sc' ); |
43 |
add_shortcode( 'author_posts', 'wptuts_post_lists_sc' ); |
44 |
add_shortcode( 'future_posts', 'wptuts_post_lists_sc' ); |
45 |
?>
|
Como puedes ver, podemos deshacernos de 3 posibles atributos de shortcode: "cat", "author" y "post_status". Siempre puedes ampliar los cases y añadir nuevos shortcodes con esta función única, relativamente pequeña.
Resumiendo
Como fan de los shortcodes de WordPress, este descubrimiento de la variable $tag es algo emocionante para mí. Parece que este método tiene un enorme potencial en cuanto a casos de uso.
¿Qué opinas de esta técnica? ¡Publica tus comentarios a continuación y comparte tus ideas con nosotros!



