Familiarizarse con la clase Walker de WordPress

Publicado: 2020-11-27

Si no está familiarizado con Walker Class, prepárese para sorprenderse de lo útil que puede ser para su trabajo. WordPress Walker Class se implementó en WordPress 2.1 para proporcionar a los desarrolladores un medio para atravesar estructuras de datos en forma de árbol con el fin de representar HTML. En este artículo estudiaremos cómo funciona el parámetro walker y cómo personalizar las salidas en menús, categorías y comentarios.

¡Vámonos!

Descripción general de la clase Walker

En WordPress, vemos con frecuencia objetos que tienen una estructura jerárquica como menús de navegación, listas de categorías o listas de comentarios.

Como ya sabrá, en el caso de una estructura de datos de árbol, algunos elementos son padres y otros son sus hijos. "Subcategoría de publicación 1" es un elemento secundario de "Categoría de publicación 1", una respuesta a un comentario es un comentario secundario del comentario en sí, y "Servicio 1" es un elemento de menú secundario del elemento "Servicios".

El Walker se denomina así porque simplemente "camina" a través de cada objeto o matriz asociativa y ejecuta una función en cada nodo. Lo que nos gustaría lograr con esto es la capacidad de enumerar los enlaces de 'nivel superior', con sus elementos 'secundarios' de diferentes maneras según nuestros requisitos específicos.

En otras palabras, WordPress le brinda una estructura <ul> <li> estándar y puede personalizar sus argumentos, pero, al extender el Walker, puede personalizar la estructura modificando su contenido HTML.

El archivo central relacionado con Walker Class es wp-includes/class-wp-walker.php y rige todos los tipos de datos en forma de árbol que enumeramos anteriormente.

Como es una clase de PHP abstracta, para generar cualquier HTML, el desarrollador debe extenderla y definirá una versión personalizada de sus propiedades y métodos. Entonces, estudiemos las clases secundarias en el archivo class-wp-walker.php una por una.

Clases Infantiles

El $tree_type es una variable opcional que viene en un tipo o matriz de tipos y define lo que maneja la clase.

 public $tree_type = array( 'post_type', 'taxonomy', 'custom' );

$db_fields es una variable requerida y define qué campos de la base de datos usar. Esta propiedad es una matriz con dos claves: 'padre' e 'id', cuyos valores son los nombres de las propiedades del objeto que contienen la identificación principal y la identificación del elemento, respectivamente.

 public $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id', );

La propiedad $max_pages también es opcional y su función es especificar el número máximo de páginas recorridas por el caminante paginado.

 public $max_pages = 1;

$has_children en realidad se explica por sí mismo y tiene un valor verdadero o falso dependiendo de si el elemento actual tiene hijos.

 public $has_children;

El método start_lvl se ejecuta en la raíz de un nuevo objeto similar a un árbol y toma los argumentos $salida, $profundidad y $args.

 public function start_lvl( &$output, $depth = 0, $args = array() ) {}

El argumento $output agrega contenido adicional, $depth especifica la profundidad del elemento y $args es una matriz de argumentos adicionales.

El método end_lvl cierra cualquier etiqueta que haya abierto previamente el método start_lvl.

 public function end_lvl( &$output, $depth = 0, $args = array() ) {}

El método start_el (elemento de inicio) se utiliza para mostrar la etiqueta HTML de apertura del elemento actual. En el caso de un menú, por ejemplo, suele ser una etiqueta <li>.

 public function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {}

La función end_el se llama después de que Walker pasa un elemento con todos sus hijos y devuelve una etiqueta de cierre.

 public function end_el( &$output, $object, $depth = 0, $args = array() ) {}

El display_element en realidad muestra los elementos del objeto de árbol. Llama a las funciones start_el , start_lvl , display_element , end_lvl , end_el en este orden. Ahora echemos un vistazo a sus argumentos.

  • $elemento : el elemento actual
  • $children_elements : todos los elementos secundarios del objeto de árbol
  • $max_depth : el límite máximo de profundidad que podemos explorar
  • $profundidad : el nivel en el que nos encontramos actualmente
  • $args : argumentos opcionales adicionales
  • $salida : la salida HTML actual.

