admin管理员组

文章数量:1022761

I have created a custom post type called "events" and have also created a custom taxonomy which only shows up on this specific post type through which the admin must select an "event category" (terms).

Currently on the public site when the event detail page is requested it looks like this:

Additionally, on the public side a web browser can access just a specific event category to view all associating events where the url looks like this:

Both of the above situations currently works fine.

The problem I am having is that I would like to customize the URL slug for the event details page as follows:

Instead of having the event detail page slug being built from the entered title I would like for it to include the taxonomy term and a specific custom field. In end effect I would like for it to look like this:

/<taxonomy-term>-event-title-<custom-field>/
  • <taxonomy-term> is the event category (the way I programed the metabox the admin is only able to select a single term).
  • <custom-field> is a specific custom field the user is required to enter before the event post can be saved.

Does anyone know how I might go about doing this correctly? All my experiments have led nowhere.

I have created a custom post type called "events" and have also created a custom taxonomy which only shows up on this specific post type through which the admin must select an "event category" (terms).

Currently on the public site when the event detail page is requested it looks like this:

http://www.domain-name/events/title-of-the-event

Additionally, on the public side a web browser can access just a specific event category to view all associating events where the url looks like this:

http://www.domain-name/events/event-category

Both of the above situations currently works fine.

The problem I am having is that I would like to customize the URL slug for the event details page as follows:

Instead of having the event detail page slug being built from the entered title I would like for it to include the taxonomy term and a specific custom field. In end effect I would like for it to look like this:

http://www.domain-name/events/<taxonomy-term>-event-title-<custom-field>/
  • <taxonomy-term> is the event category (the way I programed the metabox the admin is only able to select a single term).
  • <custom-field> is a specific custom field the user is required to enter before the event post can be saved.

Does anyone know how I might go about doing this correctly? All my experiments have led nowhere.

Share Improve this question edited Jan 22, 2011 at 2:50 MikeSchinkel 37.6k14 gold badges117 silver badges132 bronze badges asked Jan 21, 2011 at 23:58 NetConstructorNetConstructor 4,41618 gold badges70 silver badges82 bronze badges 1
  • How about updating the post slug at save_post hook? Or am I way off? – Bainternet Commented Jan 22, 2011 at 3:07
Add a comment  | 

1 Answer 1

Reset to default 6

