Hacer que los enlaces permanentes de tipo de publicación personalizada jerárquica funcionen igual que las páginas


16

He revisado todas las preguntas aquí en enlaces permanentes de tipo de publicación personalizada, pero la mayoría parecen ser problemas con reescrituras de taxonomía personalizadas o la obvia falta de flush_rewrite_rules (). Pero en mi caso, solo estoy usando un tipo de publicación personalizado (sin taxonomía), configurado para ser jerárquico (para poder asignar relaciones padre-hijo), con el "soporte" adecuado para los metabox de atributos, etc., etc. He sonrojado reescribir las reglas de mil maneras diferentes. He probado diferentes estructuras de enlaces permanentes. ¡Pero las URL secundarias siempre resultan en 404!

Originalmente tenía tipos de publicaciones personalizadas independientes para los elementos "padre" e "hijo" (usando p2p), y probablemente no habría tenido problemas para usar una taxonomía para la agrupación "parental": sé que serían semánticamente más precisos. Pero para el cliente, es más fácil para ellos visualizar la jerarquía cuando las "publicaciones" se muestran en el administrador al igual que las páginas: un árbol simple donde los niños aparecen debajo del padre, con el prefijo "-", y en el orden apropiado. Además, se pueden usar varios métodos para asignar el orden mediante arrastrar y soltar. La agrupación a través de la taxonomía (o p2p) da como resultado una lista plana de "publicaciones" en las listas de administración, lo que simplemente no es tan visualmente obvio.

Entonces, lo que busco es literalmente el mismo comportamiento que las "páginas" principales, pero con mi tipo de publicación personalizada. He registrado el tipo de publicación tal como se esperaba, y en el administrador funciona perfectamente: puedo asignar un padre y un menú_orden para cada "publicación" del boletín, aparecen correctamente en las listas de edición:

Spring 2012
 First Article
 Second Article

Y sus enlaces permanentes parecen estar construidos correctamente. De hecho, si cambio algo sobre la estructura, o incluso modifico la ficha de reescritura al registrar el tipo de publicación, se actualizan automáticamente correctamente, por lo que sé que algo funciona:

http://mysite.com/parent-page/child-page/                  /* works for pages! */
http://mysite.com/post-type/parent-post/child-post/        /* should work? */
http://mysite.com/newsletter/spring-2012/                  /* works! */
http://mysite.com/newsletter/spring-2012/first-article/    /* 404 */
http://mysite.com/newsletter/spring-2012/second-article/   /* 404 */

También tengo "páginas" básicas estándar con relaciones jerárquicas creadas, y se ven igual en el administrador, pero en realidad también funcionan en el front-end (las URL principales y secundarias funcionan bien).

Mi estructura de enlace permanente está establecida en:

http://mysite.com/%postname%/

También intenté esto (solo porque muchas otras respuestas parecían indicar que era necesario, aunque no tenía sentido en mi caso):

http://mysite.com/%category%/%postname%/

Mis registros de CPT incluyen:

$args = array(
    'public'                => true,
    'publicly_queryable'    => true,
    'show_ui'               => true,
    'has_archive'           => 'newsletter',
    'hierarchical'          => true,
    'query_var'             => true,
    'supports'              => array( 'title', 'editor', 'thumbnail', 'page-attributes' ),
    'rewrite'               => array( 'slug' => 'newsletter', 'with_front' => false ),

La única diferencia visible entre mis hijos de tipo de publicación personalizada y los hijos de página normales , es que mi CPT tiene la babosa al comienzo de la estructura de enlace permanente, luego seguida de las babosas padre / hijo (donde las páginas solo comienzan con las babosas padre / hijo, sin "prefijo"). Por qué esto arruinaría las cosas, no lo sé. Muchos artículos parecen indicar que así es exactamente como deberían comportarse tales enlaces permanentes de CPT jerárquicos, pero los míos, aunque bien formados, no funcionan.

Lo que también me desconcierta es cuando examino los query_vars para esa página 404: parecen contener los valores correctos para que WP "encuentre" mis páginas secundarias, pero algo no funciona.

$wp_query object WP_Query {46}
public query_vars -> array (58)
'page' => integer 0
'newsletter' => string(25) "spring-2012/first-article"
'post_type' => string(10) "newsletter"
'name' => string(13) "first-article"
'error' => string(0) ""
'm' => integer 0
'p' => integer 0
'post_parent' => string(0) ""
'subpost' => string(0) ""
'subpost_id' => string(0) ""
'attachment' => string(0) ""
'attachment_id' => integer 0
'static' => string(0) ""
'pagename' => string(13) "first-article"
'page_id' => integer 0
[...]

He intentado esto con varios temas, incluyendo veintiocho, solo para asegurarme de que no falte alguna plantilla de mi parte.

Usando Rewrite Rules Inspector, esto es lo que aparece en la url: http://mysite.com/newsletter/spring-2012/first-article/

newsletter/(.+?)(/[0-9]+)?/?$   
       newsletter: spring-2012/first-article
           page: 
(.?.+?)(/[0-9]+)?/?$    
       pagename: newsletter/spring-2012/first-article
           page: 

cómo se muestra en otra página del inspector:

RULE:
newsletter/(.+?)(/[0-9]+)?/?$
REWRITE:
index.php?newsletter=$matches[1]&page=$matches[2]
SOURCE:
newsletter

Esta salida de reescritura me llevaría a creer que el siguiente enlace permanente "no bonito" funcionaría:

http://mysite.com/?newsletter=spring-2012&page=first-article

No es 404, pero muestra el "boletín" del elemento CPT principal, no el secundario. La solicitud se ve así:

Array
(
    [page] => first-article
    [newsletter] => spring-2012
    [post_type] => newsletter
    [name] => spring-2012
)

Respuestas:


15

Esta es la primera vez que participo aquí en Stack Exchange, pero lo intentaré y veré si puedo ayudarlo a orientarlo en la dirección correcta.

Por defecto, los CPT jerárquicos se comportan exactamente de la manera que usted ha descrito. El único prefijo de babosa, "boletín informativo" en este caso, es dejar que el motor de reescritura sepa cómo distinguir las solicitudes de diferentes tipos de publicaciones.

Esos argumentos de registro de CPT se ven bien, pero cuando se solicita un CPT, la pagenamevar de consulta no debe tener un valor y la namevar de consulta debe ser la misma que newsletteraquí, por lo que parece que hay un conflicto en algún lugar de su configuración.

Para ayudar a depurar, instale y active el complemento Rewrite Rules Inspector , luego visite la pantalla en " Herramientas -> Reglas de reescritura ".

  1. Mientras mira la lista, todas sus reglas para el boletín CPT deben aparecer antes de cualquier regla de reescritura de páginas. Verifique que este sea el caso escaneando la columna " Fuente ".
  2. Si eso se verifica, ingrese la URL para su CPT del "primer artículo" en el campo " Coincidir URL " y haga clic en el botón "Filtro" para ver qué regla coincide. Debe coincidir con una regla de boletín y una regla de página, pero la regla del boletín debe ser la primera.

Si eso no revela ningún problema, busque en la post_namecolumna wp_postspara encontrar otras publicaciones con la babosa "primer artículo" para ver si puede haber una colisión. Haga una búsqueda de "boletín informativo" también, solo para estar seguro.

Agregue el siguiente fragmento para inspeccionar sus variables de consulta al principio de la solicitud para verificar y ver cuáles están configuradas por la coincidencia de la regla de reescritura (visite el CPT secundario en el front-end). Si la pagenamevar no aparece aquí, entonces algo se establece más adelante en la solicitud:

add_filter( 'request', 'se77513_display_query_vars', 1 );

function se77513_display_query_vars( $query_vars ) {
    echo '<pre>' . print_r( $query_vars, true ) . '</pre>';

    return $query_vars;
}

Cualquier complemento / función que modifique las variables de consulta podría estar causando un conflicto, así que deshabilítelo si aún ve problemas. También vacíe sus reglas de reescritura después de cada paso, especialmente si la solicitud coincide con una regla incorrecta en el segundo paso anterior (mantenga abierta la pantalla "Permalinks" en una pestaña separada y simplemente actualícela).


Edité la pregunta para mostrar el resultado del inspector de reglas de reescritura, ya que estos comentarios no permiten suficiente formato. Las reglas para el CPT se muestran en la parte superior de la lista, antes que nada, pero no estoy seguro de cuáles de las siguientes reglas son reglas de "página" (no está claro). Además, no hay colisiones en la post_namecolumna.
somático

¿Tienes alguna idea sobre la estructura de enlace permanente adecuada? He vuelto a hacerlo /%postname%/ya que incluir /%category%/solo parece confundir aún más las cosas en el inspector de reescritura. Incluso he visto a personas afirmar que /%category%/está mapeado mágicamente para que los CPT signifiquen "padre", aunque no creo que esto sea cierto.
somático

Esa salida parece venir para un complemento diferente, por lo que no se ve la "fuente" de la regla. De cualquier manera, parece que su regla coincide bien. Edité mi respuesta para incluir un fragmento para inspeccionar los vars de consulta anteriormente en la solicitud para asegurarme de que estén configurados correctamente.
Brady Vercher

En cuanto a la estructura de enlaces permanentes, no soy fanático de incluir la categoría. Es solo otra parte móvil que no ayuda en nada, y las publicaciones pueden pertenecer a múltiples categorías. Si hay alguna posibilidad de que pueda cambiar la estructura de enlaces permanentes en el futuro o si quisiera que se cargara otro CPT sin un prefijo slug, recomendaría "espaciar los nombres" de su estructura con algo fijo y único como /blog/%postname%/.
Brady Vercher

es el complemento correcto, pero hay dos páginas: "rewrite analyzer" y "rewrite rules", que ofrecen una URL de prueba. Probé la otra página y mostró la fuente como "programa" para el primer grupo sangrado, y "página" para el segundo.
somático

5

El parent/Childenlace permanente funciona fuera de la caja siempre que establezca

'hierarchical'=> true,
'supports' => array('page-attributes' ....

Actualizar:

Acabo de probarlo nuevamente y funciona como se esperaba, con este caso de prueba:

add_action('init','test_post_type_wpa77513');
function test_post_type_wpa77513(){
    $args = array(
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true, 
        'show_in_menu' => true, 
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'post',
        'has_archive' => true, 
        'hierarchical' => true,
        'supports' => array( 'title', 'editor', 'thumbnail', 'page-attributes' )
    ); 

    register_post_type( 'newsletter', $args );
}

y el enlace permanente configurado para /%postname%/obtener el boletín / padre / hijo trabajando bien.


mi código anterior no lo mostró, pero tengo page-attributesen los soportes (que en realidad solo se trata de mostrar el metabox para asignar la paternidad, no debería afectar los enlaces permanentes), sino obtener 404's. ¿Qué estructura de enlace permanente debe establecerse? o importa?
somático

@somatic, lo probé nuevamente y está funcionando bien, en cuanto al enlace permanente, no estoy seguro de si debería importar, pero de alguna manera actualicé mi respuesta.
Bainternet

Puedo confirmar que, con la adición de una matriz de argumentos para 'etiquetas' (sin las cuales CPT no aparecerá en el administrador), este ejemplo básico funciona en una instalación de vainilla de WP3.5 con veinte veces. Pero me doy cuenta de algunas diferencias clave en sus register_post_type$ args: solía 'rewrite' => array( 'slug' => 'newsletter', 'with_front' => false ), donde usaste solo true. También simplemente pasaste truepor has_archive, donde pasé la babosa. Sin embargo, cuando emparejé sus argumentos, todavía obtuve 404 ... Todavía trato de localizar dónde me estoy equivocando.
somático

3

Además de preguntar »¿Has intentado apagarlo y volver a encenderlo?« , También tengo que preguntar "¿Tienes algún plugin activo y tu Tema está haciendo algo en los enlaces permanentes (por ejemplo: registrar taxonomía, publicar tipos, agregar reglas de reescritura) , etc.)?

Si es así: ¿Sigue sucediendo esto después de deshabilitar todos los complementos y cambiar a TwentyEleven? ingrese la descripción de la imagen aquí

Para depurar aún más, dirígete a GitHub y toma el plugin Toschos "Rewrite" . Luego cambie al repositorio oficial de complementos en wp.org y obtenga el complemento MonkeyManRewriteAnalyzer . Incluso escribí una pequeña extensión para unir ambas cosas. Esto le dará muchos detalles sobre su configuración.


bueno, si desactivo todo , no tendré el tipo de publicación personalizada que es el punto de esta pregunta ... pero sí, lo he intentado incluso con el tema veintiocho. Todavía estoy investigando los pocos enchufes necesarios para ver qué está alterando la consulta, ya que, por lo que puedo ver, los enlaces permanentes están bien formados.
somático

@somatic Por supuesto que no desactiva el tuyo :)
kaiser

@somatic Ver actualización.
kaiser

1

Entonces, después de confirmar que podía obtener el comportamiento de página jerárquico esperado con una instalación completamente limpia y solo una declaración de CPT, supe que la falla se encontraba en algún lugar dentro de mi propio complemento que uso para manejar la creación de CPT (muy complejo, maneja metaboxes personalizados, taxonomías , etc.) El problema era que, a pesar de todos los consejos para verificar problemas de reescritura o consulta, no pude ver nada obviamente malo. Revisé todos los filtros y enlaces, visualicé la consulta en cada punto y no vi nada que causara el 404.

Así que me quedaba la tarea de deshabilitar / habilitar manualmente cada una de las 9 clases grandes, y luego, encontrar al menos 2 de ellas que causaban el 404, pasar por cada función una por una y deshabilitarlas / habilitarlas, y luego rastrear la línea por línea dentro de esas funciones: un intento de fuerza bruta para ver exactamente qué estaba causando el 404, incluso si no sabía por qué.

Fue entonces cuando descubrí que hay una consecuencia del uso $query->get_queried_object(). Parecería que el uso de esta función de contenedor en realidad modifica $ query en sí, que pensé que estaba regresando sin cambios al final de mi función. Tres filtros se distribuyen en 2 clases estaban involucrados que modificó la consulta: parse_query, posts_orderby, posts_join- y todas las funciones de devolución de llamada llamaban $query->get_queried_object()en el pasado $queryarg a continuación, ejecutar algunas pruebas condicionales y, a veces modificar la consulta vars (como en los casos especiales de orden de clasificación). Por extraño que parezca, estas funciones realmente funcionaron bien para lo que fueron diseñadas para hacer, a pesar de mi uso de la función. ¡Nunca noté nada malo con la consulta $ devuelta!

De alguna manera, después de más de un año de desarrollo y uso en docenas de sitios de producción en vivo, nunca había experimentado ningún efecto adverso por este error. Solo cuando me aventuré en CPT jerárquicos, esta pequeña diferencia de repente rompió las cosas. Eso es parte de lo que me sorprendió tanto con esto: lo mejor que pude ver, ¡mis filtros de consulta fueron confiables!

Confieso que todavía no sé exactamente por qué llamar a esta función rompe solo este pequeño aspecto de las páginas secundarias de CPT, ¡y sin embargo nunca manifesté ningún otro problema! Pero estaba claro que usarlo dentro de una devolución de llamada de filtro destrozó el devuelto de $queryalguna manera. Al eliminar esta llamada, mis errores 404 desaparecieron.

Gracias por todos los consejos, ojalá pudiera dividir la recompensa, ya que obtuve información de cada respuesta, incluso si la solución final no estaba relacionada. Esta ha sido una lección educativa para no confiar ciegamente en su código, incluso si ha funcionado de manera confiable durante mucho tiempo, o no está produciendo ningún error obvio.

A veces, como la tabla de Kaiser encarna tan claramente, solo tienes que comenzar a encender los interruptores hasta que las luces vuelvan a encenderse. En mi caso, tuve que tomar la misma estrategia de solución de problemas hasta las líneas individuales de una función antes de poder ver el problema.


También puede usar la función de contenedor get_queried_object()sin interceptar el $wpdbobjeto.
kaiser

pero $queryque agarra eso? Estoy usando esto dentro de un filtro para parse_query, y necesito obtener específicamente el objeto consultado de un específico $queryque se pasa del filtro ...
somático

Solo intenté usar el contenedor dentro de mi filtro para parse_query. Causó los mismos errores 404 nuevamente. Tengo que encontrar alguna manera de replicar lo que get_queried_object()hace sin ensuciar estos filtros ...
somático

-2

¿Está ejecutando la versión más reciente de WP? Supongo que esa es la primera pregunta (como cuando llamas al soporte técnico y te preguntan si tu computadora está conectada), ya que he leído que este problema se abordó en la actualización de la versión más reciente.

Hay una publicación en digwp.com que aborda este problema (http://digwp.com/2011/06/dont-use-postname/). Aparentemente, WP no puede distinguir fácilmente la diferencia entre publicaciones y páginas, y si comienzas tus URL con una opción basada en texto, WP activa una bandera que crea una regla para cada página / publicación que tienes. Si tiene mucho contenido en su sitio, eso puede generar una gran cantidad de solicitudes y su servidor probablemente agote el tiempo de espera, lo que resultará en un montón de 404 incluso si las páginas están allí.

Entonces. Si utiliza primero una estructura basada en números, luego su estructura basada en texto, apostaría a que su problema 404 se resolvería. Ahora, considerando los problemas de SEO, no usaría una estructura de fecha, pero tomar esa decisión será lo suficientemente lógico para usted.


2
Estoy en 3.5. A partir de WP3.3.1, este problema en digiwp está solucionado.
somático
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.