前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >史上最详细的WordPress的自定义文章类型指南(1)

史上最详细的WordPress的自定义文章类型指南(1)

作者头像
丘壑
发布2019-04-26 18:41:07
4.2K0
发布2019-04-26 18:41:07
举报
文章被收录于专栏:一丘一壑一丘一壑

最近我发现有很多从google过来的奇怪的关键字,比如best screenshot app 这种,可能是我的这个域名bestscreenshot.com 当时买的有点太随意了。不过这正好也给了我一点灵感,一直以来我自己也算是对各种优秀的工具和软件挺感兴趣的,不管是命令行的还是图形化界面的也都积攒了好多好东西,正好可以在博客上做一点推荐,也可以算作是一种优质内容的补充。

在WordPress中来展现这种内容的形式来说有很多种,最简单的就是写一篇普通的文章(post)或者页面(page),把软件名称介绍什么的往里一扔就ok了,大不了再加个分类就叫“工具推荐”。这样当然可以,但是如果说对日后想频繁的维护更新,做更多的内容组织,甚至做一个类似 xclient.info 这种专门的软件推荐下载站来说就有点不方便了。所以我决定使用自定义文章类型(Custom Post Type)这种形式。

上一篇文章里详细介绍了WordPress的Custom Post Type是什么、什么时候用、有什么优势,也简单提了一点使用的方法。本篇就用这个案例详细介绍一下使用步骤,主要包括如下几个部分:

  • 创建Custom Post Type
  • 修改Custom Post Type
  • 关于Custom Post Type的URL

一点背景知识

因为本文是面向新手的,在开始创建Custom Post Type之前有必要介绍一点基础的背景知识,这样才可以做到知其然也知其所以然。

面向对象编程(Object Oriented Programming)

首先是面向对象编程(Object Oriented Programming),OOP起源于20世纪60年代,直到20世纪90年代才成为应用软件开发的主流,如今从应用软件过渡到网站开发,面向对象思想仍然具 备极大的应用价值。PHP5之后对OOP提供了良好的支持。

OOP这个话题内容就太多了,汗牛充栋,值得大书特书,我就不献丑了,本文只涉及到OOP中的两个基本概念:类和对象。简单介绍如下,知道是啥就够了。

什么是类?

具有相同属性(特征)和方法(行为)的一系列个体的集合,类是一个抽象的概念。

什么是对象?

从类中,拿到的具有具体属性值的个体,称为对象。对象是一个具体的个体。

eg:人类;张三

类和对象的关系?
  • 类是对象的抽象化!对象是类的具体化!
  • 类仅仅表明这类对象有哪些属性,但是不能有具体的值,所以类是抽象的。
  • 对象是将类的所有属性赋值后,产生具体的个体,所有对象是具体的。

WordPress中的面向对象

WordPress的历史也算比较久远了,开发者众多,因为历史原因和技术原因,一些开发者可能并不喜欢面向对象这种思想,或者在当时面向对象编程还没有成为主流思想,所以WordPress核心代码中并不全是面向对象风格的。

但是WordPress中一些比较重要的部分,比如WP_Query , REST API, 包括本文要介绍的Post Type部分都是面向对象,而且WordPress中的一些插件就是全部使用面向对象,比如WooCommerce。

创建Custom Post Type的方法

WP_Post_Type 是WordPress中的一个核心类,处理所有关于Post Type的各种操作。我们使用自定义文章类型的时候,要 new 出一个这个类的对象来,有了对象,接来了的操作就是围绕着这个对象进行的了,一般我们不直接使用 new?WP_Post_Type?方法来创建对象,而是使用?register_post_type() 函数,望文生义,这个函数的功能就是在WordPress中注册一个Post Type,实际上就是new了一个 WP_Post_Type对象

那么这个步骤是在哪里执行呢?一般来说有两种方式:主题或插件。

主题中创建Custom Post Type

市面上有些高级 WordPress 主题也会在主题中附带提供一些Custom Post Type,比如专题、公告、视频、相册、Portfolio等等,作为自己的增值功能提供给用户,也可以基于这些已有的功能进行二次开发。