Ahora demostraremos un ejemplo para cada tipo de datos utilizando una instalación de WordPress con el tema Twenty Twenty activado.

Personalización de una estructura de menú

La función wp_nav_menu() que usa WordPress para mostrar menús está incluida en el archivo wp-includes/nav-menu-template.php . En este archivo, WordPress también solicita la clase Walker_Nav_Menu alrededor de la línea 605.

 function walk_nav_menu_tree( $items, $depth, $r ) { $walker = ( empty( $r->walker ) ) ? new Walker_Nav_Menu : $r->walker; return $walker->walk( $items, $depth, $r ); }

La clase Walker_Nav_Menu se define dentro del archivo wp-includes/class-walker-nav-menu.php y básicamente es todo el contenido del archivo.

Para mostrar la salida del menú, el código de WordPress utiliza las propiedades y los métodos de la clase Walker_Nav_Menu que se describen en este archivo.

Por ejemplo, arreglemos un problema bien conocido al que se enfrentan muchos desarrolladores, que es cambiar el elemento de los elementos del menú principal con un enlace personalizado vacío ('#') para evitar que los visitantes hagan clic en ellos.

Para permitirnos comparar nuestros resultados, primero crearemos un clon del menú principal simplemente agregando el código a continuación en header.php justo después del inicio del elemento <header> .

 <header class="header-footer-group" role="banner"> <?php wp_nav_menu( array( 'menu_class' => 'primary-menu reset-list-style' ) ); ?>

Lo que realmente hicimos aquí fue regenerar el menú principal y heredar su funcionalidad desplegable y CSS agregando sus clases primary-menu reset-list-style también al nuevo menú.

Ahora en nuestro archivo functions.php crearemos una clase que extienda la clase Walker_Nav_Menu. Como queremos cambiar el tipo de elemento, anularemos el método start_el .

 if ( !class_exists('My_Custom_Nav_Walker') ) { class My_Custom_Nav_Walker extends Walker_Nav_Menu { function start_el(&$output, $item, $depth=0, $args=[], $id=0) { $output .= "<li class='" . implode(" ", $item->classes) . "'>"; if ($item->url && $item->url != '#') { $output .= '<a href="' . $item->url . '">'; } else { $output .= '<span>'; } $output .= $item->title; if ($item->url && $item->url != '#') { $output .= '</a>'; } else { $output .= '</span>'; } } } }

Así que envolvimos cada elemento normalmente con una etiqueta <li> y luego, con el uso de la declaración if, agregamos un lapso cuando un enlace es "#" y una etiqueta <a> para el resto.

Para aplicar esto a nuestro menú, volvemos al código de menú que agregamos anteriormente y especificamos el parámetro walker:

 wp_nav_menu( array( 'walker' => new My_Custom_Nav_Walker, 'menu_class' => 'primary-menu reset-list-style' ) );

Ahora el resultado debería verse así:

Si ahora pasa el cursor sobre 'Servicios' en el elemento del menú, no aparecerá ningún cursor de mano y tampoco se puede hacer clic en este elemento del menú. Sin embargo, el submenú desplegable seguirá mostrándose correctamente.

Personalización de categorías

Primero vaya al área de administración y cree algunas categorías y subcategorías de publicaciones para tener un árbol de categorías para la demostración.

Después de eso, generaremos una lista de categorías agregando este código en algún lugar de header.php . Puede ponerlo después del inicio del elemento de encabezado como antes.

 <header class="header-footer-group" role="banner"> <?php wp_list_categories( array('hide_empty' => FALSE) ); ?>

La función es una función incorporada de WordPress que genera una salida HTML de un árbol de categorías. De forma predeterminada, solo muestra las categorías que contienen publicaciones, por eso usamos la opción hide_empty para mostrar también las categorías vacías y ver la jerarquía completa para los fines de este ejemplo.

