La función do_shortcode() recibe un string, una cadena de texto, y busca en ella todos los shortcodes registrados en WordPress y los ejecuta. Aunque es muy habitual ver como se usa en widgets y en themes, un desarrollador WordPress rara vez, muy rara vez, necesitará utilizar esta función.

Los shortcodes se deben entender como lo que son, placeholders (marcador de posición) para funciones PHP. Cada shortcode tiene una función asociada; allí dónde no se puede ejecutar PHP directamente, ponemos el shortcode. Posteriormente, a la hora de mostrar el contenido, se ejecuta la función asociada al shortcode y se muestra el output de la función en su lugar.

Por ejemplo, en el editor de un post no podemos ejecutar PHP, así que ponemos el shortcode y luego, cuándo se muestra el contenido, se buscan los shortcodes y se ejecutan las funciones asociadas correspondientes:

$content = get_the_content( 123 );
// Buscar y ejecutar los shortcodes en el contenido
echo do_shortcode( $content );

¿Pero que sentido tiene utilizar shortcodes en un script PHP como es un template? En principio, ninguno. Veamos un ejemplo.

Supongamos que tenemos este shortcode (tomado de esta pregunta, que viene muy al caso, de hecho escribo este post debido a esa pregunta):

// Register Shortcode
add_shortcode( "shorten", "shortcode_shorten_url" );

// Shortcode function
function shortcode_shorten_url( $atts, $content ) {
  return shorten_url( $content );
}

// Main Function
function shorten_url( $url ) {
  $siteurl ="http://go.example.com";

  $apikey = "8jkyA3e7xs1J";
  // You can get it from the user account

  if( $apikey && $siteurl ) {
    $short = @file_get_contents( "$siteurl/api?api=$apikey&url=" . strip_tags( trim( $url ) ) );
    $short = json_decode( $short, TRUE );
    if( ! $short["error"] ) {
      return $short["short"];
    }
  }

}

Ahora, el usuario que hizo la pregunta hacia esto:

echo do_shortcode('[shorten]http://ejemplo.com[/shorten]');

Vamos a ver si lo dejamos claro. Si un shortcode es un placeholder para un función PHP y podemos ejecutar PHP, ¿para que utilizamos un placeholder? Ejecutemos directamente la función:

echo shorten_url( 'http://ejemplo.com' );

Si miramos el código fuente de do_shortcode(), podemos ver que se hace un regex con TODOS los shortcodes disponibles, lo que puede llegar a ser banstante intenso. Si utilizamos el callback directamente nos ahorramos este regex, lo que es ya es buena razón para no utilizar sentencias del tipo do_shortcode( '[un_shortcode]' ) como se planteaba en este ejemplo.

Casos justificados

Hay algunos casos en los que utilizar do_shortcode() podría estar justificado, pero la verdad que hay que esforzarse mucho para justificar su uso directamente en un template.

En general, do_shortcode() se puede utilizar cuándo no sabes el contenido exacto de un string pero necesitas que se ejecuten los shortcodes si los hay. Por ejemplo, si se quiere añadir soporte para shortcodes en el Text Widget:

add_filter( 'widget_text', 'do_shortcode' );

Este caso no incluye, obviamente, cadenas de contenido fijo tipo do_shortcode( '[un_shortcode]' ).

El único caso que se me ocurre dónde el uso de do_shortcode( '[un_shortcode]' ) puede estar justificado es cuándo necesitas el output de un shortcode, sea cual sea, pero no puedes estar seguro de cual es su callback. Por ejemplo:

// Remove [gallery] shortcode and its callback from core
remove_shortcode( 'gallery', 'gallery_shortcode' );
// Add again [gallery] shortcode with a custom callback
add_shortcode( 'gallery', 'my_gallery_shortcode' );

Como ves, cualquiera puede eliminar un shortcode y redefinirlo con un callback diferente.

En este contexto el shortcode se puede entender no como un placeholder sino como una capa de abstracción sobre una funcionalidad. En este ejemplo la funcionalidad sería «gallery»; si necesitamos esta funcionalidad, y no el output específico de un callback, estaría justificado el uso de do_shortcode( '[gallery]' ).

Pero sería algo extremadamente raro. El shortcode [gallery] dispone del filtro post_gallery. Cualquiera que desee modificar el comportamiento de este shortcode debería utilizar ese filtro y no redefinir el shortcode, con lo que el uso directo del callback seguiría siendo seguro y seguiríamos ahorrándonos el regex innecesario del que hablábamos antes.

Por otro lado, cualquiera que programe un shortcode debería incluir un filtro para su output. De esta forma no se obligaría a nadie a tener que redefinir el shortcode si necesita modificar su comportamiento. Por ejemplo:

add_shortcode( 'cyb_shortcode', 'cyb_shortcode_callback' );
function cyb_shortcode_callback( $attr ) {

    $output = apply_filters( 'cyb_shortcode', '', $attr );

    if ( $output != '' ) {
        // Si el output del filtro no
        // es una cadena vacía, utilizarlo
        return $output;
    }

    // Si el output del filtro
    // es una cadena vacía, seguir
    $output = 'Lo que sea';

    return $output;

}

Pero claro, en la vida real ni todos los shortcodes cuentan con filtros ni todos los desarrolladores utilizan los filtros aunque estén disponibles.

Conclusión

El uso de do_shortcode() sólo está completamente justificado cuándo nos enfrentamos a stings de contenido desconocido que pueden contener shortcodes, lo que para mí queda fuera de un template y que en ningún caso es aplicable para cadenas fijas tipo do_shortcode( '[un_shortcode]' ).

El único uso del tipo do_shortcode( '[un_shortcode]' ) que podría justifcarse es en el caso de shortcodes que no cuentan con filtro para su output o, si aún contando con el filtro, se van a utilizar en un contexto en el que no podemos controlar que el shortcode no vaya a ser redefinido (¿un theme comercial o de distribución pública por ejemplo?).