对于 WordPress 的普通用户来说,最方便的就是在主题文件夹的functions.php 中写代码进行各种自定义,执行各种 WordPress 的函数,当然也可以在这里注册新的文章类型。

这样带来的一个问题就是基本上这个Custom Post Type就会被这个主题绑死了,换了主题后原有的Custom Post Type相关设置就没了(在其中创建过文章不会被删除,但是不一定能显示出来),除非你把主题中相关的代码抠出来再移植到新主题中去。如果你不介意这一点的话,或者动手能力强,这也不是什么大问题,但最好是确定好一个长期使用的主题再搞,不然换主题后会比较麻烦。

自从开始遇到Genesis这个神级主题框架之后,相见恨晚,今后很长一段时间估计我都不会在更换目前用的Genesis Sample这个主题了,所以就在主题文件中改代码了。使用其他的主题朋友也可以参考一下。

插件创建Custom Post Type

插件和主题是相对独立的,所以使用插件来进行新建Custom Post Type的方式就不会依赖于主题了。其实细分来说,这类插件也可以分为几种形式。

一种是主题商额外提供的特性Post Type类型的插件,比如Genesis开发公司StudioPress就提供了一个插件Genesis Portfolio Pro是专门处理Portfolio(作品展示)这种类型,但是只能用于Genesis主题,也算是比较依赖主题的。

还有一种就是通用型的插件,可以用来创建各种Custom Post Type,设置各种参数,比如这篇文章里推荐的几个插件:5 Best Free Custom Post Types and Custom Taxonomies Plugins for WordPress

这次先用纯手工的方式撸一遍,插件的作用无非也就是帮你把很多手动的工作给自动化了而已,以后再写写插件的用法。

register_post_type函数的用法

现在,已经确定了要在Genesis主题中创建Custom Post Type。那么首先来看一下register_post_type()函数的具体用法,使用方法很简单,如下所示::

代码语言:javascript
复制
register_post_type( $post_type, $args );

$post_type 是必需的参数,必须是字符串,最长20个字符,只能使用小写字符,可以包含下划线,但不能包含空格。这就是你要使用的自定义文章类型的名称,根据需要来取就可以,比如在我这里就是专门用来介绍精品软件,那么我就把这个类型定叫做 awsome_app 类型。

$args 是对需要注册的post type的扩展设置,可以设置的选项非常非常多,但是不要被吓到了,这些参数都是可选项,也并不一定要一开始就全部设置好,可以根据需要的在时候再进行追加修改,下文涉及的地方会详细介绍。

有一点非常重要:调用register_post_type() 来注册新的文章类型时,必须要挂载在?init 这个action 上,在init之前调用则不生效。如果你对action的用法不了解,可以看下本博客里之前介绍的WordPress动作函数这篇文章。

那么现在就可以在主题function.php 文件中加入以下代码了:

代码语言:javascript
复制
add_action( 'init', 'create_new_cutom_post_type' );

function create_new_cutom_post_type() {
	register_post_type( 'awsome_app' );
    }

为了最简单最快速的的演示,我只加了一个必需的参数,可选参数什么都没有写。实际上这样已经完事了,现在awsome_app这个post type已经注册好了可以用了。就这么简单?就这么简单。如果不相信的话,我们可以通过wp shell 看一下结果:

get_post_types():Get a list of all registered post type objects.

可以看到已经多出来一个post type了。不过因为没有传入其他扩展参数,目前在WordPress 的管理后台看不到任何变化,只有通过代码才可以对这个新的post type进行新建文章等操作,或者用wp cli工具也可以在创建的时候指定这个post type:

现在即使发布了在前台也是看不了(详见下文关于public参数的部分),这样显然是没有任何意义。那么我们再对这个post type进行一些扩展设置。

register_post_type函数支持的参数

上面说过register_post_type函数支持的参数非常多,也比较复杂。按照用途来分的话主要用几类:后台管理用、描述信息用、固定链接用、角色权限控制用等等,这需要根据不同场景做更细致的设置。在创建的时候,可以把不同用途的参数归入一类再统一加入$args中,这样代码的可读性会比较好。

WordPress智库上也翻译了这些所有的参数,比较全面详细,摘录如下:

