web-dev-qa-db-fra.com

Regex conditionnel dans add_rewrite_rule () pour des filtres de requête et une pagination spécifiques

Je travaille sur un site Web avec deux types de publication partageant plusieurs taxonomies et champs personnalisés. J'ai développé une fonctionnalité de filtrage avec de jolies URL, et les urls fonctionnent pour le moment de cette manière:

1) J'ai enregistré mes vars de requête

function return_vars( $vars ) {
$vars[] = 'tax_filters';
$vars[] = 'field_filters';
return $vars;
}
add_filter( 'query_vars', 'return_vars' );

2) J'ai configuré ces règles de réécriture en utilisant add_rewrite_rule () de cette manière:

add_rewrite_rule( 'my-base/filters/([^\/]*)/([^&]*)/fields/([^&]*)/?', 'index.php?post_type=$matches[1]&tax_filters=$matches[2]&field_filters=$matches[3]', 'top');
add_rewrite_rule( 'my-base/filters/([^\/]*)/([^&]*)/?', 'index.php?post_type=$matches[1]&tax_filters=$matches[2]', 'top');

pour que:

  1. $ correspond [1] représente le type de message
  2. $ matches [2] filtre les taxonomies. C'est une chaîne, divisée par des barres obliques, sous la forme/tax1_name/term/tax2_name/term/tax3_name/term .....
  3. $ matches [3] dans la première règle arrête l'enregistrement des correspondances [2] et commence à faire correspondre le contenu après le/fields/placeholder, qui suit en tant que/field1_name/value/field2_name/etcetera
  4. Dernièrement, je filtre WP_Query en utilisant pre_get_posts, en fonction du contenu de tax_filters [] & field_filters []

Donc, mes URL peuvent être:

(according to rule 1)
my-base/my-cpt/filters/tax1/term/tax2/term/../../fields/field1/value/fields2/value/../../

ou filtrer uniquement les taxes:

(according to rule 2)
my-base/my-cpt/filters/tax1_name/term/tax2_name/term/../../

Maintenant, puisque j'ai besoin de même:

  1. filtrer uniquement les champs tels que: my-cpt/fields/field1/value/fields2/value /
  2. pagination pour chaque combinaison de filtrage possible: a) uniquement taxe, b) uniquement des champs c) taxe et des champs

Cela donnerait 6 règles différentes, qui doivent être écrites dans un ordre spécifique, du plus long au plus court, sinon ces dernières écraseront les autres.

Je me demandais: est-il possible d'écrire une regex qui combinerait éventuellement toutes ces règles en une?

J'ai essayé avec plusieurs expressions conditionnelles regexes, mais je n'y suis pas compétent, je n'ai donc que des erreurs d'analyse.

Merci à tous ceux qui pourraient aider!

1
frafor

J'ai réussi à contourner le problème. Il est la solution pour référence ultérieure.

1) Je n'ai qu'une seule requête var maintenant:

function return_vars( $vars ) {
  $vars[] = 'filters';
  return $vars;
}

2) Mes règles de réécriture ont été modifiées en:

add_rewrite_rule( 'my-base/filters/([^\/]*)/([^&]*)/page/([0-9]{1,})/?', 'index.php?post_type=$matches[1]&filters=$matches[2]&paged=$matches[3]', 'top');
add_rewrite_rule( 'my-base/filters/([^\/]*)/([^&]*)/?', 'index.php?post_type=$matches[1]&filters=$matches[2]', 'top');

Règle 1: gestion de la pagination Règle 2: gestion de la page principale uniquement

Ils doivent être dans cet ordre.

3) Ensuite, je filtre plus ou moins la chaîne de filtres de cette manière

function my_pre_get_posts( $query ) {
  $filters = get_query_var('filters');

  // if no filter or if filters are odd, then return
  if(!$filters || count(explode("/", $k4w_filters)) % 2 != 0) return;

  // this is a global array with my 2 tax slugs in it
  global $CUSTOM_TAXES_S;

  $chunks = array_chunk(explode('/', $filters), 2);
  $filter_data = array_combine(array_column($chunks, 0), array_column($chunks, 1));

  // filter data, populate tax_data and field_data for queries
  foreach($filter_data as $key => $value) {
    if(in_array($key, $CUSTOM_TAXES_S)) {
        $tax_data[$key] = $value;
    } else {
        $field_data[$key] = $value;
    }
    $query->set('debug_tax_data', $tax_data);
    $query->set('debug_field_data', $field_data);
  }

  // if tax_data exist set tax_query
  if($tax_data) {
    foreach( $tax_data as $taxonomy => $slugs ) {
        // append tax query
        $tax_query[] = array(
            'taxonomy'  => get_tax_name($taxonomy), // that's a simple function that retrieves the taxonomy name from its slug
            'field'     => 'slug',
            'terms'     => explode(',', $slugs),
        );
    }
    $query->set('tax_query', $tax_query);
  }

  // if field_data exist set meta_query
  if($field_data) {
    foreach( $field_data as $key => $value ) {
        // append tax query
        $meta_query[] = array(
            'key'   => $key,
            'value'     => explode(',',$value),
            'compare'       => 'IN',
        );
    }
    $query->set('meta_query', $meta_query);
  }
}
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);

De cette façon, je peux même fournir plusieurs termes pour les taxes ou des valeurs pour les champs, tels que:

/my-base/filters/my-cpt/tax1/term1,term2/tax2/term1,term2/field1/val1,val2/goingon...

Et ça va marcher! Avec la pagination aussi.

Évidemment, le code ci-dessus fonctionne, mais il y a aussi plusieurs vérifications pour éviter les problèmes et les hacks (par exemple, vérifier si un nom de champ fourni existe ou non, ou s'il se trouve dans une liste de champs filtrable, etc.).

J'espère que cela aidera quelqu'un :)

2
frafor