Cómo se programa un widget de WordPress

Programar un widget de WordPress es fácil y divertido. En esta entrada veremos cómo hacerlo.

archivado en: WordPress / 5 noviembre, 2012

En esta entrada vamos a ver cómo se programa un plugin de WordPress para que se muestre como un widget del sidebar. No es un tutorial sencillo, hay que hablar de clases y otras espesuras relacionadas con la programación orientada a objetos de PHP  😎 ... pero don't panic! It's easy.

Si seguimos con atención este tutorial (espero) podremos programar nuestros propios widgets sin tener la más remota idea de qué es una clase, aunque sí es importante saber al menos qué es una función, una variable, etcétera... De todas maneras, otro día trataré de explicar qué eso de la POO en PHP, que además se lo he prometido a mi amigo Javier.

1. Declarar el plugin

Lo primero es crear el plugin, que no es sino un conjunto de instrucciones en un archivo php que se cargan cuando un ordenador cliente se conecta al sitio. Todos los plugin deben llevar los siguientes datos iniciales:

  • /*
  • Plugin Name: nombre del plugin
  • Plugin URI: url desde la que se puede descargar
  • Description: descripción de lo que hace
  • Author: nombre del autor
  • Version: versión
  • Author URI: url del autor
  • License: licencia
  • */

Es muy importante que el plugin tenga un nombre que con toda seguridad no se vaya a repetir, por lo que conviene añadir las iniciales o el nik o cualquier otra particularidad al principio. Por ejemplo, un plugin que acabo de programar se llama mmfilesi-random-post.

Una vez completados esos datos, el archivo php se guarda en una carpeta con el mismo nombre del plugin.

Importante Importantísimo: si se trabaja con Notepad++, que es el editor que suelo emplear yo, conviene codificar el archivo como UTF sin BOM y no hay que dejar ni un solo espacio antes ni después del código (explico esto otro día, que es un jaleo de cuidado).

[singlepic id=19 w=466 h=336 float=center]

2. Cuatro funciones con clase

Tras los datos que identifican al widget se crea una una clase extendida de WP_Widget. Una clase es una especie de superfunción, que incluye varias funciones, llamadas métodos, y variables, denominadas propiedades. Las clases se pueden «copiar» definiendo la clase precedida por la palabra clave extends. Estas copias extendidas tienen todos los métodos y propiedades de la clase original.

Así, para acceder a todos los métodos (funciones) de la clase de WP_Widget basta con escribir:

  • class nombre_de_mi_widget extends WP_Widget {
  • // aquí las funciones
  • }

Por lo general, para programar un widget hay que trabajar con estos cuatro métodos de la clase WP_Widget:

  1. function __construct(): Registra el widget en WordPress.
  2. function widget ($args, $instance): Lo que hace el widget, es decir, lo que se muestra en el front-end.
  3. function update ($new_instance, $old_instance): Graba los datos indicados en el back-end en la base de datos.
  4. function form ($instance): Para definir los datos que se muestran en el front-end.

Por lo tanto, de momento el código de nuestro plugin debería quedar así:

  1. <?php
  2. /*
  3. Plugin Name: nombre del plugin
  4. Plugin URI: url desde la que se puede descargar
  5. Description: descripción de lo que hace
  6. Author: nombre del autor
  7. Version: versión
  8. Author URI: url del autor
  9. License: licencia
  10. */
  11. ?>
  12. <?php
  13. class mi_widget extends WP_Widget {
  14. public function __construct () {
  15. // instrucciones para esta función
  16. }
  17. public function widget ($args, $instance) {
  18. // instrucciones para esta función
  19. }
  20. public function update ($new_instance, $old_instance) {
  21. // instrucciones para esta función
  22. }
  23. public function form($instance) {
  24. // instrucciones para esta función
  25. }
  26. } // Cierra la clase
  27. ?>

Veamos estas funciones / métodos con más detalle.

3)  Primera función: function __construct()

Sirve para declarar el widget  (línea 80 y ss. del core). Por este orden, pueden definirse cuatro propiedades, es decir, se le pueden indicar cuatro datos:

a) $id_base: (string opcional) el ID del widget, con el que nos referiremos a él en el resto del código. Importante, hay que escribirlo en mínusculas sin CamelCase. Si se deja vacío, se usará el nombre de la clase del widget. Claro está, debe ser único.

b) $name: (string opcional) el nombre del widget tal y como aparecerá en el back-end.

c) $widget_options: (array) un array con dos argumentos opcionales:

  • description: una descripción (breve) que se mostrará en el back-end.
  • classname: el nombre de la clase.

d) array $control_options: otro array, opcional, en el que se pueden definir dos parámetros:

  • width: requerido si el widget es más ancho de 250px.
  • height: de momento no se usa nunca, no es necesario pero lo han incluido pensando en alguna necesidad futura.