代码语言:javascript
复制
# 在 'init' 钩子上注册自定义文章类型.
add_action('init', 'my_register_post_types');

/**
 * 注册插件需要的文章类型
 *
 * @since  1.0.0
 * @access public
 * @return void
 */
function my_register_post_types()
{

    // 设置文章类型参数
    $args = [

        // 文章类型的简介,貌似没有在 WordPress 内核中使用,不过我们可以在主题或插件中使用
        'description'         => __('This is a description for my post type.', 'wprs'),
        // 字符串

        // 文章类型是否公开给管理员或者前端用户使用,这个参数的值是后面很多参数的默认值
        'public'              => true,
        // bool (default is FALSE)

        // 是否可以在前端作为 parse_request() 的一部分查询该文章类型
        'publicly_queryable'  => true,
        // bool (默认为 'public' 参数的值).

        // 是否在前端搜索中隐藏该文章类型
        'exclude_from_search' => false,
        // bool (默认为 'public' 反值)

        // 是否可以在导航菜单中选择
        'show_in_nav_menus'   => false,
        // bool (默认为 'public' 参数的值)

        // 是否在管理界面生成默认的管理界面,使用后面的参数,可以控制生成的 UI 组件,如果我们要构建自己的管理界面,
        //设置该参数为 False
        'show_ui'             => true,
        // bool (默认为 'public' 的值)

        // 是否在管理菜单中显示,'show_ui' 参数必须设置为 True,这个参数才有效,我们页可以设置该参数为一个顶级菜单
        //(如:'tools.php'),这种情况下,该文章类型的管理菜单出现在 Tools 菜单下面
        'show_in_menu'        => true,
        // bool (默认为 'show_ui' 的值)

        // 是否在管理工具条中显示该文章类型,如果设置为 true,WordPress 会在管理工具条中添加一个新建该文章类型文章的链接
        'show_in_admin_bar'   => true,
        // bool (默认为 'show_in_menu' 的值)

        // 该文章类型在管理菜单中出现的位置,'show_in_menu' 必须设置为 true,该参数才有用
        'menu_position'       => null,
        // int (默认为 25 - 出现在「评论」菜单后面)

        // 管理菜单的图标 URI,或者 Dashicon 的类名称. 参见: https://developer.wordpress.org/resource/dashicons/
        'menu_icon'           => null,
        // 字符串 (默认使用文章图标)

        // 属于该文章类型的文章是否可以通过 WordPress 导入/导出插件或者类型的插件导出
        'can_export'          => true,
        // bool (默认为 TRUE)

        // 是否暴露在 Rest API 中
        'show_in_rest',
        // 布尔值,默认为 false

        // 使用 Rest API 访问的基础 URI 别名
        'rest_base',
        // 字符串,默认为文章类型别名

        // 使用自定义 Rest API 控制器而不是默认的 WP_REST_Posts_Controller,自定义控制器必须继承 WP_REST_Controller
        'rest_controller_class',
        // 字符串,默认为 WP_REST_Posts_Controller

        // 是否在删除用户时,删除他们撰写的文章
        'delete_with_user'    => false,
        // bool (如果文章类型支持 ‘author’ 功能,该参数默认为 TRUE)

        // 该文章类型是否支持多级文章(父级文章/子文章/等等.) 
        'hierarchical'        => false,
        // bool (默认为 FALSE)

        // 是否为该文章类型开启存档页面 index/archive/root 页面,如果设置为 TRUE, 该文章类型名称将作为存档页面别名使用,
        //当然,我们页可以设置自定义存档别名
        'has_archive'         => 'example',
        // bool|string (默认为 FALSE)

        // 为该文章类型设置 query_var 键,如果设置为 TRUE, 将使用文章类型名称,如果需要,也可以设置自定义字符串
        'query_var'           => 'example',
        // bool|string (默认为 TRUE - 文章类型名称)

        // 用于构建该文章类型的编辑、删除、阅读权限的字符串,可以设置字符串或者数组,如果单词的负数不是加“s”的形式,我们需要
        //设置一个数组,array( 'box', 'boxes' )
        'capability_type'     => 'example',
        // string|array (默认为 'post')

        // 是否让 WordPress 映射权限元数据 (edit_post, read_post, delete_post),如果设置为 FALSE, 我们需要自己通过
        //过滤 “map_meta_cap” 钩子来设置文章类型权限
        'map_meta_cap'        => true,
        // bool (默认为 FALSE)

        // 设置更精确的文章类型权限,WordPress 默认使用 'capability_type' 参数来构建权限,多数情况下,我们不需要像文章
        //或页面这么完整的权限,下面是我经常使用的几个权限: 'manage_examples', 'edit_examples', 'create_examples'.
        // 每个文章类型都是独特的,我们可以根据需要调整这些权限
        'capabilities'        => [

            // meta caps (don't assign these to roles)
            'edit_post'              => 'edit_example',
            'read_post'              => 'read_example',
            'delete_post'            => 'delete_example',

            // primitive/meta caps
            'create_posts'           => 'create_examples',

            // primitive caps used outside of map_meta_cap()
            'edit_posts'             => 'edit_examples',
            'edit_others_posts'      => 'manage_examples',
            'publish_posts'          => 'manage_examples',
            'read_private_posts'     => 'read',

            // primitive caps used inside of map_meta_cap()
            'read'                   => 'read',
            'delete_posts'           => 'manage_examples',
            'delete_private_posts'   => 'manage_examples',
            'delete_published_posts' => 'manage_examples',
            'delete_others_posts'    => 'manage_examples',
            'edit_private_posts'     => 'edit_examples',
            'edit_published_posts'   => 'edit_examples',
        ],

        // 定义该文章类型的 URL 结构,我们可以设置一个具体的参数或一个布尔值,如果设置为 false,该文章类型将不支持
        // URL Rewrite 功能
        'rewrite'             => [

            // 文章类型的别名
            'slug'       => 'example', // string (默认为文章类型名称)

            // 是否在固定链接中显示 $wp_rewrite->front 文章类型别名
            'with_front' => false, // bool (默认为 TRUE)

            // 是否允许文章类型中的文章通过 <!--nextpage--> 快捷标签实现分页
            'pages'      => true, // bool (默认为 TRUE)

            // 是否为订阅源创建漂亮的固定链接feeds.
            'feeds'      => true, // bool (默认为 'has_archive' 的值)

            // 为固定链接设置设置 endpoint 遮罩
            'ep_mask'    => EP_PERMALINK, // const (默认为 EP_PERMALINK)
        ],

        // 文章类型支持的 WordPress 功能,许多参数在文章编辑界面非常有用。这有助于其他主题和插件决定让用户使用什么功能
        //或者提供什么数据,我们可以为该参数设置一个数组,也可以设置为 false,以防止添加任何功能,文章类型创建后,我们
        //可以使用 add_post_type_support() 添加功能,或使用 remove_post_type_support() 删除功能。默认功能是“标题
        //”和“编辑器”。
        'supports'            => [
            'title',// 文章标题 ($post->post_title).
            'editor', // 文章内容 ($post->post_content).
            'excerpt', // 文章摘要 ($post->post_excerpt).
            'author',  // 文章作者 ($post->post_author).
            'thumbnail',// 特色图像 (当前站点使用的主题必须支持 'post-thumbnails').
            'comments', // 显示评论元数据盒子,如果设置了该值, 这个文章类型将支持评论
            'trackbacks', // 在编辑界面显示允许发送链接通知的元数据盒子
            'custom-fields', // 显示自定义字段元数据盒子
            'revisions', // 显示版本元数据盒子,如果设置了该参数,WordPress 将在数据库中保存文章版本
            'page-attributes',  // 显示“页面属性”元数据盒子,包含父级页面或页面排序字段。
            'post-formats',// 显示文章格式元数据盒子,并允许该文章类型使用文章格式
        ],
        // 标签用来在管理界面或前端显示该文章类型的名称,标签参数不会自动改写文章更新、错误等信息中的字段,我们需要过滤
        // 'post_updated_messages' 钩子来自定义这些消息。
        'labels'              => [
            'name'                  => __('Posts', 'wprs'),
            'singular_name'         => __('Post', 'wprs'),
            'menu_name'             => __('Posts', 'wprs'),
            'name_admin_bar'        => __('Posts', 'wprs'),
            'add_new'               => __('Add New', 'wprs'),
            'add_new_item'          => __('Add New Post', 'wprs'),
            'edit_item'             => __('Edit Post', 'wprs'),
            'new_item'              => __('New Post', 'wprs'),
            'view_item'             => __('View Post', 'wprs'),
            'search_items'          => __('Search Posts', 'wprs'),
            'not_found'             => __('No posts found', 'wprs'),
            'not_found_in_trash'    => __('No posts found in trash', 'wprs'),
            'all_items'             => __('All Posts', 'wprs'),
            'featured_image'        => __('Featured Image', 'wprs'),
            'set_featured_image'    => __('Set featured image', 'wprs'),
            'remove_featured_image' => __('Remove featured image', 'wprs'),
            'use_featured_image'    => __('Use as featred image', 'wprs'),
            'insert_into_item'      => __('Insert into post', 'wprs'),
            'uploaded_to_this_item' => __('Uploaded to this post', 'wprs'),
            'views'                 => __('Filter posts list', 'wprs'),
            'pagination'            => __('Posts list navigation', 'wprs'),
            'list'                  => __('Posts list', 'wprs'),

            // 只在分级文章类型中使用的标签
            'parent_item'           => __('Parent Post', 'wprs'),
            'parent_item_colon'     => __('Parent Post:', 'wprs'),
        ],
    ];

    // 注册文章类型
    register_post_type(
        'example', // 文章类型名称,最多 20 个字符,不支持大写或空格
        $args // 文章类型的参数
    );

}

