Question

I need to implement a list of a custom post_type that has to be able to filter them by two taxonomies,

I found this answer that helps out with the wp_query syntax

My question is, now, how should the url look like?

The post_type: ad and the taxonomies are area and category

Current posts url is:

/category/bikes wich works

or

/ads/area/area-5 wich works

But how sould I generate the slug for the page where is filtering by category==bikes and area==area-5 ?

-EDIT-

Outside wp I would rewrite something like this (for this example):

/ads/(bikes|cars)/(area-5|area-3)

to:

/posts.php?type=ads&category=bikes&area=area-5

But I don't see how to work around that in wp

Any ideas?

thanks!

Was it helpful?

Solution

Just released today a plugin named Cortex, freely available on GitHub. You need PHP 5.4+ and Composer to install it (docs).

This plugin allows to write custom 'routes' to queries, it is based on Symfony routing component so mechanism of adding routes is similar to that.

Here you'll find full docs for Cortex.

Using Cortex all you need is a simple route:

add_action( 'brain_loaded', function() {

  Brain\Routes::add( '/ads/{cat}/{area}', 'cat_area_ad' )
  ->requirements( [ 'cat' => '[a-z]+', 'area' => 'area-[0-9]+' ] )
  ->query( function( $matches ) {
    return [
       'post_type' => 'ad',
       'tax_query' => [
          'relation' => 'AND',
          [
            'taxonomy' => 'category',
            'terms'    => [ $matches['cat'] ],
            'field'    => 'slug'
          ],
          [
            'taxonomy' => 'area',
            'terms'    => [ $matches['area'] ],
            'field'    => 'slug'
          ]
       ]
    ];
  } );

} );

"cat_area_ad" is an ID I assigned to route, that allows to easily build url for the route (see Cortex docs):

function get_cat_area_url( $cat = '', $area = '' ) {
  if ( did_action( 'parse_request' ) && ! empty( $cat ) && ! empty( $area ) ) {
    if ( strpos( $area, 'area-' ) !== 0 ) {
      $area = 'area-' . $area;
    }
    return Brain\Routes::url( 'cat_area_ad',  [ 'cat' => $cat, 'area' => $area ] );
  } else {
    return home_url();
  }
}

Previous function allows to get an url for the route, but both area and category must be passed as function arguments.

Once reading OP seems that "area" terms are named in the form "area-XX" (where 'XX' is a number) I made the route require that format and I also made get_cat_area_url function automatically prepend "area-" to the area string passed as argument (if not already present), so you can use it like so:

$url = get_cat_area_url( 'bikes', '5' );
echo $url; // will be: example.com/ads/bikes/area-5

get_cat_area_url function works properly only if 'parse_request' hook have been triggered (due to a limitation of Cortex url() API method), but in any template file you can use it without problems because when a template is shown that hook has always been triggered.

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top