admin管理员组

文章数量:1131184

I'm working on rewrite rules for a plugin that uses a URL endpoint, /modifier, to create a query_var &modifier=1 to signify it should do something else.

The rewrite deals with URLs where /modifier is appended to the end of a URL for a post, page, or custom post type.

It seems like adding a rewrite endpoint would be ideal, but according to the Wordpress rewrite endpoints API the incoming URL would need to end with a value, like /modifier/1 in order to rewrite automatically to &modifier=1 via the endpoint API. If there's no value after the endpoint, it resolves to &modifier= and has no value when checking if it isset.

So I'm still doing it the long way, via generate_rewrite_rules. The rewrite for posts and pages works fine - I could include it but maybe it's not relevant.

The rewrite for custom post types, added at the top, also works when a post type is explicitly hardcoded.

add_filter('generate_rewrite_rules', 'my_rewrite');
function my_rewrite($wp_rewrite) {
    // rewrite rules for custom post type "specific-type"
    $cpt_rules = array(
        'specific-type-slug/([^/]+)/modifier' => 'index.php?specific-type='. $wp_rewrite->preg_index(1) .'&modifier=1'
    );
    $wp_rewrite->rules = $cpt_rules + $wp_rewrite->rules;
}

The problem is making a loop for all custom post types. get_post_types() is only available after init. This rewrite is filtering generate_rewrite_rules, several steps earlier.

So here's the loop I've tried. It obviously doesn't work, the post types aren't set up yet.

add_filter('generate_rewrite_rules', 'my_rewrite');
function my_rewrite($wp_rewrite) {
  global $wp_post_types;
  $types = get_post_types( array( '_builtin' => false ) );
  // get the registered data about each post type with get_post_type_object
  foreach( $types as $type ) {
    $cpt_rules = '';
    $typeobj = get_post_type_object( $type );

    if( isset( $typeobj->rewrite->slug ) ) {
        $slug = $typeobj->rewrite->slug;
        $cpt_rules = array(
            $slug.'/([^/]+)/modifier' => 'index.php?'.$type.'='. $wp_rewrite->preg_index(1) .'&modifier=1'
        );
        $wp_rewrite->rules = $cpt_rules + $wp_rewrite->rules;
    }
  }
}

Something tells me using a plugin class might be the way to solve this, but I don't understand how.

I'm working on rewrite rules for a plugin that uses a URL endpoint, /modifier, to create a query_var &modifier=1 to signify it should do something else.

The rewrite deals with URLs where /modifier is appended to the end of a URL for a post, page, or custom post type.

It seems like adding a rewrite endpoint would be ideal, but according to the Wordpress rewrite endpoints API the incoming URL would need to end with a value, like /modifier/1 in order to rewrite automatically to &modifier=1 via the endpoint API. If there's no value after the endpoint, it resolves to &modifier= and has no value when checking if it isset.

So I'm still doing it the long way, via generate_rewrite_rules. The rewrite for posts and pages works fine - I could include it but maybe it's not relevant.

The rewrite for custom post types, added at the top, also works when a post type is explicitly hardcoded.

add_filter('generate_rewrite_rules', 'my_rewrite');
function my_rewrite($wp_rewrite) {
    // rewrite rules for custom post type "specific-type"
    $cpt_rules = array(
        'specific-type-slug/([^/]+)/modifier' => 'index.php?specific-type='. $wp_rewrite->preg_index(1) .'&modifier=1'
    );
    $wp_rewrite->rules = $cpt_rules + $wp_rewrite->rules;
}

The problem is making a loop for all custom post types. get_post_types() is only available after init. This rewrite is filtering generate_rewrite_rules, several steps earlier.

So here's the loop I've tried. It obviously doesn't work, the post types aren't set up yet.

add_filter('generate_rewrite_rules', 'my_rewrite');
function my_rewrite($wp_rewrite) {
  global $wp_post_types;
  $types = get_post_types( array( '_builtin' => false ) );
  // get the registered data about each post type with get_post_type_object
  foreach( $types as $type ) {
    $cpt_rules = '';
    $typeobj = get_post_type_object( $type );

    if( isset( $typeobj->rewrite->slug ) ) {
        $slug = $typeobj->rewrite->slug;
        $cpt_rules = array(
            $slug.'/([^/]+)/modifier' => 'index.php?'.$type.'='. $wp_rewrite->preg_index(1) .'&modifier=1'
        );
        $wp_rewrite->rules = $cpt_rules + $wp_rewrite->rules;
    }
  }
}

Something tells me using a plugin class might be the way to solve this, but I don't understand how.

Share Improve this question edited Jun 30, 2014 at 10:18 nimmolo asked Jun 30, 2014 at 9:14 nimmolonimmolo 2041 silver badge6 bronze badges 1
  • Update: it is certainly a heck of a lot easier to just change the URL to modifier/1 and use the endpoint API, I can confirm this works. Still I'm curious if there's a way to use the query_var modifier even if it is not followed by a value in the URL. – nimmolo Commented Jun 30, 2014 at 10:40
Add a comment  | 

1 Answer 1

Reset to default 1

Apologies if this seemed too obvious to answer, i'm just getting my head around htaccess rewrites in wordpress.

The most elegant way to parse the modifier through the URL like this seems to be to add a rewrite endpoint and just check for it in the URL later, if you don't want to pass a value.

The beauty is there's no need for any other rewrite rules, as long as you're just checking for this endpoint.

add_action( 'init', 'wp_modifier_endpoint' );
function wp_modifier_endpoint() {
    add_rewrite_endpoint( 'modifier', EP_PERMALINK | EP_PAGES );
}

In the function creating the /modifier links, there's also no need to add a value after /modifier/value either, unless you need a value. My previous technique checked if the endpoint (as query_var) isset, but you can just check for the endpoint string within the URL with the php strrpos function.

$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$endpoint = substr( $url, 9 ); /* number of chars in string "/modifier" */
if( false !== strpos( $endpoint, '/modifier' ) ) {
    /* do something; */
}

Update: per Milo's comment below, it is preferable to check if modifier is an array_key of query_vars - this seems more foolproof and easily extensible, in case you want to check for multiple keys.

global $wp_query;
if( array_key_exists( 'modifier' , $wp_query->query_vars ) ) {
    /* do your thing; */
}

本文标签: custom post typesRewrite Endpoints and CPTsHow to use in a plugin