Type de publication personnalisé en tant que page parent

4

Il existe donc un million d'extraits expliquant comment obtenir des pages en tant que parents de types d'articles personnalisés.

Cependant, l'inverse semble discutable. On pourrait penser, puisque tout dans WordPress est techniquement un "post", ce serait trivial. Cependant, ce n’est pas le cas.

Jusqu'à présent, j'ai:

add_filter( 'page_attributes_dropdown_pages_args',
  function( $dropdown_args, $post = null ) {
    $dropdown_args['post_type'] = 'portal';
    return $dropdown_args;
  } );

Et bien entendu, les pages me permettent maintenant de sélectionner les publications portal -type en tant que parents. Les URL semblent bien s’inscrire correctement dans wordpress, bien qu’elles soient toutes 404.

Comment puis-je faire en sorte que wordpress comprenne cette hiérarchie et charge les pages contenant des publications en tant que parents?

    
posée Qix 26.01.2015 - 07:27

3 réponses

6

WordPress utilise un ensemble de règles de réécriture pour pouvoir convertir une URL en requête sur une base de données.

La regex qui gère les urls pour les pages est très générale, le code IIRC est quelque chose comme (.+.?)/? , il indique pratiquement que tout n'a pas déjà été égalé par d'autres règles.

Pour cette raison, il n'est pas possible d'écrire une règle de réécriture qui fonctionnera dans votre cas: vous ne pouvez pas distinguer via regex que dans une URL telle que example.com/my-portal/sample-page , la partie 'mon-portail' est un CPT et sample-page est une page.

Les choses deviennent plus complexes si vous avez plus de niveaux d'imbrication: my-portal/my-portal-child/sample-page .

Pour gérer ce type d’URL, WordPress utilise la fonction get_page_by_path() : il explose l’URL de la page en / , obtenant des slugs de page, puis interroge la base de données pour tous les pages contenant ces slug.

Par exemple, si vous avez une page dont le slug est "exemple de page" et que vous définissez comme parent les CPT "mon-portail" , les appels WordPress:

get_page_by_path('my-portal/sample-page')

mais il ne renvoie aucun résultat, car il recherche une page avec un slug "page-échantillon" dont le parent est une autre page avec un slug "mon-portail". . Cette page n’existant pas, vous obtenez donc l’erreur 404.

Cependant, get_page_by_path() accepte comme troisième argument un tableau de types d'articles: si vous le définissez à array('page', 'portal') alors la fonction pourra trouver correctement la page.

Vous pouvez donc résoudre le problème en définissant manuellement l'ID de la page (récupéré comme expliqué ci-dessus) dans les vars de requête WP.

Le crochet 'parse_request' est parfait pour la portée:

  • il s'exécute après l'analyse de l'URL
  • il transmet aux callbacks l'instance de $wp object que vous pouvez utiliser pour définir des vars de requête

Code:

add_action('parse_request', function ($wp) {
  // only if WP found a page
  if (isset($wp->query_vars['pagename']) && ! empty($wp->query_vars['pagename'])) {
    $page = get_page_by_path( // let's find the page object
        $wp->query_vars['pagename'],
        OBJECT,
        array('page', 'portal') // we need to set both post types
    );
    if ($page instanceof WP_Post) { // if we find a page
        unset($wp->query_vars['pagename']); // remove pagename var
        $wp->query_vars['page_id'] = $page->ID; // replace with page_id query var
    }
  }
});

Ce code, associé au filtre de OP, est tout ce dont vous avez besoin.

Notez que le code fonctionne même avec des portails hiérarchiques imbriqués.

    
réponse donnée gmazzap 29.01.2015 - 08:13
0
La

So @ gmazzap a donc réponse un point dans la bonne direction. Cependant, pour une raison quelconque, var_dump($wp->query_vars) ne montrait qu'un tableau avec une clé, attachment , ce qui n'a pas aidé du tout.

Cependant, cela a montré comment je pouvais y parvenir en utilisant un peu plus de ruse.

Le script ci-dessous obtient une page uniquement si la hiérarchie est correcte. c'est-à-dire que le parent de chaque slug correspond à un message avec le slug approprié ( 0 pour le premier slug, bien sûr).

De plus, il saute les chemins avec 0 ou 1 slug simplement parce que ceux-ci désignent généralement des pages spéciales que WordPress devrait gérer (de plus, peu importe la hiérarchie des pages ...)

Et non, la requête ne peut pas vraiment être trop optimisée. Cela est dû au fait que MySQL ne prend pas en charge les sélections / jointures récursives comme vous le souhaiteriez dans un modèle de données hiérarchique.

function get_page_by_slug_path( $path ) {
  global $wpdb;
  global $table_prefix;

  $slugs = explode(
    '/',
    preg_replace(
      '~\/+~',
      '/',
      preg_replace(
        '~^\/*(.+?)\/*$~',
        '$1',
        $path
      )
    )
  );

  # Skip if slugs length is 1 or 0, of course.
  #   A single 'slug' URL may mean something completely different, so
  #   we'll bank on WordPress knowing what to do with it.
  if( count( $slugs ) < 2 ) {
    return;
  }

  $parents = [ 0 ];
  foreach( $slugs as $slug ) {
    $sql = $wpdb->prepare(
      "SELECT ID FROM ${table_prefix}posts WHERE post_name='%s' AND post_parent IN ("
      . implode( ',', $parents )
      . ")",
      $slug
    );

    $results = $wpdb->get_results( $sql );

    if( count( $results ) === 0 ) {
      return null;
    }

    $parents = array_map(
      function( $elem ) {
        return $elem->ID;
      },
      $results
    );

  }

  if( count( $parents ) > 1 ) {
    trigger_error( E_USER_WARNING, "Multiple IDs for this page slug: "
      . implode( ', ', $parents ) );
  }

  return intval( $parents[0] );
}

add_action('parse_request', function ($wp) {
  $path = parse_url(
    "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
    PHP_URL_PATH
  );

  $pageID = get_page_by_slug_path( $path );

  if( $pageID ) {
    $wp->query_vars = [ 'page_id' => $pageID ];
  }
});
    
réponse donnée Qix 03.02.2015 - 04:58
-1
  add_action('admin_menu', function() { remove_meta_box('pageparentdiv', 'chapter', 'normal');});
  add_action('add_meta_boxes', function() { add_meta_box('chapter-parent', 'Part', 'chapter_attributes_meta_box', 'chapter', 'side', 'high');});
  function chapter_attributes_meta_box($post) {
    $post_type_object = get_post_type_object($post->post_type);
    if ( $post_type_object->hierarchical ) {
      $pages = wp_dropdown_pages(array('post_type' => 'part', 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __('(no parent)'), 'sort_column'=> 'menu_order, post_title', 'echo' => 0));
      if ( ! empty($pages) ) {
        echo $pages;
      } // end empty pages check
    } // end hierarchical check.
  }

Essayez cette réponse par: enlace

    
réponse donnée TTech IT Solutions 26.01.2015 - 10:29

Lire d'autres questions sur les étiquettes