在实际应用中当然不用这么麻烦一个个参数的去手动设置。推荐一个可以快速生成post type的各种参数的在线工具:Post Type Generator,按照需求在各个参数填入值,生成的代码组织的还是比较清晰的,把各种参数按照不同的用途分类好了,直接把生成的代码复制粘贴到你的主题中就可以用起来了。

和public值相关的参数

注册新的post type时,有些参数是比较重要的,有些参数会依赖于别的参数的值。

public这个属性就是其中之一,它的true或false会直接影响其他参数是否生效,比如是否在后台可以管理,是否在前台可见等等。

和public值相关的参数值组合效果如下,如果没有什么特殊需求,建议把public设置为true。:

代码语言:javascript
复制
'rewrite' => true
	'public' => true	'publicly_queryable' => true	/cpt-slug/cpt-post-slug 	Loads fine
	'public' => false	'publicly_queryable' => true	/cpt-slug/cpt-post-slug 	Loads fine
	'public' => true	'publicly_queryable' => false	/cpt-slug/cpt-post-slug		404 Error
	'public' => false	'publicly_queryable' => true	/cpt-slug-cpt-post-slug 	404 Error

'rewrite' => false
	'public' => true	'publicly_queryable' => true	/?cpt-slug=cpt-post-slug 	Loads fine
	'public' => true	'publicly_queryable' => true	/?p=ID&post_type=cpt-slug 	Loads fine
	'public' => false	'publicly_queryable' => true	/?cpt-slug=cpt-post-slug 	Loads fine
	'public' => false	'publicly_queryable' => true	/?p=ID&post_type=cpt-slug 	Loads fine
	'public' => true	'publicly_queryable' => false	/?cpt-slug=cpt-post-slug 	404 Error
	'public' => false	'publicly_queryable' => false	/?cpt-slug=cpt-post-slug 	404 Error
	'public' => true	'publicly_queryable' => false	/?p=ID&post_type=cpt-slug 	404 Error
	'public' => false	'publicly_queryable' => false	/?p=ID&post_type=cpt-slug 	404 Error