Así, este método podría quedar más o menos de esta manera:

  • public function __construct() {
  • parent::__construct(
  • 'mi_widget', // $id_base
  • 'Soy un widget formidable', // $name
  • array( 'description' => __( 'Widget formidable que hace maravillas', 'mi-widget' ), ) // $widget_options
  • );

Inciso importante: strings traducibles

En description no he asignado la cadena directamente:

description' =>  'Widget formidable que hace maravillas'

En vez de eso, he usado esta fórmula

__('cadena', 'nombre-del-widget').

Esto es para que luego el widget se muestre en el idioma del WP en el que está instalado. Ya veremos esto con calma otro día, de momento, baste con saber que todo el texto debe(ría) declararse de estas dos formas:

  • __('cadena', 'nombre-del-widget'): texto que no se muestra directamente.
  • _e('cadena', 'nombre-del-widget'): equivale a echo __('cadena', 'nombre-del-widget').

Hay otras maneras de tratar las cadenas, pero las dejamos para otra entrada.

4. Segunda función: function widget ($args, $instance)

Es la función más importante, la que procesa los datos para mostrarlos en el front-end. Recibe como parámetros dos matrices (arrays):

  • $args: con los argumentos definidos el tema para los widgets (before_title, after_title, before_widget y after_widget).
  • $instance: con los argumentos definidos en el widget.

Equivaldría a:

  • function widget ($args=array ('before_title' => 'valor',...), $instance ('clave' => 'valor')).

Y lo bueno es que mediante la función extract de PHP se pueden convertir todos los pares clave/valor de un array en variables de forma muy sencilla. Así, esto:

  • extract ($args);

da como resultado que se formen las siguientes variables

  • $before_title = "valor";
  • $after_title ="valor";
  • ...

Y lo mismo con $instance. Por ejemplo, si hemos definido en un formulario un campo llamado mi_campo para recoger el título del widget, esto:

  • extract ($instance);

da como resultado:

  • $mi_campo ="el valor que introdujo el usuario";

Así, en el caso anterior, el código final de esta función podría ser similar a este:

  • public function widget ($args, $instance ) {
  • extract($args);
  • extract($instance);
  • echo $before_widget.$before_title;
  • echo $mi_campo;
  • echo $after_title.$after_widget;
  • }

5. Tercera función: function update ($new_instance, $old_instance)

Esta función graba los datos indicados en el formulario del widget en la base de datos (en un registro de wp_options). Es la forma más sencilla para guardar datos y se emplea cuando son pocos (si el widget necesita grabar muchos datos, entonces lo más recomendable es crear una tabla específica, que ya veremos cómo se hace otro día).

Los datos se guardan en un array (el que luego se recoge con $instance) después de haberlos pasado por strip_tags, una función de PHP que sirve para quitar código HTML de una cadena de texto (el addslashes para evitar inyecciones SQL ya lo hace automáticamente).

  • public function update( $new_instance, $old_instance ) {
  • $instance = array();
  • $instance['mi_campo1] = strip_tags( $new_instance['mi_campo1'] );
  • $instance['mi_campo2] = strip_tags( $new_instance['mi_campo2'] );
  • return $instance;
  • }

6. Cuarta función: function form($instance)

Esta función es la que muestra el widget en el back-end, el formulario que se pone en el sidebar, para entendernos.

Al igual que sucedía con function widget, recibe el array $instance, que podemos pasar por un extract o utilizar directamente. Es decir, esto:

  • extract ($instance);
  • if ($mi_campo == 1) {
  • echo "soy una variable llamada mi_campo";
  • }

es lo mismo que esto:

  • if ($instance['mi_campo'] == 1 {
  • echo "soy una variable llamada mi_campo";
  • }

Sea de una forma u otra, es muy recomendable que, antes de definir el formulario, pongamos un valor por defecto a los distintos datos que luego se recogerán con function update. Por ejemplo,

  • if ( isset( $instance[ 'mi_campo' ] ) ) {
  • $mi_campo = $instance[ 'mi_campo' ];
  • }
  • else {
  • $mi_campo = __( 'Valor por defecto', 'mi-widget' );
  • }

Una vez definidos unos valores por defecto, se puede pasar a crear el formulario, para lo cual es muy útil emplear otras dos funciones de WP_Widget:

  • function get_field_name($field_name) {
  • return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . ']';
  •  }
  • function get_field_id($field_name) {
  • return 'widget-' . $this->id_base . '-' . $this->number . '-' . $field_name;
  • }

Con la primera se obtiene el nombre del campo tal y como se necesita para trabajarlo después y con la segunda el id. Así, por ejemplo, un formulario podría quedar de forma similar a esta:

  • <p>
  • <label for="<?php echo $this->get_field_id( 'mi_campo' );  ?>"><?php _e('T&iacute;tulo:', 'mi-widget'); ?></label>
  • <input class="widefat" id="<?php echo $this->get_field_id( 'mi_campo' ); ?>" name="<?php echo $this->get_field_name ( 'mi_campo' ); ?>" type="text" value="<?php echo esc_attr ($mi_campo); ?>" />
  • </p>

(esc_attr codifica en HTML los caracteres < > & " ')

7. Últimos detalles

Una vez definidas las cuatro funciones, fuera de la clase se declaran las hojas de estilo, los script de jQuery y la traducción, temas todos que veremos en la próxima entrada de este tutorial.

  • /*  CSS */
  • function carga_estilo_del_widget () {
  • wp_register_style( 'mi-estilo', plugins_url('mi-estilo.css', __FILE__) );
  • wp_enqueue_style( 'mi-estilo' );
  • }
  • add_action( 'wp_enqueue_scripts', 'carga_estilo_del_widget' );
  • /* jQuery */
  • function carga_mi_jquery() {
  • wp_enqueue_script( 'jquery' );
  • wp_enqueue_script( 'mi_jquery', plugins_url('js/mi_jquery.js', __FILE__));
  • }
  • add_action('wp_enqueue_scripts', 'carga_mi_jquery');
  • /* traducciones */
  • function carga_mi_traduccion() {
  • load_plugin_textdomain('mi-widget', false, basename( dirname( __FILE__ ) ) . '/languages' );
  • }
  • add_action('init', 'carga_mi_traduccion');
  • /* se registra el plugin */
  • function registra_mi_plugin() {
  • register_widget('mi_widget'); // ID
  • }
  • add_action('widgets_init', 'registra_mi_plugin');

Bueno, leído del tirón quizás no habrá quedado muy claro, pero en la próxima entrada de este tutorial haremos una práctica que nos permitirá terminar de comprender cómo se programa un widget para WordPress. De momento, espero que esta primera parte haya resultado de utilidad.

Abrazos++;

|| Tags: , ,

valoración de los lectores sobre Cómo se programa un widget de WordPress

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 5 sobre 5 (3 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

9 respuestas a “Cómo se programa un widget de WordPress

  1. Y si a la hora de añadir el estilo y jquery no lo hace?

    He probado varias formas de hacerlo y con ninguna lo consigo. No me da ningun error pero no me aparacen.

  2. marcos el dijo:

    La forma correcta de añadir jQuery en WP es esta.

    a) Escribes el código jquery en modo no conflicto (poniendo jQuery en vez del dólar) en un archivo que por ejemplo llamas mi-jquery.js y guardas en un directorio llamado js

    b) En funcions.php añades este código:

    function carga_jqueries() {
    wp_register_script(‘mi-jquery.js’, get_template_directory_uri() . ‘/js/mi-jquery.js’, array(‘jquery’),false);
    wp_enqueue_script( ‘mi-jquery.js’ );
    }

    add_action( ‘wp_enqueue_scripts’, ‘carga_jqueries’ );

    Con eso debería bastar para un tema.

    En el caso de los widgets el proceso es similar. Aquí tienes el código de un widget con jquery:

    https://github.com/mmfilesi/mmfilesi-random-post

  3. Me refiero que al hacer:

    function carga_estilo_del_widget () {
    wp_register_style( ‘mi-estilo’, plugins_url(‘mi-estilo.css’, __FILE__) );
    wp_enqueue_style( ‘mi-estilo’ );
    }

    No me lo carga. Esto lo tengo puesto en el plugin y no me funciona.

    PD: Estoy en un servidor local.

  4. marcos el dijo:

    ¿Lo has anclado? Es decir, una vez “registrado” tienes que anclarlo con un hook (ad action)

    function carga_estilo_del_widget() {
    todo el tinglado como lo tienes
    }

    add_action( ‘wp_enqueue_scripts’, ‘carga_estilo_del_widget’ );

  5. Sisi, lo tengo como lo muestras tu.
    Y existir, existen esos archivos.

    No hay otra forma de conseguir agregarlos?

  6. marcos el dijo:

    no, cualquier otra manera sería una ñapa. Pero si tienes el código como indicas está bien. Hay algo que no funciona, pero no es el código… vamos, igual es una errata por algún lado, pero tal y como lo tienes está bien.

    ¿No puedes probarlo en un sitio que no sea local?

  7. Si, al principio estaba en una Web online, pero quiero instalarlo también en mi servidor por comodidad.

    Es que en todos los foros que he estado dicen esta forma de hacerlo y en mi server no funciona! Que raro!

  8. marcos el dijo:

    Ando fatal, pero realmente mal, de tiempo y no me da tiempo de revisar el código, pero lo que sí te puedo asegurar es que tal y como lo tienes debería funcionar.

    Si no lo hace no es por el procedimiento, sino por algún tipo de errata o cualquier rarismo ajeno al widget que estás programando.

    Prueba una cosa: quita todo el código menos el carga estilos y luego mira con el inspector de chrome si lo ha cargado.

  9. No me ha funcionado.
    Gracias por la ayuda, lo subiré a internet y a ver cómo responde.

    Si se te ocurre algo me dices.

    Un saludo.