Well if I had thought about how much work with was going to be before writing it, you wouldn't be able to get me points right now. :) Needless to say, it's rather involved (though I don't think it really should have to be, but it is what it is.)

First off, you can't (easily) do it like you wanted; the problem is how to differentiate between these two URLs:

  • Event Type = "Day Time", Event Title = "For a Change"

  • Event Type = "Day", Event Title = "Time For a Change"

Both would have a portion of their URLs looking like this and how could we tell which is which?

day-time-for-a-change

So, I modified your pattern to use tildes (~) as separators and that works fine:

http://www.domain-name/events/<taxonomy-term>~event-title~<custom-field>/

Anyway, I wrote a plugin that does what you need. It does the following things:

  1. It sets the rewrite rule in the the plugin activation hook using $wp_rewrite->add_rule().

  2. It applys the pattern to create actual event post links using the 'post_type_link' hook, and

  3. It simplifes editing of the URL slug by using the 'get_sample_permalink_html' hook (I didn't try to show the full URL because it would have been too tricky for something I'm writing for free. :)

So here's what the edit screen looks like:


(source: mikeschinkel)

Which produces this view on the front end:


(source: mikeschinkel)

And here ya go with the plugin code (let me know if you have questions, but not toooo many. ;-):

<?php 
/*
Plugin Name: SEO URLs for Events
*/
if (!class_exists('SeoUrlsForEvents')) {
  class SeoUrlsForEvents {
    static function on_load() {
      add_action('init', array(__CLASS__,'init'));
      add_filter('post_type_link', array(__CLASS__,'post_type_link'),10,4);
      add_filter('get_sample_permalink_html',array(__CLASS__,'get_sample_permalink_html'),10,4);
    }
    static function get_sample_permalink_html($sample, $post_id, $new_title, $new_slug) {
      $post = get_post($post_id);
      if ($post->post_type=='event') {
        $post_slug = self::make_post_slug($post);
        if ($post_slug) {
          $sample = str_replace('<strong>Permalink:</strong>','<strong>Permalink Slug:</strong>',$sample);
          $sample = preg_replace('#(<span id="sample-permalink">).+?(<span id="editable-post-name" title="Click to edit this part of the permalink">).+?</span>/</span>#Us',"$1$2{$post->post_name}</span></span>",$sample);
          $permalink = get_post_permalink($id);
          $sample = preg_replace("#(<span id='view-post-btn'><a href=').+?(' class='button' target='_blank'>View Post</a></span>)#","$1{$permalink}$2",$sample);
        }
      }
      return $sample;
    }
    static function make_post_slug($post) {
      $post_slug = false;
      $post = (object)$post;
      if ($post->post_type=='event') {
        $when = get_post_meta($post->ID,'when',true);
        if (!empty($when)) { // If we don't have a when, use default
          $types = wp_get_object_terms($post->ID,'event-type');
          if (count($types)) // If we don't have an event-type, use default else use the first one
            $post_slug = "{$types[0]->slug}~{$post->post_name}~{$when}/";
        }
      }
      return $post_slug;
    }
    static function post_type_link($post_link, $post, $leavename, $sample) {
      if ($post->post_type=='event' && $sample) {
        $post_link = '%event%';
      } else {
        $post_slug = self::make_post_slug($post);
        if ($post_slug) {
          $post_link = get_bloginfo('wpurl') . '/events/' . $post_slug;
        }
      }
      return $post_link;
    }
    static function activate() {
      global $wp_rewrite;
      $wp_rewrite->add_rule('events/([^~]+)~([^~]+)~([^/]+)','index.php?post_type=event&taxonomy=event-type&term=$matches[1]&name=$matches[2]&meta_key=when&meta_value=$matches[3]', 'top');
      $wp_rewrite->flush_rules(false);
    }
    static function init() {
      register_post_type('event',
        array(
          'label'           => 'Events',
          'public'          => true,
          'rewrite'         => array('slug' => 'events'),
          'hierarchical'    => false,
          'supports'        => array('title','editor','custom-fields'),
        )
      );
      register_taxonomy('event-type', 'event', array(
        'hierarchical'    => false,
        'label'           => 'Event Types',
        'rewrite'         => array('slug' => 'event-types' ),
        )
      );
    }
  }
  SeoUrlsForEvents::on_load();
}
register_activation_hook(__FILE__,array('SeoUrlsForEvents','activate'));

I have created a custom post type called "events" and have also created a custom taxonomy which only shows up on this specific post type through which the admin must select an "event category" (terms).

Currently on the public site when the event detail page is requested it looks like this:

Additionally, on the public side a web browser can access just a specific event category to view all associating events where the url looks like this:

Both of the above situations currently works fine.

The problem I am having is that I would like to customize the URL slug for the event details page as follows:

Instead of having the event detail page slug being built from the entered title I would like for it to include the taxonomy term and a specific custom field. In end effect I would like for it to look like this:

/<taxonomy-term>-event-title-<custom-field>/
  • <taxonomy-term> is the event category (the way I programed the metabox the admin is only able to select a single term).
  • <custom-field> is a specific custom field the user is required to enter before the event post can be saved.

Does anyone know how I might go about doing this correctly? All my experiments have led nowhere.

I have created a custom post type called "events" and have also created a custom taxonomy which only shows up on this specific post type through which the admin must select an "event category" (terms).

Currently on the public site when the event detail page is requested it looks like this:

http://www.domain-name/events/title-of-the-event

Additionally, on the public side a web browser can access just a specific event category to view all associating events where the url looks like this:

http://www.domain-name/events/event-category

Both of the above situations currently works fine.

The problem I am having is that I would like to customize the URL slug for the event details page as follows:

Instead of having the event detail page slug being built from the entered title I would like for it to include the taxonomy term and a specific custom field. In end effect I would like for it to look like this:

http://www.domain-name/events/<taxonomy-term>-event-title-<custom-field>/
  • <taxonomy-term> is the event category (the way I programed the metabox the admin is only able to select a single term).
  • <custom-field> is a specific custom field the user is required to enter before the event post can be saved.

Does anyone know how I might go about doing this correctly? All my experiments have led nowhere.

Share Improve this question edited Jan 22, 2011 at 2:50 MikeSchinkel 37.6k14 gold badges117 silver badges132 bronze badges asked Jan 21, 2011 at 23:58 NetConstructorNetConstructor 4,41618 gold badges70 silver badges82 bronze badges 1
  • How about updating the post slug at save_post hook? Or am I way off? – Bainternet Commented Jan 22, 2011 at 3:07
Add a comment  | 

1 Answer 1

Reset to default 6

Well if I had thought about how much work with was going to be before writing it, you wouldn't be able to get me points right now. :) Needless to say, it's rather involved (though I don't think it really should have to be, but it is what it is.)

First off, you can't (easily) do it like you wanted; the problem is how to differentiate between these two URLs:

  • Event Type = "Day Time", Event Title = "For a Change"

  • Event Type = "Day", Event Title = "Time For a Change"

Both would have a portion of their URLs looking like this and how could we tell which is which?

day-time-for-a-change

So, I modified your pattern to use tildes (~) as separators and that works fine:

http://www.domain-name/events/<taxonomy-term>~event-title~<custom-field>/

Anyway, I wrote a plugin that does what you need. It does the following things:

  1. It sets the rewrite rule in the the plugin activation hook using $wp_rewrite->add_rule().

  2. It applys the pattern to create actual event post links using the 'post_type_link' hook, and

  3. It simplifes editing of the URL slug by using the 'get_sample_permalink_html' hook (I didn't try to show the full URL because it would have been too tricky for something I'm writing for free. :)

So here's what the edit screen looks like:


(source: mikeschinkel)

Which produces this view on the front end:


(source: mikeschinkel)

And here ya go with the plugin code (let me know if you have questions, but not toooo many. ;-):

<?php 
/*
Plugin Name: SEO URLs for Events
*/
if (!class_exists('SeoUrlsForEvents')) {
  class SeoUrlsForEvents {
    static function on_load() {
      add_action('init', array(__CLASS__,'init'));
      add_filter('post_type_link', array(__CLASS__,'post_type_link'),10,4);
      add_filter('get_sample_permalink_html',array(__CLASS__,'get_sample_permalink_html'),10,4);
    }
    static function get_sample_permalink_html($sample, $post_id, $new_title, $new_slug) {
      $post = get_post($post_id);
      if ($post->post_type=='event') {
        $post_slug = self::make_post_slug($post);
        if ($post_slug) {
          $sample = str_replace('<strong>Permalink:</strong>','<strong>Permalink Slug:</strong>',$sample);
          $sample = preg_replace('#(<span id="sample-permalink">).+?(<span id="editable-post-name" title="Click to edit this part of the permalink">).+?</span>/</span>#Us',"$1$2{$post->post_name}</span></span>",$sample);
          $permalink = get_post_permalink($id);
          $sample = preg_replace("#(<span id='view-post-btn'><a href=').+?(' class='button' target='_blank'>View Post</a></span>)#","$1{$permalink}$2",$sample);
        }
      }
      return $sample;
    }
    static function make_post_slug($post) {
      $post_slug = false;
      $post = (object)$post;
      if ($post->post_type=='event') {
        $when = get_post_meta($post->ID,'when',true);
        if (!empty($when)) { // If we don't have a when, use default
          $types = wp_get_object_terms($post->ID,'event-type');
          if (count($types)) // If we don't have an event-type, use default else use the first one
            $post_slug = "{$types[0]->slug}~{$post->post_name}~{$when}/";
        }
      }
      return $post_slug;
    }
    static function post_type_link($post_link, $post, $leavename, $sample) {
      if ($post->post_type=='event' && $sample) {
        $post_link = '%event%';
      } else {
        $post_slug = self::make_post_slug($post);
        if ($post_slug) {
          $post_link = get_bloginfo('wpurl') . '/events/' . $post_slug;
        }
      }
      return $post_link;
    }
    static function activate() {
      global $wp_rewrite;
      $wp_rewrite->add_rule('events/([^~]+)~([^~]+)~([^/]+)','index.php?post_type=event&taxonomy=event-type&term=$matches[1]&name=$matches[2]&meta_key=when&meta_value=$matches[3]', 'top');
      $wp_rewrite->flush_rules(false);
    }
    static function init() {
      register_post_type('event',
        array(
          'label'           => 'Events',
          'public'          => true,
          'rewrite'         => array('slug' => 'events'),
          'hierarchical'    => false,
          'supports'        => array('title','editor','custom-fields'),
        )
      );
      register_taxonomy('event-type', 'event', array(
        'hierarchical'    => false,
        'label'           => 'Event Types',
        'rewrite'         => array('slug' => 'event-types' ),
        )
      );
    }
  }
  SeoUrlsForEvents::on_load();
}
register_activation_hook(__FILE__,array('SeoUrlsForEvents','activate'));

本文标签: customizationInteresting Custom Post Type Slug with Taxonomy and Custom Field