'has_archive' => true
	'public' => true	'publicly_queryable' => true	/cpt-slug/ 	Loads archive page
	'public' => false	'publicly_queryable' => true	/cpt-slug/ 	Loads archive page
	'public' => true 	'publicly_queryable' => false	/cpt-slug/ 	No archive page
	'public' => false	'publicly_queryable' => false	/cpt-slug/ 	No archive page

'has_archive' => false
	'public' => true	'publicly_queryable' => true	/?post_type=cpt-slug 	Loads fine
	'public' => true	'publicly_queryable' => false	/?post_type=cpt-slug 	Loads index
	'public' => false	'publicly_queryable' => true	/?post_type=cpt-slug 	Loads fine
	'public' => false	'publicly_queryable' => false	/?post_type=cpt-slug 	Loads index

'exclude_from_search' => false
	'public' => true	'publicly_queryable' => true	/?s=search-term 			Results show from all post types
	'public' => false	'publicly_queryable' => true	/?s=search-term 			Results show from all post types
	'public' => true	'publicly_queryable' => true	/?s=search-term&post_type=cpt-slug 	Result shows only one post type
	'public' => false	'publicly_queryable' => true	/?s=search-term&post_type=cpt-slug 	Result shows only one post type
	'public' => true	'publicly_queryable' => false	/?s=search-term 			Results show from all post types
	'public' => false	'publicly_queryable' => false	/?s=search-term 			Results show from all post types
	'public' => true	'publicly_queryable' => false	/?s=search-term&post_type=cpt-slug 	Result shows results from all post types WRONG
	'public' => false	'publicly_queryable' => false	/?s=search-term&post_type=cpt-slug 	Result shows results from all post types WRONG

