web-dev-qa-db-fra.com

Comment forcer une requête conditionnelle?

Il existe un bug de longue date dans WordPress ( # 16373 ) dans lequel, si des variables de requête personnalisées sont enregistrées et présentes dans la chaîne de requête, la requête ne définira pas is_front_page() true, même si 'page' == get_option( 'show_on_front' ). Tous les détails se trouvent dans le ticket de traçage, mais le résultat final est que la page de couverture renvoie une page non valide au lieu de get_option( 'page_on_front' ).

J'ai un certain cas d'utilisation dans lequel je dois passer des variables de requête personnalisées à la chaîne de requête sur la page d'accueil (en utilisant un formulaire pour transmettre les variables de requête enregistrées, qui sont à leur tour utilisées pour filtrer les options de thème - une démo d'options de thème front-end ). Le ticket de transport mentionné ci-dessus a été fermé comme invalide, donc j'ai besoin d'une solution de contournement.

Je peux forcer le modèle de page de couverture assez facilement, comme ceci:

function themeslug_force_front_page_template( $template ) {
    if ( '' != get_query_var( 'foobar' ) ) { // Registered custom query var
        return get_front_page_template();
    }
    return $template;
}
add_filter( 'template_include', 'themeslug_force_front_page_template' );

Toutefois, les conditions de requête sous-jacentes ne sont pas affectées. Ainsi, tout code dépendant de is_front_page() étant true (par exemple, un curseur qui apparaît uniquement sur la page d'accueil du site) ne sera toujours pas restitué correctement.

J'ai tenté de modifier $query à pre_get_posts, mais cela ne semble pas fonctionner:

function themeslug_force_static_front_page( $query ) {
    if ( $query->is_main_query() ) {
        if ( 'page' == get_option( 'show_on_front' ) ) {
            if ( '' != get_query_var( 'foobar' ) ) { // Registered custom query var
                $query->set( 'page_id', get_option( 'page_on_front' ) );
                $query->set( 'is_home', false );
                $query->set( 'is_page', true );
                $query->set( 'is_front_page', true );
            }
        }
    }
}
add_action( 'pre_get_posts', 'themeslug_force_static_front_page' );

Les conditions de la requête ne sont pas modifiées. Est-ce que j'essaie de manière incorrecte dans mon rappel? Existe-t-il un moyen différent/meilleur de forcer les conditions de requête, en particulier is_front_page()?

Modifier

Notez que la définition de page_id do fonctionne dans le rappel pre_get_posts:

$query->set( 'page_id', get_option( 'page_on_front' ) );

Si j'omets le filtre template_include, la page affichée est bien la page attribuée à la page de couverture; Cependant, get_page_template() est utilisé, plutôt que get_front_page_template(). Donc, définir page_id à pre_get_posts fait que is_page() soit vrai. Mais le bogue susmentionné empêche is_front_page() d'être défini sur true.

Modifier 2

Selon la requête de @ toscho, voici un code de requête var, pour le contexte.

Enregistrer les variables de requête:

/**
 * Add options-related query variables
 */
function themslug_add_theme_demo_query_vars( $qvars ) {
    $qvars[] = 'demo_foo';
    $qvars[] = 'demo_bar';
    $qvars[] = 'demo_baz';
    return $qvars;
}
add_filter( 'query_vars', 'themeslug_add_theme_demo_query_vars' );

(Où foo, bar et baz sont des options de thème - arrière-plan, différentes couleurs, etc.)

Leur utilisation consiste simplement à ajouter un filtre à une option de thème - cette partie n’entre pas dans le cadre de la question, je vais donc l’omettre ici.

Ils sont édités sur le front-end via un widget personnalisé. La sortie du widget est juste un formulaire. Voici un exemple de l'un des champs de formulaire:

<h3>Foo</h3>
<input name="demo_foo" id="demo_foo" class="pickcolor"  type="text" value="<?php echo $foo_setting; ?>" data-default-color="<?php echo $foo_setting; ?>" />

Chaîne de requête générée lors de l'envoi:

www.example.com/?foo=some_value
7
Chip Bennett

Avez-vous vérifié quelle partie de is_front_page () est en train de renvoyer false?

Je pourrais reproduire le problème en suivant la configuration à partir du ticket trac. Dans mon cas, dans cette fonction, l'appel à is_page () retournait false.

J'imagine que cela est dû à l'utilisation de $wp_query->set() pour page_id et is_page ne fait que modifier le query_vars, vous ne changez pas "l'état de la requête" lui-même.

J'ai pu créer une solution de contournement pour cela en ajoutant ces deux lignes à votre code:

$query->is_page = true;
$query->queried_object = get_post(get_option('page_on_front') );

Cela a eu pour résultat (dans ma configuration) que la page soit correctement affichée sur la page d'accueil (bien que la variable query_var soit présente dans l'URL) et que is_front_page() renvoie true.

J'espère que cela vous aide un peu plus loin.


Si vous regardez la définition de WP_Query class, vous verrez qu'il existe une variable $query_vars et une variable $is_page.

La fonction set que vous avez utilisée ($query->set( 'is_page', true );) définit uniquement un query var :

function set($query_var, $value) {
    $this->query_vars[$query_var] = $value;
}

Il ne modifie pas les informations d'état enregistrées dans $query->is_page = true, mais définit la requête var $query->query_vars['is_page'] = true.

C'est un peu trompeur si vous venez d'une approche POO et comprenez WP_Query::set() en tant que fonction classique d'établissement de classes - ce qui n'est pas le cas.

7
s1lv3r

J'ai également répondu à ce billet Trac, mais je pense que le problème de base est beaucoup plus simple que cela.

Vous accrochez demo_foo, demo_bar, demo_baz en tant que "variables de requête", mais elles ne le sont pas; du moins, pas dans le sens voulu.

Alors que la chaîne? Foo = barre après l'URL est souvent appelée la chaîne de requête, les "variables de requête" sont en réalité simplement des variables qui affectent la requête principale. Si vous n'accrochez pas une variable, elle ne disparaît pas, elle n'est simplement pas lue par l'objet principal WP_Query.

Et dans votre cas, cela semble être exactement ce que vous voulez. Vos variables sont des options de thème, elles ne font pas partie de la requête principale (qui reçoit des publications de la base de données). Vous ne les utilisez pas pour sélectionner les publications à afficher, vous les utilisez pour définir des options de thème, etc.

Si vous ne les accrochez pas en tant que query_vars, ils n'affecteront pas du tout l'objet WP_Query principal. Vous devrez les obtenir à partir du superglobal $ _GET principal au lieu d'utiliser get_query_var et vous devrez les désinfecter correctement pour éviter les attaques XSS réfléchies (en utilisant esc_attr ou tout autre choix approprié), mais cela devrait résoudre votre principal problème en éliminant le code à l'origine du problème, au lieu d'ajouter une solution de contournement supplémentaire.

3
Otto