En este tutorial, analizaremos de cerca el widget de texto de WordPress para descubrir el proceso de creando un widget que se pueden agregar a múltiples ubicaciones de widgets.
Si conoce los conceptos básicos de la programación en PHP, crear un widget de WordPress no es difícil en absoluto. He cubierto lo básico en un tutorial anterior, La anatomía de un complemento de WordPress. Es una buena idea verificarlo antes de seguir leyendo, si no ha creado un widget antes..
Si bien esa forma básica de crear un widget es lo suficientemente buena para muchos complementos, tiene un gran inconveniente: el widget se puede agregar a una sola ranura en un blog..
Si agrega el widget a una de las barras laterales, el botón "Agregar" del widget desaparece y el widget no se puede agregar a ninguna otra ranura antes de eliminarlo de la primera..
En algunos casos, eso no es un problema, porque la naturaleza del widget es que se muestra solo una vez. Por ejemplo, es bastante correcto enumerar solo el archivo del blog en un lugar del diseño. Pero hay muchos casos en los que más de una instancia puede ser muy útil. Un ejemplo es el widget de texto que viene incluido con WordPress.
El widget de texto es un widget simple que te permite especificar un encabezado y un texto, también permite HTML, y muestra su contenido en la barra lateral del blog. Debido a esta simplicidad, el widget se puede utilizar para una amplia gama de propósitos. Por ejemplo, en la siguiente imagen, una captura de pantalla de mi blog personal, puede ver cómo uso el widget de texto en mi barra lateral primero para mostrar un texto de bienvenida y luego nuevamente para mostrar algunos anuncios en la parte inferior de la barra lateral. En la documentación de WordPress, widgets como este se llaman "multi-widgets".
Debido a que WordPress es un proyecto de código abierto, podemos profundizar en el código fuente y usarlo como referencia para nuestros propios proyectos. Para este tutorial, significa que podemos echar un vistazo más de cerca al widget de Texto y ver cómo se ha implementado, usándolo como un ejemplo para convertir nuestros propios widgets en múltiples widgets..
El primer paso es buscar en el código base de WordPress y localizar el widget de texto. Es un paso interesante y le recomiendo que revise algunos otros archivos aquí y allá también para obtener una visión general de lo que ocurre dentro de la plataforma de blogs..
Pero si no puedes esperar para entrar en acción, aquí es donde encontrarás el código del widget:
wordpress / wp-includes / widgets.php
Abra el archivo y desplácese hasta el final, alrededor de la línea 1958 (en la versión 2.7.1), y allí, oculto en el centro del código fuente, encontrará un widget de ejemplo, comentado y etiquetado como "Patrón para varios widgets (permite múltiples instancias, como el widget de texto)".
Al principio, el código de ejemplo puede parecer bastante desalentador, así que lo analizaremos línea por línea, dando sentido a las ideas alrededor de las cuales se construye el patrón. Los fragmentos de código en este tutorial se han copiado del patrón de ejemplo, pero he hecho algunos pequeños cambios aquí y allá para hacer que el código sea más fácil de seguir (principalmente para dividir líneas largas en largas). Aparte de esos pequeños ajustes, el código fuente es exactamente el mismo que encontrará al abrir widgets.php
desde el código base de WordPress.
Cuando el usuario presiona el botón "Guardar cambios" en el menú Widgets, WordPress recopila los parámetros del formulario de cada widget listado en las barras laterales y los envía a cada uno de los widgets registrados. Esta característica es lo que hace que sea posible crear múltiples widgets: a medida que la función de controlador de widgets recibe una notificación para guardar una instancia de widget, se le pasan todos los parámetros, y puede actualizar cada instancia de este tipo de widget de una sola vez, agregando otros nuevos y Eliminar los no utilizados según sea necesario..
Examinaremos los detalles del proceso de guardado en breve, pero primero, un buen lugar para comenzar a ver cómo se almacenan los datos del widget para un multivigo es mirar la parte del código donde se usan los datos. . Aquí está el código del método utilizado para mostrar una instancia del widget de ejemplo:
$ widget_args); $ widget_args = wp_parse_args ($ widget_args, array ('número' => -1)); extraer ($ widget_args, EXTR_SKIP); // Los datos deben almacenarse como una matriz $ options = get_option ('widget_many'); if (! isset ($ options [$ número])) devolver; echo $ before_widget; // Haz cosas para este widget, dibujando datos de $ options [$ número] echo $ after_widget; ?>
El primer parámetro pasado a la función de representación del widget, $ args
, contiene configuraciones de widgets genéricos, como lo que debe imprimirse antes y después del widget, y cómo debe formatearse el encabezado del widget. El código en la línea 3 se usa para dividir esa información en variables locales, de las cuales $ before_widget
y $ after_widget
se utilizan en el ejemplo.
El segundo parametro, $ widget_args
Es más interesante para nosotros: contiene el ID de la instancia del widget que se va a representar. Las líneas 4 a 7 están ahí para asegurarse de que el parámetro tenga el formato correcto, y que al final, después de extraer
Llame a la línea 7, podemos encontrar el índice del widget en la variable local $ numero
.
Al igual que la configuración de widgets para un widget simple, de una sola vez, las configuraciones para una instancia de widget se almacenan como una matriz que contiene pares clave-valor para cada configuración. Pero como ahora necesitamos almacenar múltiples instancias, en lugar de guardar cada matriz con su propia llamada a update_option
, los colocamos todos en una matriz usando el id de instancia ($ numero
) como el índice y luego guardar todo con el id del tipo de widget.
En el ejemplo anterior, tenemos un widget llamado "widget_many
", y digamos que hemos agregado tres instancias de esto a la barra lateral de nuestro blog. Al representar uno de ellos, primero obtenemos una matriz que contiene todos los widget_many
instancias llamando get_option ('widget_many');
(línea 10) y luego busque los datos para la instancia actual de esa matriz (línea 16).
El código de ejemplo de no muestra los detalles de lo que debes hacer con los datos, así que echemos un vistazo al widget de texto real para obtener más información:
$ widget_args); $ widget_args = wp_parse_args ($ widget_args, array ('número' => -1)); extraer ($ widget_args, EXTR_SKIP); $ options = get_option ('widget_text'); if (! isset ($ options [$ número])) devolver; $ title = apply_filters ('widget_title', $ options [$ number] ['title']); $ text = apply_filters ('widget_text', $ options [$ número] ['texto']); ?>
En las líneas 13 y 14, puede ver cómo se leen los dos parámetros necesarios para el widget de texto desde las opciones usando $ numero
como id de instancia Y en las siguientes diez líneas, los parámetros se representan en la pantalla..
Al analizar la función de representación del widget, ahora hemos descubierto los conceptos básicos de guardar los datos para un widget múltiple:
Ahora, miraremos más de cerca y veremos los trucos y advertencias involucrados..
Usando el mismo enfoque que antes, ahora veremos la función utilizada para mostrar y manejar los formularios de configuración y revisaremos línea por línea. Esta función, widget_many_control
, es la función que guarda la configuración y representa el formulario de configuración para el widget de ejemplo "widget_many". Se llama una vez para cada widget_many
instancia, siempre pasando el id de instancia en $ widget_args
.
Como la función forma parte del manejo de envío de formularios, $ _POST
La matriz contendrá todos los parámetros que se han enviado utilizando el formulario de edición del widget.
$ widget_args); $ widget_args = wp_parse_args ($ widget_args, array ('número' => -1)); extraer ($ widget_args, EXTR_SKIP);
En las primeras líneas de la función, verá algo familiar (líneas 6-9). Este es el mismo fragmento de código que se utilizó en la función de representación para asegurarse de que $ numero
se ha inicializado con el ID numérico de la instancia del widget actual.
Pero como pronto se dará cuenta, no necesitaremos ese índice para otra cosa que no sea la forma de edición del widget, ya que siempre guardamos cada instancia del tipo de widget "widget_many" en un solo bucle.
A continuación, recuperaremos la configuración actual de los widgets y los crearemos si no existen:
$ options = get_option ('widget_many'); if (! is_array ($ options)) $ options = array ();
Al implementar su propio widget, recuerde cambiar la clave, widget_many
a la identificación de su propio widget. Aparte de eso, este código se puede reutilizar como está. En las líneas 2 y 3, el código se ocupa del caso cuando estamos agregando la primera instancia de widget de este tipo creando una matriz de opciones vacía para usar.
Si las configuraciones ya se han guardado al menos para una instancia, las obtenemos de get_option
y puede continuar actualizando la configuración si se envió un formulario:
if (! $ updated &&! empty ($ _ POST ['sidebar']))
La línea anterior tiene dos funciones: verifica si los datos se publicaron ("!vacío ($ _ POST ['barra lateral'])
") y se asegura de que las instancias de este tipo de widget se manejen solo una vez.
El sistema de widgets llama a la función de manejo de widgets una vez por cada instancia de widget, pero debido a que debemos ocuparnos de cosas como agregar y eliminar nuevas instancias de widgets, no podemos hacer eso sin conocer todos los widgets de este tipo que existen. Esta es la razón por la que el enfoque es actualizar cada instancia de widget de este tipo en la primera aparición y luego establecer la variable global $ actualizado
a verdadero para que la siguiente instancia no vuelva a hacer la actualización.
// Nos dice qué barra lateral para poner los datos en $ sidebar = (string) $ _POST ['sidebar']; $ sidebars_widgets = wp_get_sidebars_widgets (); if (isset ($ sidebars_widgets [$ sidebar])) $ this_sidebar = & $ sidebars_widgets [$ sidebar]; else $ this_sidebar = array (); foreach ($ this_sidebar as $ _widget_id) $ widget = $ wp_registered_widgets [$ _ widget_id]; if ('widget_many' == $ widget ['callback'] && isset ($ widget ['params'] [0] ['number'])) $ widget_number = $ widget ['params'] [0] [' número']; if (! in_array ("many- $ widget_number", $ _POST ['widget-id'])) no establecido ($ options [$ widget_number]); // Compilar datos de $ widget_many_instance $ widget_data = (array) $ _POST ['widget-many']; foreach ($ widget_data como $ widget_number => $ widget_many_instance) if (! isset ($ widget_many_instance ['algo']) && isset ($ options [$ widget_number])) // el usuario hizo clic en cancelar continuar; $ algo = wp_specialchars ($ widget_many_instance ['algo']); $ options [$ widget_number] = array ('algo' => $ algo); update_option ('widget_many', $ opciones); $ updated = true; // Para que no pasemos por esto más de una vez.
Este fragmento de código primero busca todos los widgets almacenados en la barra lateral que se está actualizando (líneas 2-8) y luego recorre la lista eliminando todos los que coinciden con el ID de widget de este tipo de widget (líneas 10-18).
$ _POST ("barra lateral")
(línea 2) contiene el id de la barra lateral. De esta manera, si el usuario ha eliminado un widget, también se eliminará de los datos. Y al eliminar todo, nos aseguramos de no dejar duplicados accidentalmente, por ejemplo, si la identificación de algún widget ha cambiado entre actualizaciones.
Después de eliminar todo, comenzamos a agregar los widgets que fueron publicados por el usuario. En el formulario publicado, hay una matriz que contiene todos los datos para cada instancia del tipo de widget. La matriz está organizada de esta manera:
['widget-many'] => [0] => params para la instancia de widget 0 (matriz), [1] => params para la instancia de widget 1 (matriz), ...
En las líneas 23-31, el código recorre los datos de la instancia del widget enviados y crea la configuración para cada instancia (líneas 29 y 30). Como este es solo un código de ejemplo, la parte de guardado está usando datos de marcador de posición como "algo". Entonces, veamos nuevamente el widget de texto para ver cómo funciona esto con datos reales:
$ title = strip_tags (stripslashes ($ widget_text ['title'])); if (current_user_can ('unffiltered_html')) $ text = stripslashes ($ widget_text ['text']); else $ text = stripslashes (wp_filter_post_kses ($ widget_text ['text'])); $ options [$ widget_number] = compacto ('título', 'texto');
El widget de texto tiene dos parámetros: título
y texto
. los $ widget_text
La variable en este fragmento de código se usa de la misma manera que $ widget_many_instance
en el código de ejemplo que hemos estado siguiendo: contiene los datos publicados para una instancia específica del widget.
En el ejemplo del widget de texto, también verás algunas características de seguridad interesantes que quizás quieras ver un poco más cuando desarrolles tus propios widgets. Para este tutorial, sin embargo, es suficiente ver que el contenido de las variables $ titulo
y $ texto
se leen desde la matriz publicada y luego se almacenan como una matriz para las opciones del widget en la línea 6.
Si te estás preguntando por el compacto()
función, es lo contrario de extraer()
, y toma las variables locales cuyos nombres se pasaron como parámetros y las convierte en una matriz con los nombres como claves.
Finalmente, el nuevo $ opciones
matriz se almacena como los datos para el widget, widget_many
en el código de ejemplo o widget_text
en el widget de texto, usando el update_option ()
función.
Lo último que queda en la función de configuración del widget es dibujar el formulario para esta instancia de widget. Esta forma no se muestra en la pantalla tal como está, pero WordPress la convierte en una forma real más tarde, usando algo de magia de JavaScript. El siguiente código es del código de la plantilla, por lo que utiliza $ algo
para representar los datos del widget. En el widget de texto se sustituye por $ titulo
y $ texto
, y en tu propio widget con cualquier cosa que necesites guardar..
Es importante tener en cuenta que aunque el guardado se realiza para cada instancia de una vez, el formulario presentado aquí es para una sola instancia. Aquí es donde usaremos el ID de instancia de widget leído al principio de la función..
if (-1 == $ número) $ algo = "; $ número = '% i%'; else $ algo = attribute_escape ($ opciones [$ número] ['algo']);
En las líneas anteriores, el widget primero verifica si se dio un número de widget válido o no. Si no, y $ numero
se estableció en el valor predeterminado, -1, todos los datos deben establecerse en los valores predeterminados. De lo contrario, obtendremos los datos de la $ opciones
Array y utilícelo para rellenar el formulario con la configuración actual. Esto es una buena cosa que hacer para que el usuario no tenga que comenzar siempre a editar el widget desde una pizarra vacía.
Y luego, el formulario en sí está creado de modo que se puede leer en una matriz cuando se publica en el código de manejo del widget: las entradas del formulario se nombran siguiendo el patrón widget-many [$ number] [algo]
dónde $ numero
es el número de esta instancia de widget y alguna cosa
Es el nombre del parámetro a guardar. WordPress luego analiza esto en la estructura de matriz descrita anteriormente cuando el usuario envía el formulario.
El formulario no tiene un botón de envío porque todos los widgets se guardan utilizando el mismo botón de envío proporcionado por WordPress.
Para que WordPress muestre un widget en la lista de widgets, debe registrarlo indicándole a WordPress qué funciones debe usar para representar el widget y su configuración. La forma en que se hace para los widgets múltiples no es tan diferente de los widgets normales. La única diferencia está en cómo se define el id del widget: En $ control_ops
(línea 7), le decimos a WordPress que habilite múltiples instancias y que adjunte todas las instancias de widgets con un inicio de identificación "muchos"
a este tipo de widget.
function widget_many_register () if (! $ options = get_option ('widget_many')) $ options = array (); $ widget_ops = array ('classname' => 'widget_many', 'description' => __ ('Widget que permite múltiples instancias')); $ control_ops = array ('width' => 400, 'height' => 350, 'id_base' => 'many'); $ nombre = __ ('Muchos'); $ registrado = falso; foreach (array_keys ($ options) como $ o) // Los widgets antiguos pueden tener valores nulos por alguna razón si (! isset ($ options [$ o] ['algo'])) continúa; // $ id debería verse como $ id_base - $ o $ id = "many- $ o"; // Nunca nunca traducir nunca un id $ registered = true; wp_register_sidebar_widget ($ id, $ name, 'widget_many', $ widget_ops, array ('number' => $ o)); wp_register_widget_control ($ id, $ name, 'widget_many_control', $ control_ops, array ('number' => $ o)); // Si no hay ninguno, registramos la // existencia del widget con una plantilla genérica si (! $ Registered) wp_register_sidebar_widget ('many-1', $ name, 'widget_many', $ widget_ops, array ('number' = > -1)); wp_register_widget_control ('many-1', $ name, 'widget_many_control', $ control_ops, array ('number' => -1)); // Esto es importante add_action ('widgets_init', 'widget_many_register');
En la función anterior, primero registramos todos los widgets existentes de este tipo, omitiendo los que no tienen datos válidos (líneas 11-23), y luego, si no hay una instancia disponible aún, registre una predeterminada para asegurarse el widget está registrado y disponible en la barra lateral (líneas 27-32).
Como último paso crucial, en la línea 34, conectamos la función de inicialización del widget a la widgets_init
evento para que WordPress lo llame cuando sea el momento de inicializar todos los widgets. Sin esta función, no veríamos ninguna de las funciones del widget que acabamos de analizar, ya que ninguna parte del código se llamaría.
En los fragmentos anteriores, he dejado deliberadamente algo del código para que las cosas sean más legibles, por lo que no podrá copiar las piezas y juntarlas. En su lugar, debe ir y copiar ese mismo código de su instalación de WordPress.
Después de eso, solo necesitas poner tu propia funcionalidad, y ahí está: tu propio multi-widget.