'exclude_from_search' => true
	'public' => true	'publicly_queryable' => true	/?s=search-term 			Only results from other post types
	'public' => false	'publicly_queryable' => true	/?s=search-term 			Only results from other post types
	'public' => true	'publicly_queryable' => true	/?s=search-term&post_type=cpt-slug 	Results show from this post type WRONG
	'public' => false	'publicly_queryable' => true	/?s=search-term&post_type=cpt-slug 	Results show from this post type WRONG
	'public' => true	'publicly_queryable' => false	/?s=search-term 			Only results from other post types
	'public' => false	'publicly_queryable' => false	/?s=search-term 			Only results from other post types
	'public' => true	'publicly_queryable' => false	/?s=search-term&post_type=cpt-slug 	Results from all other post types WRONG
	'public' => false	'publicly_queryable' => false	/?s=search-term&post_type=cpt-slug 	Results from all other post types WRONG

register_post_type_args的用法

上面已经说过了,在调用 register_post_type这个函数的时候,有非常非常多的参数可以进行设置,在实际使用中有时候注册好了之后发现有些参数没有设置,或者有的参数设置的不符合需求。要修改也很简单。

WordPress 为我们提供了一个过滤器register_post_type_args,使用这个过滤器,可以修改现有文章类型的参数,从而对已注册的文章类型的属性进行修改,可以多次任意修改。如果你对过滤器的使用不熟悉的话,也可以看看本博客中关于过滤器的文章

比如下面的示例中,我们修改了awsome_app 文章类型的中的参数publictrue,使其在后台中显示出来。

代码语言:javascript
复制
add_filter( 'register_post_type_args', 'change_awsome_app_args', 10, 2 );

function change_awsome_app_args( $args, $post_type ) {
	// Make sure we're only modifying our desired post type.
	if ( 'awsome_app' != $post_type )
		return $args;
	$args['public'] = true;
	return $args;
}

public: Controls how the type is visible to authors (show_in_nav_menus,?show_ui) and readers (exclude_from_search,?publicly_queryable).

如上图所见,现在可以在后台中看到这个post type了,还有一个问题,名字不对,这是因为刚才我们注册的时候只是定义了类别的名称(相当于学名),没有定义一个具体的描述性的名字(相当于小名)。

参照官网的说明,post type的名字是在labels这个参数里定义的,是用来配置显示文案有关的内容,必须是一个数组。所以改一下上面的代码,如下:

代码语言:javascript
复制
add_filter( 'register_post_type_args', 'change_awsome_app_args', 10, 2 );

function change_awsome_app_args( $args, $post_type ) {
	// Make sure we're only modifying our desired post type.
	if ( 'awsome_app' != $post_type )
		return $args;

	$args['public'] = true;

	$args['labels'] = array( 'name' => __( 'Apps' ) );

	return $args;
}

