Los ganchos son un medio para que una pieza de código interactúe con otra y la modifique. Constituyen el fundamento por el cual los plugins y los temas interactúan con el núcleo de WordPress, aunque también son empleados por el mismo núcleo.
Existen dos tipos de ganchos: las Acciones y los Filtros. Para utilizarlos, necesitas escribir una función personal conocida como llamada de vuelta (callback), y registrarla en WordPress para una acción o filtro específicos.
Los filtros te dan la posibilidad de cambiar el valor de un dato durante la ejecución de WordPress. Las funciones para llamadas de vuelta de filtros se pasan a través de una variable, se modifican y se devuelven. Están pensadas para trabajar de una manera aislada, y no suelen afectar a las variables globales o nada más fuera de la función.
Por el contrario, las acciones te permiten añadir o modificar el funcionamiento de WordPress. Tu función de llamada de vuelta se ejecutará un un punto específico en la ejecución de WordPress, y puede realizar algunos tipos de tarea, como mostrar algo al usuario o insertar algún elemento en la base de datos.
WordPress provee muchos ganchos que puedes emplear, pero además puedes crearte los tuyos propios, con los que otros desarrolladores pueden extender o modificar en tu plugin o tema.
Fuentes externas de información
- Referencia de filtros
- Referencia de acciones
- Base de datos de ganchos de Adam Brown
- Acciones y filtros no son lo mismo
Acciones
Las acciones son uno de los dos tipos de ganchos. Proveen una manera por la cual una función permite a otra función engancharse a si misma, por lo que un código adicional puede ejecutarse en un punto específico de la ejecución del núcleo de WordPress, de los plugins y de los temas. Son las contrapartidas a los filtros.
Trabajan llamando la función add_action() y pasándole dos parámetros: el nombre de la acción a la que quieres enganchar, y el nombre de tu función de llamada de vuelta que se ejecutará cuando la acción arranque. Por ejemplo: add_action( ‘init’, ‘haz_algo’ );.
La sentencia anterior hace que tu función haz_algo() sea llamada cuando WordPress arranca la acción init.
Puedes acudir a la Sección de ganchos de referencia de código para un ejemplo de acciones disponibles.
Ejemplos
Si quieres modificar la consulta MySQL que recupera artículos para el ‘loop’, puedes enganchar en la acción pre_get_posts. Algo que podrías hacer es incluir tipos de post personales (custom post type) en los resultados de la búsqueda:
1 2 3 4 5 6 7 8 |
function search_filter( $query ) { if ( ! is_admin() && $query->is_main_query() ) { if ( $query->is_search ) { $query->set( 'post_type', array( 'post', 'movie' ) ); } } } add_action( 'pre_get_posts', 'search_filter' ); |
Si quieres añadir una etiqueta HTML extra en la sección <head> de una página, puedes enganchar en la acción wp_head:
1 2 3 4 |
function prevent_google_maps_resize() { echo '<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />'; } add_action( 'wp_head', 'prevent_google_maps_resize' ); |
Parámetros adicionales
Tanto add_action() como add_filter() aceptan dos parámetros adicionales, para dar prioridad a la función de llamada de vuelta, y para el número de argumentos que se le pasará.
- Prioridad
La prioridad determina cuándo se ejecutará la función de llamada de vuelta en relación a otra función de llamada de vuelta asociada con un gancho dado.
Una función con una prioridad 11, se ejecutará después que otra función con una prioridad 10, y ésta después que una con prioridad 9. Cualquier entero positivo es un valor aceptable y por defecto es 10.
Si dos funciones están registradas para el mismo gancho y con la misma prioridad, entonces correrán en el orden en que han sido registradas en el gancho.
- Número de argumentos
A veces es deseable para una función de llamada de vuelta recibir algunos datos extras.
Por ejemplo, cuando WordPress guarda un ‘post’ y ejecuta la acción save_post, pasa dos parámetros a la función de llamada de vuelta: el ID del post que se guarda, y el objeto ‘post’ mismo.
do_action( ‘save_post’, $post->ID, $post );
Entonces, cuando una función de llamada de vuelta está registrada para la acción save_post, puede especificar que quiere recibir dichos dos argumentos:
add_action( ‘save_post’, ‘my_save_post_callback’, 10, 2 );
… y entonces, puede registrar los argumentos en la definición de la función:
1 2 3 |
function my_save_post_callback( $post_id, $post ) { // do stuff } |
Filtros
Los filtros proveen un mecanismo a las funciones para permitir a otras funciones modificar una parte de un dato.
Para usar los filtros, llamar a la función add_filter(). Necesita dos parámetros: el nombre del filtro al que quieres enganchar, y el nombre de la función de llamada de vuelta que se ejecutará cuando se active el filtro. En el siguiente ejemplo, el filtro the_title() ejecutará una función personalizada llamada modify_the_title():
add_filter( ‘the_title’, ‘modify_the_title’ );
El valor devuelto por tu función de llamada de vuelta reemplaza el valor pasado. Por ejemplo, un ‘post’ titulado «Portland is the Greatest City o Earth» vuelve con un título diferente cuando pasa a través de la función modify_the_title().
1 2 3 4 5 6 7 8 9 |
function modify_the_title( $title ) { // At this point, $title has the value of "Portland is the Greatest City on Earth" $title = str_replace( 'Portland', 'Seattle', $title ); // the str_replace() function changes "Portland" to "Seattle" return $title; // Now the title will show as "Seattle is the Greatest City on Earth" } |
Puedes acudir a la Sección de filtros de referencia de código para un ejemplo de filtros disponibles.
Ejemplos
Para añadir clases CSS extra a la etiqueta <body> cuando se cumple cierta condición:
1 2 3 4 5 6 7 8 |
function add_classes_to_body_tag( $classes ) { if ( $some_condition ) { $classes[] = 'the-extra-class'; } return $classes; } add_filter( 'body_class', 'add_classes_to_body_tag' ); |
Para añadir cierto contenido al final de cada ‘post’ o página:
1 2 3 4 5 6 |
function add_post_signature( $content ) { $content .= '<p>This text appears at the bottom of each post</p>'; return $content; } add_filter( 'the_content', 'add_post_signature' ); |
Parámetros adicionales
Como en las acciones, la función add_filter() acepta los parámetros prioridad y argumentos indicados para aquellas.
Crear ganchos personales
Una práctica importante – y muchas veces olvidada – es añadir ganchos personales a tu plugin, para que otros desarrolladores puedan extender y modificarlo, sin tener que trabajar en el.
Los ganchos personales se crean y llaman de la misma manera que los del núcleo, con add_action() / do_action() y add_filter() / apply_filters().
Desde cualquier plugin se puede crear un gancho personal, es importante poner un prefijo a tus nombres de ganchos, para evitar conflictos con otros plugins. Por ejemplo, un filtro nombrado email_body será menos útil porque es casi como el que otro desarrollador escogerá. Si el usuario instala ambos plugins, puede sufrir bugs (fallos) que son difíciles de localizar. Nombrando la función abcd_email_body (donde abcd_ es un prefijo único para tu plugin) evitarás conflictos.
Generalmente, es buena práctica emplear apply_filters() en cualquier texto que es mostrado en pantalla, particularmente en el front-end. Ello hace más fácil que tus plugins sean modificados según las necesidades de los usuarios.
Ejemplos
- Crear un formulario de ajustes extensible
Si tu plugin añade un formulario de ajustes al Panel Administrativo de WordPress, puede usar acciones para permitir otros plugins añadir sus propios ajustes. Este ejemplo muestra una acción personal siendo llamada al final del formulario:
1 2 3 4 5 6 7 8 9 10 |
function markup_settings_menu() { ?> Foo: <input id="foo" name="foo1" type="text" /> Bar: <input id="bar" name="bar1" type="text" /> <?php do_action( 'myplugin_after_form_settings' ); } |
Entonces, ahora otro plugin puede registrar una llamada de vuelta para la acción personal myplugin_after_form_settings y añadir nuevos ajustes:
1 2 3 4 5 6 7 8 9 |
function add_form_settings() { ?> New 1: <input id="new_setting" name="new_settings" type="text" /> New 2: <input id="new_setting2" name="new_setting2" type="text" /> <?php } add_action( 'myplugin_after_form_settings', 'add_form_settings' ); |
- Crear un ‘Custom Post Type’ extensible.
En este ejemplo, cuando se registra el nuevo ‘post type’, los parámetros que lo definen se pasan a través de un filtro, que otro plugin puede cambiar antes de que se cree el tipo de post.
1 2 3 4 5 6 7 8 |
function myplugin_create_post_type() { $post_type_params = array( /* ... */ ); register_post_type( 'post_type_slug', apply_filters( 'myplugin_post_type_params', $post_type_params ), ); } |
El plugin que quiera modificar el ‘post type’ puede, entonces, registrar una función de llamada de vuelta para el filtro personal myplugin_post_type_params que fue creado antes. En este caso, la llamada de vuelta está cambiando el tipo de post de tipo plano (flat) a jerárquico.
1 2 3 4 5 |
function change_post_type_params( $post_type_params ) { $post_type_params['hierarchical'] = true; return $post_type_params; } add_filter( 'myplugin_post_type_params', 'change_post_type_params' ); |
Fuentes de información externas
- Extendable Extensions
- WordPress Plugins as Frameworks
- The Pluggable Plugin
- WordPress Plugin Pet Peeves #3: Not Being Extensible
Aspectos avanzados
Eliminar acciones y filtros
A veces querrás eliminar un gancho de llamada de vuelta que otro plugin o tema ha creado, o uno del propio núcleo de WordPress. Por ejemplo, puedes mejorar la ejecución de un innecesariamente largo tema desenganchando algunas de sus funcionalidades innecesarias.
Para eliminar un gancho de llamada de vuelta, necesitas llamar a las funciones remove_action() o remove_filter() con los mismos argumentos de las correspondientes add_action() / add_filter() que lo registraron. Piensa que debes esperar hasta después de que el tema ha registrado la llamada de vuelta antes de que tú la puedas eliminar.
Un tema añade un gancho en su archivo functions.php
1 2 3 4 |
function setup_slider() { // ... } add_action( 'template_redirect', 'setup_slider', 9 ); |
Eliminar el gancho
Desde que la llamada de vuelta se añade en el fichero functions.php del tema, engancharás en WordPress después de que ha sido cargado. El primer gancho que funciona después de la ejecución de functions.php es after_setup_theme.
1 2 3 4 |
function remove_theme_hooks() { remove_action( 'template_redirect', 'setup_slider', 9 ); // make sure all of the parameters match the add_action() call exactly } add_action( 'after_setup_theme', 'remove_theme_hooks' ); // make sure we run call remove_action() after add_action() has been called |
Eliminar todas las llamadas de vuelta
Puedes eliminar todas las llamadas de vuelta asociadas a un gancho con las funciones remove_all_actions() y remove_all_filters().
Determinar el filtro actual
En ocasiones quieres que una función se ejecute en varios ganchos, pero se comporta de diferente manera según donde esté. Puedes usar la función current_filter() para determinar el gancho actual. Aunque se llama current_filter(), también devuelve la acción actual.
1 2 3 4 5 6 7 8 9 |
function abc_modify_content() { if ( 'the_content' == current_filter() ) { // do something } else { // do something else } } add_filter( 'the_content', 'abc_modify_content' ); add_filter( 'the_excerpt', 'abc_modify_content' ); |
Verificando cuántas veces se ejecuta un gancho
Algunos ganchos son llamados varias veces en el curso de la ejecución de los scripts, pero puedes querer que tu llamada de vuelta sólo se ejecute una vez. En este caso, puedes chequear cuántas veces el gancho se ha producido con la función did_action().
1 2 3 4 5 6 7 8 |
function foo() { if ( 1 !== did_action( 'save_post' ) { return; } // ... } add_action( 'save_post', 'foo' ); |
Depurando con el gancho ‘all’
Si quieres una llamada de vuelta que se ejecute con cada acción y con cada filtro, puedes registrarla a la acción ‘all’. A veces, es útil en situaciones de depuración, para ayudar a determinar cuando se produce un evento particular o cuando una página no funciona.
1 2 3 4 |
function print_current_hook() { echo '<p>' . current_filter() . '</p>'; } add_action( 'all', 'print_current_hook' ); |
hola amigo. muy buen tutorial, pero quiera preguntar si puedes ayudarme con el filtro de enganchar las imágenes que se cargan a mi web y modificares el nombre. podrías ayudarme?
Buenos días, Séptimo.
Por lo que me dices, entiendo que quieres cambiar el nombre de las imágenes en el momento en que las subes a tu directorio de medios. Para ello, tienes el filtro wp_handle_upload_prefilter, del que encontrarás más información en https://codex.wordpress.org/Plugin_API/Filter_Reference/wp_handle_upload_prefilter
Espero que te haya podido ayudar. Saludos, y ya me contarás.