自定义POST类型固定链接每隔一次更改

时间:2019-04-24 作者:S_R

我已经创建了父>子>孙结构。(课程>系列>剧集)。

我已经创建了下面的代码来更新每个自定义帖子类型的url,这样我就可以拥有url结构

http://mywebsite.co.uk/system/%course%/%series%/%episode%.

例如,一门名为“速成课程”的课程,包含一系列“基础知识”,其中一集是“检查镜子”,应该是这样的

http://mywebsite.co.uk/system/crash-course/the-basics/checking-your-mirrors

一切正常,但我注意到一个非常奇怪的bug。每隔一次我保存一集,permalink就会改变自己,尝试匹配一个随机的系列?

例如,如果我保存一次该集,我的永久链接是

http://mywebsite.co.uk/system/crash-course/the-basics/checking-your-mirrors.

然后,只要我回到这一集,进行任何更改并再次尝试保存,一旦保存并刷新页面,它就会将自身更改为

http://mywebsite.co.uk/system/crash-course/the-basics/the-basics-2, 我必须单击“编辑”并手动将其更改回来。

我的完整自定义帖子类型注册码如下,如果有人有任何想法,请告诉我!每隔一次我进行更改时,手动将永久链接更改回原来的位置,这并不理想!

Note - My apologies for the huge code snippet below, i thought it would be best if I pasted ALL of my custom post type code in to help debug!