name’ – general name for the post type, usually plural. The same and overridden by $post_type_object->label. Default is Posts/Pages

关于Custom Post Type的URL

经过上面的折腾,现在已经可以在后台看到这个类型,也可以在这个类型下面进行新建文章的操作了,理论上也可以在网站前端看到了。

但是如果你现在兴致冲冲的点击这篇文章的view链接想看一看效果,很可能给你大大的404提示,一盆冷水浇头,What the Fuck?哪里搞错了?

其实上面的步骤并没有什么地方搞错,只不过这一步的更改比较隐蔽。

如果你直接访问 http://127.0.0.1:20002/?awsome_app=appppppppppp ,这种是添加了key-value查询参数的动态URL,这个地址就不会404。

注意看下图中默认访问的URL形式是:http://127.0.0.1:20002/awsome_app/appppppppppp/,这个URL是怎么来的呢?

这是因为在WordPress中启用了URL规则重写(rewrite)功能,会自动把和Post相关的动态URL改写为伪静态URL,这也会影响到自定义的Post Type。而创建自定义文章类型的时候有一个参数是rewrite,默认是true,也会使用伪静态形式URL。

rewrite(boolean or array) (optional) Triggers the handling of rewrites for this post type. To prevent rewrites, set to false.Default: true and use $post_type as slug

动态地址访问ok,伪静态地址404,这一现象主要是因为在 WordPress 中的伪静态规则会被存储到数据库,新的文章类型注册之后原有的伪静态并不会自动更新,也就无法识别这个URL,所以就404了。

正如官网上的提示,如果你在WordPress中启用了URL规则重写,而且在创建自定义Post Type的时候没有把参数rewrite设置为false,那么在注册之后,还需要一些额外步骤来进行伪静态规则的刷新。如果创建的时候设置了rewritefalse,使用动态URL,那么可以直接略过下面所有的步骤了。。。。

Note:?If registering a post type inside of a plugin, call?flush_rewrite_rules()?in your activation and deactivation hook (see?Flushing Rewrite on Activation?below). If flush_rewrite_rules() is not used, then you will have to manually go to Settings > Permalinks and refresh your permalink structure before your custom post type will show the correct structure. https://codex.wordpress.org/Function_Reference/register_post_type

如果你是使用了相关插件来进行自定文章类型的设置,基本上不会出现这种情况,因为开发者多半会在相关的主题或者插件启用的时候调用flush_rewrite_rules() 函数来刷新伪静态规则,帮你把这一步做掉了。

刷新WordPress 的伪静态规则的方法

第一种方法:WordPress后台中操作

在WordPress的Settings中找到Permalink Settings,拉到最下面,什么都不要改,直接再点一次Save 就可以了,这种方法是最直观最简单的。

The easiest way is to safe the Permalink structure in your settings again.?

第二种方法:PHP代码

上面说过,WordPress提供了一个函数flush_rewrite_rules可以用来刷新url规则,所以你也可以在自己的主题文章中手动执行这个函数。可以参考官网上flush_rewrite_rules的示例

代码语言:javascript
复制
function myplugin_flush_rewrites() {
	// call your CPT registration function here (it should also be hooked into 'init')
	myplugin_custom_post_types_registration();
	flush_rewrite_rules();
}
/* Flush rewrite rules for custom post types. */
add_action( 'after_switch_theme', 'flush_rewrite_rules' );

另外要注意,更新伪静态规则是非常消耗时间和效率的,所以不要每次执行代码都调用,只在必要的情况调用(比如启用主题和启用插件),把 flush_rewrite_rules() 挂到 init 钩子上是极其不正确的。新建一个文章类之后更新一次就可以。

如果还是不行,那么还可以放大招。

第三种方法:改数据库

重要提示:任何情况下都要尽量避免直接操作线上数据库,这属于高危操作。以下内容仅作演示用,如果你对数据库不熟悉,不要轻易模仿,操作失误本人概不负责。操作之前做好备份!

如果你对自己的WordPress数据库有权限,那么你可以直接修改数据库中的wp_options来进行rewrite rules的刷新,本质上这些规则都是存在option_value这个字段中,只要把这个字段的值清空即可。