Como anteriormente, podemos crear una clase personalizada en functions.php para ampliar la clase Walker_Category predeterminada que se describe en el archivo wp-includes/class-walker-category.php y aplicar nuestros cambios. Por ejemplo, agregaremos algunos íconos antes de los nombres de las categorías agregando este código:

 if ( !class_exists('My_Category_tree_Walker') ) { class My_Category_tree_Walker extends Walker_Category { function start_el(&$output, $item, $depth=0, $args=array(),$current_object_id = 0) { $output.= '<li><a href="'.home_url('category/'.$item->slug).'"> <img src="http://path/to/mages/'.($item->slug).'.jpg"> '.esc_attr($item->name); } } }

Para que esto funcione, por supuesto, deberá preparar imágenes adecuadas y guardarlas en la carpeta definida. Estas imágenes deberían seguir un formato de nombre específico que, en este ejemplo, sería "post-category-1", "post-subcategory-1", "post-category-3.jpg", etc.

Personalización de comentarios

Actualizar el menú y la lista de categorías es, con mucho, las razones más comunes por las que puede personalizar una clase Walker, pero a veces también debe implementar la misma técnica para los comentarios. Si, por ejemplo, desea cambiar la metainformación junto a la imagen de Gravatar en la sección de comentarios, podemos hacerlo fácilmente ampliando la clase Walker_Comment que se encuentra en el archivo wp-includes/class-walker-comment.php.

En el archivo functions.php agrega este código

 if ( !class_exists('My_Comment_Walker') ) { class My_Comment_Walker extends Walker_Comment { protected function html5_comment( $comment, $depth, $args ) { $tag = ( 'div' === $args['style'] ) ? 'div' : 'li'; ?> <<?php echo $tag; ?> <?php comment_class( $this->has_children ? 'parent' : '', $comment ); ?>> <article class="comment-body"> <footer class="comment-meta"> <div class="comment-author vcard"> <?php if ( 0 != $args['avatar_size'] ) echo get_avatar( $comment, $args['avatar_size'] ); ?> <?php printf( __( '%s <span class="says">says:</span>' ), sprintf( '<span class="fn">%s</span>', get_comment_author_link( $comment ) ) ); ?> </div><!-- .comment-author --> <div class="comment-metadata"> <?php $user_id=$comment->user_id; ?> <p class="commenter-bio"><?php the_author_meta('description',$user_id); ?></p> <p class="commenter-url"><a href="<?php the_author_meta('user_url',$user_id); ?>" target="_blank"><?php the_author_meta('user_url',$user_id); ?></a></p> </div><!-- .comment-metadata --> <?php if ( '0' == $comment->comment_approved ) : ?> <p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.' ); ?></p> <?php endif; ?> </footer><!-- .comment-meta --> <div class="comment-content"> <?php comment_text(); ?> </div><!-- .comment-content --> <?php comment_reply_link( array_merge( $args, array( 'add_below' => 'div-comment', 'depth' => $depth, 'max_depth' => $args['max_depth'], 'before' => '<div class="reply">', 'after' => '</div>' ) ) ); ?> </article><!-- .comment-body --> <?php } } }

Como puede notar al comparar el código about con el contenido del Walker_Comment original, el único cambio necesario fue en el método html5_comment que básicamente genera un comentario en formato HTML5.

Después de eso, tenemos que mostrar la lista de comentarios usando la función incorporada wp_list_comments con los argumentos correctos para mostrar el HTML del objeto similar a un árbol de comentarios.

 wp_list_comments( array( 'page' => 143, 'walker' => new My_Comment_Walker ));

Insertamos el código en la misma línea de header.php que hicimos antes y usamos el ID de la publicación que contiene los comentarios. Por supuesto, puede simplemente reemplazar el código relacionado con el comentario de su plantilla y omitir la opción 'página' para que se aplique a la sección de comentarios de todos sus artículos.

Si actualiza la interfaz de su sitio web ahora, notará las entradas de información adicionales (biografía del autor y URL del autor) que agregamos en el código personalizado anterior.

Conclusión

Con suerte, lo anterior le ha dado una idea del uso de WordPress Walker Class. En todos los ejemplos, aplicamos cambios directamente a los archivos del tema principal. Si bien eso está bien para fines de demostración, obviamente querrá asegurarse de que solo aplica ediciones a un tema secundario en la práctica para asegurarse de que estas actualizaciones no se sobrescriban cuando se actualice WordPress o el tema utilizado.