<?php
/* ----------------------------------------------------------------------------------------------------------
        Register our custom post types
---------------------------------------------------------------------------------------------------------- */
function create_post_type() {
    //Courses
    register_post_type( \'course\',
      [
        \'labels\' => array(
          \'name\' => __( \'Courses\' ),
          \'singular_name\' => __( \'Course\' )
        ),
        \'description\' => \'All courses\',
        \'public\' => true,
        \'hierarchical\' => true,
        \'rewrite\' => array(
            \'slug\'       => \'system\',
        ),
        \'menu_icon\' => \'dashicons-welcome-learn-more\',
        \'supports\' => [\'title\', \'custom_fields\', \'page-attributes\']
      ]
    );

    //Series
    register_post_type( \'series\',
      [
        \'labels\' => array(
          \'name\' => __( \'Series\' ),
          \'singular_name\' => __( \'Series\' )
        ),
        \'description\' => \'Course Series\',
        \'public\' => true,
        \'hierarchical\' => false,
        \'show_ui\'              => true,
        \'show_in_menu\'         => \'edit.php?post_type=course\',
        \'supports\' => [\'title\', \'custom_fields\', \'page-attributes\']
      ]
    );

    //Episodes
    register_post_type( \'episodes\',
      [
        \'labels\' => array(
          \'name\' => __( \'Episodes\' ),
          \'singular_name\' => __( \'Episode\' )
        ),
        \'description\' => \'Series Episodes\',
        \'public\' => true,
        \'hierarchical\' => false,
        \'show_ui\'              => true,
        \'show_in_menu\'         => \'edit.php?post_type=course\',
        \'supports\' => [\'title\', \'custom_fields\', \'page-attributes\']
      ]
    );
}
add_action( \'init\', \'create_post_type\' );



/* ----------------------------------------------------------------------------------------------------------
        Add our meta boxes to our series and episode add/edit page
---------------------------------------------------------------------------------------------------------- */
function my_add_meta_boxes() {
  //Series Meta Boxes
  add_meta_box( \'series-parent\', \'Course\', \'series_attributes_meta_box\', \'series\', \'side\', \'high\' );

  //Episode Meta Boxes
  add_meta_box( \'episode-parent\', \'Series\', \'episode_attributes_meta_box\', \'episodes\', \'side\', \'high\' );
}
add_action( \'add_meta_boxes\', \'my_add_meta_boxes\' );

function series_attributes_meta_box($post) {
  $post_type_object = get_post_type_object($post->post_type);
    $pages = wp_dropdown_pages([
    \'post_type\' => \'course\',
    \'selected\' => $post->post_parent,
    \'name\' => \'parent_id\',
    \'show_option_none\' => __( \'(no parent)\' ),
    \'sort_column\'=> \'menu_order, post_title\',
    \'echo\' => 0
  ]);
  if (!empty($pages)){
        echo $pages;
    }
}

function episode_attributes_meta_box( $post ) {
  $post_type_object = get_post_type_object( $post->post_type );
  $select = "<select name=\'parent_id\' id=\'parent_id\'>";
    $select .= "<option value=\'\'>(No Parent)</option>";
    //Get Series
    $args = [
      \'post_type\' => \'series\',
      \'posts_per_page\' => -1,
      \'meta_key\' => \'series_number\',
      \'orderby\' => \'meta_value_num\',
      \'order\' => \'ASC\'
    ];
    $seriesQuery = new WP_Query($args);
    //Loop the series
    while($seriesQuery->have_posts()){
      $seriesQuery->the_post();
      $select .= "<option " . (get_the_ID() == $post->post_parent ? \'selected\' : \'\') . " class=\'level-0\' value=\'" . get_the_ID() . "\'>" . get_the_title(wp_get_post_parent_id(get_the_ID())) . \' - \' . get_the_title() . "</option>";
    }
    wp_reset_postdata();
  $select .= "</select>";
  echo $select;
}


/* ----------------------------------------------------------------------------------------------------------
        String replace on the permalinks before we save them
---------------------------------------------------------------------------------------------------------- */
function custom_permalinks($permalink, $post, $leavename) {

  $post_id = $post->ID;
  $parent = $post->post_parent;
  $parent_post = get_post( $parent );

  //Series or Episodes
  switch($post->post_type){
    case \'episodes\':
        if(empty($permalink) || in_array($post->post_status, array(\'draft\', \'pending\', \'auto-draft\'))){
          return $permalink;
        } else {
          $grandparent_post = get_post( $parent_post->post_parent );
          $search = [\'%course%\', \'%series%\'];
          $replace = [$grandparent_post->post_name, $parent_post->post_name];
          $permalink = str_replace($search, $replace, $permalink);
          return $permalink;
        }
    break;
    case \'series\':
        if(empty($permalink) || in_array($post->post_status, array(\'draft\', \'pending\', \'auto-draft\'))){
          return $permalink;
        } else {
          $search = [\'%course%\'];
          $replace = [$parent_post->post_name];
          $permalink = str_replace($search, $replace, $permalink);
          return $permalink;
        }
    break;
    default:
        return $permalink;
    break;
  }

}
add_filter(\'post_type_link\', \'custom_permalinks\', 10, 3);

function my_add_rewrite_rules() {

  //Episodes
  add_permastruct(\'episodes\', \'/system/%course%/%series%/%episodes%\', false,  [\'walk_dirs\' => false]);
  add_rewrite_tag(\'%episodes%\', \'([^/]+)\', \'episodes=\');
  add_rewrite_rule(\'^system/([^/]+)/([^/]+)/([^/]+)?\',\'index.php?episodes=$matches[3]\',\'top\');

  //Series
  add_permastruct(\'series\', \'/system/%course%/%series%\', false,  [\'walk_dirs\' => false]);
    add_rewrite_tag(\'%series%\', \'([^/]+)\', \'series=\');
  add_rewrite_rule(\'^system/([^/]+)/([^/]+)/?\',\'index.php?series=$matches[2]\',\'top\');


}
add_action( \'init\', \'my_add_rewrite_rules\' );

?>

1 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

更好的解决方案实际上,在WP_Query reference:

Note: Ticket #18408 要在管理中查询帖子,请考虑使用get_posts()wp_reset_postdata() 可能表现不符合预期。

因此,与其尝试重置全局post数据,更合适的解决方案是:

使用get_posts():

$seriesPosts = get_posts($args);
foreach($seriesPosts as $p){
  $select .= "<option " . ($p->ID == $post->post_parent ? \'selected\' : \'\') . " class=\'level-0\' value=\'" . $p->ID . "\'>" . get_the_title(wp_get_post_parent_id($p->ID)) . \' - \' . $p->post_title . "</option>";
}
$seriesQuery->posts:

$seriesQuery = new WP_Query($args);
foreach($seriesQuery->posts as $p){
  $select .= "<option " . ($p->ID == $post->post_parent ? \'selected\' : \'\') . " class=\'level-0\' value=\'" . $p->ID . "\'>" . get_the_title(wp_get_post_parent_id($p->ID)) . \' - \' . $p->post_title . "</option>";
}
And 不呼叫setup_postdata() 在循环中

原始答案问题是wp_reset_postdata() 无法重置全局$post 对象,因为post 全球的财产$wp_query 对象是null (即。$GLOBALS[\'wp_query\']->post 为空):

function episode_attributes_meta_box( $post ) {
    ...
    wp_reset_postdata(); // <- fails to reset $GLOBALS[\'post\']
    ...
}
因此,一个简单的修复方法是wp_reset_postdata(), 您可以复制/备份$post 对象传递到元框回调,然后设置全局$post 功能结束时的副本(或您认为需要重置全局post数据的任何地方):

function episode_attributes_meta_box( $post ) {
    $_post = $post; // copy it to $_post

    $post_type_object = get_post_type_object( $post->post_type );
    $select = "<select name=\'parent_id\' id=\'parent_id\'>";
    ... your code ...
    //wp_reset_postdata();
    $select .= "</select>";
    echo $select;

    // Here resets the global post data.
    $GLOBALS[\'post\'] = $_post;
    unset( $_post );
}
可能还有其他选择,但上面的技巧对我很有效:)

相关推荐

Problem with permalinks

我已经更改了类别的基本名称,现在它是“博客”,工作正常。但当我通过/blog/%category%/%postname%/更改结构时。显示404。如果我删除结构中的blog,它会再次工作,但我想使用blog word。问题出在哪里?非常感谢。