首先通过phpMyadmin或者其他第三方MySql客户端连上数据库,找到这一行:

代码语言:javascript
复制
SELECT * FROM  `wp_options` WHERE  `option_name` =  'rewrite_rules';

rewrite_rules

然后手动编辑把option_value这个字段清空,或者使用下面的命令:

代码语言:javascript
复制
UPDATE `wp_options` SET `option_value` = '' WHERE  `option_name` =  'rewrite_rules';

甚至你可以用更粗暴的方式,就是直接把rewrite_rules 这一行删除掉!WordPress还会自动再加回来。

不管用哪种方式,再次打开刚才的文章链接就不会404了。可以愉快的在自定义文章类型下面发布文章了。

设置Custom Post Type的固定连接样式

搞定了伪静态URL的404问题之后,再来具体看看Custom Post Type 的固定连接样式问题。

Custom Post Type的固定链接(Permalink)结构默认是类似 /custome_post_type/post_name,如果没有设置slug,则默认会用post type的类型名作为slug,如果设置了自定义的slug,那就是形如/cumstomslug/post_name。本例中没有指定 slug ,要想改变也很简单,只要在创建的时候传入几个参数即可,或者用上文提到的register_post_type_args这个方法来修改。参数如下:

代码语言:javascript
复制
 // 定义该文章类型的 URL 结构,我们可以设置一个具体的参数或一个布尔值,如果设置为 false,该文章类型将不支持
        // URL Rewrite 功能
        'rewrite'             => [

            // 文章类型的别名
            'slug'       => 'example', // string (默认为文章类型名称)

            // 是否在固定链接中显示 $wp_rewrite->front 文章类型别名
            'with_front' => false, // bool (默认为 TRUE)

            // 是否允许文章类型中的文章通过 <!--nextpage--> 快捷标签实现分页
            'pages'      => true, // bool (默认为 TRUE)

            // 是否为订阅源创建漂亮的固定链接feeds.
            'feeds'      => true, // bool (默认为 'has_archive' 的值)

            // 为固定链接设置设置 endpoint 遮罩
            'ep_mask'    => EP_PERMALINK, // const (默认为 EP_PERMALINK)
        ],

上面这种/slug/post_name/形式的URL结构其实对搜索引擎也算是比较友好的。但是如果你想对其进一步自定义的话,WordPress并没有在后台提供自定义文章类型的固定链接设置,上文提到的Settings中找到Permalink Settings这种设置方式只对自带的Post有效,Custom Post Type在属性上更接近于Page,而非Post,更改它们的固定链接需要通过代码或插件实现。

使用代码的方式比较重,比较麻烦,不适合普通用户,而且我也没有这方面的需求,就不写了,感兴趣的可以看看这篇文章: 如何修改自定义文章类型的固定链接

这方面最好的插件就是?Custom Post Type Permalinks. 使用很简单,安装、激活,在Settings中找到Permalink Settings页面中会多出一部分,能够让你对自定义文章类型的固定链接格式进行设置,就像设置文章的固定链接那样。

未完待续

关于Custom Post Type的内容实在是太多了,本篇限于篇幅先写到这里了。下一篇将继续详细介绍关于Custom Post Type的后台管理功能、前台显示、查询、分类、归档页等内容。敬请期待

本文参考了大量资料:

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-04-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一点背景知识
    • 面向对象编程(Object Oriented Programming)
      • 什么是类?
      • 什么是对象?
      • 类和对象的关系?
    • WordPress中的面向对象
    • 创建Custom Post Type的方法
      • 主题中创建Custom Post Type
        • 插件创建Custom Post Type
          • register_post_type函数的用法
            • register_post_type函数支持的参数
              • 和public值相关的参数
              • register_post_type_args的用法
              • 关于Custom Post Type的URL
                • 刷新WordPress 的伪静态规则的方法
                  • 第一种方法:WordPress后台中操作
                  • 第二种方法:PHP代码
                  • 第三种方法:改数据库
                • 设置Custom Post Type的固定连接样式
                  • 未完待续
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                  http://www.vxiaotou.com