Cómo agregar un Enlace Personalizado a un Menú con una URL relativa a la URL del blog
Parte de mi trabajo es crear sitios web en WordPress. Normalmente trabajo en mi portátil hasta tener algo lo suficientemente bueno para subirlo al servidor de pruebas donde el cliente lo revisa.
Creo un VirtualHost para cada nuevo proyecto, así que siempre trabajo con una instalación de WordPress en un dominio que se ve como http://local.example.com/
, pero cuando el sitio se sube al servidor de pruebas (no controlado por mí), el dominio puede terminar siendo algo como http://testserver.com/arbitrary/path/example/
.
El problema es que si agrego un enlace personalizado a un menú que apunte a, por ejemplo, /events/
, funcionaría bien localmente creando un enlace a http://local.example.com/events/
, pero en el servidor de pruebas, el enlace apuntará a http://testserver/events/
, lo cual obviamente no es correcto.
Lo que quiero es dar al enlace personalizado una URL que funcione tanto en mi entorno local como en el servidor de pruebas.
Ya manejo el problema de cambiar las opciones home
y siteurl
de WordPress mediante:
- cambiar esas configuraciones en la base de datos local
- crear un volcado de la base de datos
- actualizar la base de datos en el servidor
- restaurar las opciones locales.
No quiero usar URLs completas para los enlaces personalizados y tener que reemplazarlas con la URL del servidor cada vez que necesito actualizar la base de datos del servidor.
Para enlaces dentro del contenido de las entradas, existe un plugin que resuelve el problema agregando dos shortcodes: http://wordpress.org/extend/plugins/url-shortcodes/, pero no he podido encontrar algo similar para Enlaces Personalizados.
Esto funciona pero también cambia la URL para incluir el index.php. En el caso de una aplicación de una sola página con enlaces #, primero actualizaría la página y luego te llevaría al destino (solo la primera vez). Aun así, es una buena idea

Puedes usar el filtro nav_menu_link_attributes
para inspeccionar y modificar el atributo href de cada elemento del menú antes de que se muestre.
En este ejemplo, buscamos cualquier atributo href que comience con /
, y le anteponemos la URL del sitio de prueba en ese caso:
function wpd_nav_menu_link_atts( $atts, $item, $args, $depth ){
if( '/' == substr( $atts['href'], 0, 1 ) ){
$atts['href'] = 'http://testserver.com/example' . $atts['href'];
}
return $atts;
}
add_filter( 'nav_menu_link_attributes', 'wpd_nav_menu_link_atts', 20, 4 );
Podrías crear un plugin simple con este código y activarlo solo en tu servidor de prueba, o crear algún tipo de bandera que aplique este filtro condicionalmente cuando esté presente el entorno del sitio de prueba.

Usar la etiqueta <base href=" ">
en el meta del head proporcionará una URL base para todos los enlaces relativos en la página.
Referencia:
https://www.w3.org/TR/html4/struct/links.html
12.4 Información de ruta: el elemento BASE
Enlaces personalizados relativos en WordPress:
Si quieres que la URL del sitio sea la URL base de todos los enlaces, añade esto en theme / header.php dentro del <head>
:
<base href="<?php echo site_url(); ?>/">
Sé que puede ser tarde para ti, pero podría ayudar a alguien más.

Parece prometedor. Lo probaré y reportaré los resultados.

No funciona con rutas como ehepperle.com/sites/in-progress/some-wp-site-root/
a menos que establezcas explícitamente la raíz del sitio. La velocidad de desarrollo web no mejora notablemente al usar la etiqueta base
, ya que cuando migras a otro sitio, tendrás que redefinir cuál es la base. Sin embargo, puedo ver el valor en reducir la longitud de los valores href.

En la configuración de Menú, en una URL personalizada, es posible usar enlaces relativos al [blogurl]. El secreto es comenzar la URL relativa con una sola /
. Cuando una sola / inicia la URL personalizada, el sistema no antepondrá el típico http://
y luego la URL actual del blog se generará en la URL de destino en tiempo de ejecución.
EJEMPLO
Si deseas ir a tu página de inicio, simplemente coloca /
como la URL personalizada.
Si deseas ir a la página índice en la carpeta bbforums
, entonces coloca /bbforums
como la URL personalizada.
Esto te permite mover un sitio a un dominio de prueba sin tener que codificar manualmente el nuevo blogURL en todos los enlaces personalizados de los menús.
Por ejemplo:
Si mi blog es http://example.com
y quiero probarlo en un subdominio http://test.example.com
, el sitio se puede mover entre prueba y producción sin problemas de menús usando la convención de URL relativa mencionada anteriormente. He probado con éxito este enfoque usando el plugin XCloner para mover el sitio.

Esto no funciona para URLs de blog que tienen barras, por ejemplo http://www.example.com/blog/. Si sigues el elemento del menú '/', solo te llevaría a http://example.com.

Primero debes instalar este plugin para shortcodes de URL.
Añade este código a tu archivo functions.php
en tu tema:
class description_walker extends Walker_Nav_Menu {
function start_el( &$output, $item, $depth, $args ) {
global $wp_query;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
$class_names = ' class="'. esc_attr( $class_names ) . '"';
$output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';
$attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) . '"' : '';
$attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) . '"' : '';
$attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) . '"' : '';
// echo $item->url;
$string = explode( '::', $item->url, 3 );
if ( $string[1] ) {
$string[1] = str_replace( '-', ' ', $string[1] );
$item->url = do_shortcode( "[$string[1]]" );
}
$attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : '';
$prepend = '<strong>';
$append = '</strong>';
$description = ! empty( $item->description ) ? '<span>' . esc_attr( $item->description ) . '</span>' : '';
if ( $depth != 0 ) {
$description = $append = $prepend = "";
}
$item_output = $args->before;
$item_output .= '<a'. $attributes . '>';
$item_output .= $args->link_before . $prepend . apply_filters( 'the_title', $item->title, $item->ID ) . $append;
$item_output .= $description . $args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
Luego debes llamar la función wp_nav_menu
desde los archivos de plantillas:
$arg = array(
'menu' => "main-menu",
'echo' => true,
'fallback_cb' => 'wp_page_menu',
'depth' => 0,
'walker' => new description_walker()
);
wp_nav_menu( $arg );
Eso es todo. Luego ve a la sección de menús en el back-end.
Por ejemplo, si quiero dar la URL de una página a un enlace personalizado, lo añadiré así:
http://::blogurl-id='1302'::
Ahora puedes ir al front-end y comprobar que el shortcode funciona.
