WordPress主题开发,从入门到精通。

相关文档:https://www.wpzhiku.com/document/wordpress-plugin-basics/

全局变量:https://codex.wordpress.org/zh-cn:%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8Fhttps://codex.wordpress.org/Global_Variables

wp_query查询内容:https://developer.wordpress.org/reference/classes/wp_query

wp_comments-query评论查询:https://developer.wordpress.org/reference/classes/wp_comment_query

应用程序接口:https://make.wordpress.org/core/handbook/best-practices/core-apis/

官方开发文档:https://developer.wordpress.org/themes/basics/theme-functions/

主题相关

1.如何为不同分类的页面显示不同的模板。

文章页面默认调用的是single.php,可以在single.php里判断不同的分类,include不同的模板文件。

2.get_template_part

get_template_part( $slug,  $name = null,$args = array() ),将模板部件加载到模板中,并传递一个参数。

要将此功能与主题目录中的子文件夹一起使用,只需在 slug 之前添加文件夹名称即可。例如,如果您的主题目录中有一个名为“partials”的文件夹,而该子文件夹中有一个名为“content-page.php”的模板部分,则可以这样使用get_template_part():

<?php get_template_part( 'partials/content', 'page' ); ?>

Hook列表

1.after_setup_theme

在主题初始化后(funtions.php已经执行完毕),每次页面加载期间都会调用此钩子。它通常用于执行主题的基本设置、注册和初始化操作。

2.init

大部分 WP 在这个阶段被加载,并且用户被认证。WP 继续加载随后的“init”钩子(例如小部件),许多插件出于各种原因在其上实例化自己(例如,它们需要用户、分类等)。

3.wp_loaded

彻底加载完毕, WP、所有插件和主题完全加载并实例化,就会触发此钩子。https://developer.wordpress.org/reference/hooks/wp_loaded/

4.admin_init

当管理员页面或脚本正在初始化时触发,当用户访问管理区域时,在任何其他挂钩之前触发。不仅在面向用户的管理屏幕上运行。它也在 admin-ajax.php 和 admin-post.php 上运行。

加载顺序:after_setup_theme  -->  init  --> wp_loaded  --> admin_init

5.wp_enqueue_scripts、admin_enqueue_scripts、login_enqueue_scripts

当脚本和样式入队时触发。用于将主页面的脚本和样式排入队列。

6.edit_form_after_title

在WordPress撰写文章页面添加一段提示标语的功能。

7.wp_head、wp_body_open(放在Body之后)、wp_footer

利用钩子函数的输出,在指定标签的位置输出相应的内容;wp_head(),方法内就是一个do_action("wp-head")

8.after_switch_theme

主题切换后,第一次加载wp时触发的钩子;check_theme_switched()检查是否已经触发这个钩子

9.save_post、publish_post、edit_post

在文章保存后立即触发,remove_all_actions(),移除所有钩子,did_action(),钩子的运行次数

10.admin_menu

在后台加载管理菜单之前触发。

主题可用函数

带s的方法一般是钩子函数的包装器,可以直接传入函数作为钩子;

1.add_theme_support

WordPress 默认隐藏了很多功能,我们可以通过 add_theme_support() 函数启用它们,add_theme_support可以在主题的functions.php中调用,如需在hook中调用的必须在after_theme_setup中调用;

  1. add_theme_support( 'post-thumbnails' ,[array( 'post' )]); 启用指定类型文章的缩略图功能,不指定第二个参数时默认为全部文章启用缩略图功能;
  2. post-formats:文章形式。
  3. html5:HTML5支持。
  4. custom-logo:自定义网站Logo图标。
  5. custom-header-uploads:顶部图像上传。
  6. custom-header:自定义网站顶部内容。
  7. custom-background:自定义网站背景内容。
  8. title-tag:自动生成页面标题信息,需调用。
  9. customize-selective-refresh-widgets:小部件选择性更新。
  10. starter-content:内容初始化。
  11. responsive-embeds:自适应嵌入内容。
  12. align-wide:配置块编辑器宽对齐。
  13. dark-editor-style:配置暗风格块编辑器。
  14. disable-custom-colors:禁用快编辑器自定义颜色。
  15. disable-custom-font-sizes:禁用快编辑器自定义字体大小。
  16. editor-color-pallete:配置块编辑器调色板。
  17. editor-font-sizes:配置块编辑器字体大小。
  18. editor-styles:配置块编辑器样式。
  19. wp-block-styles:启用默认块编辑器样式。

2.目录、路径的相关函数

get_template_directory,获取活动主题所在的目录路径;
get_template_directory_uri()获取活动主题的完整URL;
get_stylesheet_uri(),获取活动主题的style.css的完整URL路径;
get_theme_file_path($file)、get_theme_file_uri($file) 一样 ,这个函数将返回主题中文件的路径(如果存在)。

3.wp_get_theme()

获取当前启用的主题相关说明信息(style.css文件内的主题说明),wp_get_themes(),获取系统内所有的主题信息;

4.样式、脚本加载

只在wp_enqueue_scripts(主页面)、admin_enqueue_scripts(后台)、login_enqueue_scripts(登录页面)钩子内可用;

<?php
/*注册样式*/
wp_enqueue_style( string $handle(样式名), string $src = ''(样式文件的目录路径), string[] $deps = array()(依赖的文件), string|bool|null $ver = false(动态版本号), string $media = 'all' (支持的媒体类型));按照注册的队列加载css文件。
/*注册脚本*/
wp_enqueue_script( string $handle, string $src = '', string[] $deps = array(), string|bool|null $ver = false, bool $in_footer = false )
/*内联样式*/
wp_add_inline_style()
/*内联脚本*/
wp_add_inline_script()

参考:https://developer.wordpress.org/reference/functions/wp_add_inline_script/ 

5.删除已注册的样式表、脚本

  • wp_deregister_style(style)
  • wp_dequeue_script(script)

6.文章相关函数

这些函数需要在循环中工作,因为它们需要全局 post 对象,WordPress 循环会自动设置这个 post 对象。

  1. in_the_loop(),是否处于文章循环;
  2. get_the_ID,获取文章ID;
  3. the_title,输出文章标题
  4. the_title_attribute(['before'=>"前",'after'=>"后",'post'=>1]); 指定相关属性输出标题
  5. get_the_title,获取文章标题
  6. the_guid,文章的GUID
  7. get_the_guid,获取文章的GUID
  8. the_content,文章内容
  9. get_the_content,获取文章内容
  10. the_excerpt,文章摘要
  11. get_the_excerpt,获取文章摘要
  12. has_excerpt,是否有文章摘要
  13. post_password_required,是否需要密码
  14. next_post(),下一篇文章
  15. previous_post(),前一篇文章

7.缩略图

  1. has_post_thumbnail,是否拥有缩略图
  2. get_post_thumbnail_id,获取缩略图ID
  3. the_post_thumbnail,输出缩略图(img元素)
  4. update_post_thumbnail_cache
  5. get_the_post_thumbnail,缩略图(img元素)
  6. get_the_post_thumbnail_url,缩略图URL
  7. the_post_thumbnail_url,输出缩略图URL
  8. get_the_post_thumbnail_caption,缩略图文件标题
  9. the_post_thumbnail_caption,缩略图文件标题

8.站点信息

页面判断函数需要在指定声明周期之后才会有值,例如function加载的时候是没有的,wp_enqueue_scripts钩子内是有值的。

  1. bloginfo([$key])、get_bloginfo([$key]);
  2. is_user_logged_in(),是否已经登录
  3. is_home(),是否处于首页;
  4. is_admin(),是否处于后台;
  5. is_single(),传递空、文章ID、文章标题,判断是否在这个文章页面;
  6. is_sticky(),传递空、文章ID、文章标题,判断是否是置顶的文章
  7. is_page(),传递空、文章ID、文章标题,判断是否在这个页面;
  8. $paged = $wp_query->get( 'page' ); 获取分页所处的页数;
  9. is_page_template(‘about.php’),是否处于某个页面模板;
  10. is_category(),传递空、分类ID、分类标题,判断是否在某个分类页面;
  11. is_archive()、is_search()、is_404()

以上所有get都可以单独指定wp_post对象;

9.列表

  • 传递一个配置数组获取页面列表:wp_list_pages()
  • 传递一个配置数组获取目录列表:wp_list_categories()
  • 传递一个配置数组获取评论列表:wp_list_categories()

10.posts表相关操作方法

  • wp_update_post(),更新文章
  • wp_insert_post(),插入文章
  • wp_is_post_revision(),
  • wp_trash_post(),删除文章到回收站
  • wp_delete_post(),删除文章
  • wp_publish_post(),发布文章,改为发布状态

相对应的还有wp_insert_attachment、wp_insert_category等钩子;

11.网络

  • wp_send_json_success
  • wp_send_json_error
  • wp_send_json
  • 响应json数据,然后die

11.附件

  • wp_get_attachment_thumb_file
  • wp_get_attachment_thumb_url
  • wp_get_attachment_link
  • wp_get_attachment_url
  • wp_get_attachment_image_src
  • wp_generate_attachment_metadata,获取附件的元信息
  • wp_update_attachment_metadata,更新附件的元信息

post表保存的是基本信息,访问附件的URL保存在post_meta表

12.wp_options表

option可直接存放一个数组;当我们单独访问许多选项数据时,可能导致许多单独的数据库事务,通常,数据库事务是昂贵的操作(就时间和服务器资源而言)而把许多选项作为数组存储和获取时,只会产生一个数据库事务,这是一种比较理想的操作。

  • update_option 更新WP设置选项
  • delete_option,从 WordPress 选项数据表中安全删除“选项/值”对的方法。
  • add_option 添加设置选项
  • get_option 获取选项设置值
  • add_site_option、get_site_option...

13.wp_posts文章类型

Post、Page、Attachment、Revision、Navigation Menu Items

14.转义

  • esc_html() – 在显示 HTML 时,使用此函数。
  • esc_url() – 在输出 URL 时,使用此函数,包括在src和href属性中的 URL。
  • esc_js() – 对内联 JavaScript 使用此函数。
  • esc_attr() – 把数据设置为 HTML 元素属性时使用此能力。
  • 相对于使用 echo 输出数据,我们应该更多的使用 WordPress 的本地化能力,如 _e() 或 __()

15.简码

  • add_shortcode()
  • remove_shortcode()
  • shortcode_exists()
  • 简码解析器只对简码的内容进行一次传递。
  • 可以在处理函数的最终返回值上调用 do_shortcode() ,使 $content 中包含的简码也可以被解析。简码可以接受一些参数,我们称之为简码的属性

16.元数据

指的是post_meta表里的数据,一般用于保存post表内容有关的元数据。

  • get_post_meta($postID, $count_key, true); //查询元字段数据
  • delete_post_meta($postID, $count_key);//删除原字段数据
  • add_post_meta($postID, $count_key, '0');//新增元字段数据
  • update_post_meta($postID, $count_key, '0');//更新元数据

17.query_posts函数

query函数用于查询文章,将会修改wordpress主查询的指向:

wp_reset_query用于重置主循环的指针。

<?php
    query_posts("showposts=10");
    while (have_posts()) {
        the_post();//移动文字指定到此处
        get_the_permalink();
        get_the_title(); 
        get_the_title();
    }
    wp_reset_query(); //重置文章指指针
?>

18.get_posts函数

指定参数查询文章,返回一个wp_Query对象数组,代表所有符合条件的文章:

支持的参数:https://developer.wordpress.org/reference/classes/wp_query/parse_query/

<?php
/* 检索10条最新的指定类型的文章 */
$args = array(
  'numberposts' => 10,
  'post_type'   => 'book'
);
 
$latest_books = get_posts( $args );

19.get_query_var函数

get_query_var用于查询公共变量,例如

<?php
//获取当前页码,默认值返回1
$page = get_query_var( 'page', 1 );  

20.update_user_meta

update_user_meta用于更新用户信息

update_user_meta( int $user_id, string $meta_key, mixed $meta_value, mixed $prev_value = '' );
  • userid,代表需要更新数据的用户ID
  • meta_key,代表需要更新的key
  • meta_value,更新之后的值
  • prev_value,更新前的值,用户区分具有相对用户ID和key的数据,不指定时将更新所有数据

21.站点URL

  • plugins_url() — 插件目录的 URL (例如:https://nicen.cn/wp-content/plugins)
  • includes_url() — includes 目录的 URL (例如:https://nicen.cn/wp-includes)
  • content_url() — content 目录的 URL (例如:https://nicen.cn/wp-content)
  • admin_url() — admin 目录的 URL (例如:https://nicen.cn/wp-admin/)
  • site_url() — 当前网站的 URL (例如:https://nicen.cn)
  • home_url() — 当前网站首页的 URL (例如:https://nicen.cn)

22.获取标签、目录链接

get_tag_link 调用的是get_category_link,get_category_link又调用get_term_link(参数为对象或term_id)

23.获取用户的头像

<?php
   get_avatar_url( $adminUserInfo->ID )

24.判断是不是移动设备

<?php 
     wp_is_mobile();

25.获取查询对象

<?php

//访问分类或者标签时返回分类和标签的wp_term对象
$term = get_queried_object();

26.获取所有标签

$tags = get_terms(array( 'taxonomy' => 'post_tag', 'hide_empty' => false, ));

WP_Rewrite对象

WP_Rewrite是 WordPress 的类,用于管理重定向规则。官方不建议直接修改该对象的属性,而是通过它的方法进行操作。

<?php
$wp_rewrite->pagination_base = nicen_theme_config("document_rewrite_page_prefix", false);// 作者归档翻页前缀
$wp_rewrite->flush_rules();//刷新规则

API文档:https://codex.wordpress.org/Rewrite_API

自定义编辑器

TinyMCE:https://www.tiny.cloud/docs-4x/api/tinymce/root_tinymce/

1.TinyMCE4.x版本相关方法

2.添加插件的两种方式;

  • 先create一个类,再通过PluginManager.add添加插件。
  • 直接PluginManager.add一个对象,添加插件。

3.tinymce.Editor,编辑器核心API

官方文档:https://www.tiny.cloud/docs-4x/api/tinymce/tinymce.editor

  1. selection,代表编辑器内被选中的内容的对象;https://www.tiny.cloud/docs-4x/api/tinymce.dom/tinymce.dom.selection/
    • getContent(),获取被选中对象的内容;
    • setContent(),设置被选中对象的内容
  2. windowManager,可打开一个新的窗口或者对话框;https://www.tiny.cloud/docs-4x/api/tinymce/tinymce.windowmanager/

4.wp注册tinymce插件、样式、按钮

<?php
add_action( 'admin_init', 'my_tinymce_button' );

/*后台初始化*/
function my_tinymce_button() {
	if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) ) {
                /* 编辑器新增上方按钮的勾子*/
		add_filter( 'mce_buttons', 'my_register_tinymce_button' ); 
                /* 编辑器新增插件的勾子*/   
                add_filter( 'mce_external_plugins', 'my_add_tinymce_button' );
	}
}
function my_register_tinymce_button( $buttons ) {
      /*每一个按钮代表一个插件的JS类(插件)*/
      /*JS类里指定功能和图标*/
        $buttons[] = 'success';
        $buttons[] = 'alert';
        $buttons[] = 'error';
        $buttons[] = 'h1';
        $buttons[] = 'h2';
        $buttons[] = 'h3';
        $buttons[] = 'code';
        $buttons[] = 'lightbox';
        $buttons[] = 'mark';
	return $buttons;
}
function my_add_tinymce_button( $plugin_array ) {
	$plugin_array['my_button_script'] = plugins_url( '/mybuttons.js', __FILE__ );/*指定要加载的插件*/
	return $plugin_array;
}

 /* 编辑器新增样式的勾子*/
add_filter( 'mce_css', 'pure_highlightjs_mce_css' ); /* 样式新增的勾子*/
function pure_highlightjs_mce_css( $mce_css ) {
	if ( ! is_array( $mce_css ) ) {
		$mce_css = explode( ',', $mce_css );
	}
	$mce_css[] = PURE_HIGHLIGHTJS_PLUGIN_URL . 'tinymce/tinymce.css';
	return implode( ',', $mce_css );
}

5.新增短标签

/* 标题标签 */
function nrtitle($atts, $content = null, $code = "")
{
    static $times=1;
    $return = '<h2 id="list'.$times.'">';
    $return .= $content;
    $return .= '</h2>';
    $times++;
    return $return;
}

add_shortcode('title', 'nrtitle');

技巧

1.文章是否有缩略图

<?php
if ( has_post_thumbnail() ) {
    the_post_thumbnail();
}

2.注册加载样式文件,并根据修改时间自动修正版本号

//样式加载
wp_enqueue_style('main-styles', get_template_directory_uri() . '/css/style.css', array(), filemtime(get_template_directory() . '/css/style.css'), false);
//脚本加载
wp_enqueue_script('prism', $url . '/common/prism/prism.js', array(), filemtime($root . '/common/prism/prism.js'), false);

3.获取wordpress注册的所有action和filter钩子

<?php
global $wp_filter;
print_r($wp_filter);

4.去除头部无用代码

function initialize(){

    /*
     * 去除头部多余无用的东西
     * */
    remove_action('wp_enqueue_scripts', 'wp_enqueue_global_styles'); //内联样式
    remove_action('wp_footer', 'wp_enqueue_global_styles', 1);//dobate图标
    remove_action('wp_head', 'wp_generator'); //移除WordPress版本
    remove_action('wp_head', 'rsd_link'); //移除离线编辑器开放接口
    remove_action('wp_head', 'wlwmanifest_link'); //移除离线编辑器开放接口
    remove_action('wp_head', 'index_rel_link'); //去除本页唯一链接信息
    remove_action('wp_head', 'parent_post_rel_link', 10, 0); //清除前后文信息
    remove_action('wp_head', 'start_post_rel_link', 10, 0); //清除前后文信息
    remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0); //清除前后文信息
    remove_action('wp_head', 'feed_links', 2); //移除feed
    remove_action('wp_head', 'feed_links_extra', 3); //移除feed
    remove_action('wp_head', 'rest_output_link_wp_head', 10); //移除wp-json链
    remove_action('wp_head', 'print_emoji_detection_script', 7); //头部的JS代码
    //remove_action( 'wp_head', 'wp_print_styles', 8 ); //emoji载入css
    remove_action('wp_head', 'rel_canonical'); //rel=canonical
    remove_action('wp_head', 'wp_shortlink_wp_head', 10, 0); //rel=shortlink

    /*移除emjoy*/
    remove_action('wp_head', 'print_emoji_detection_script', 7);
    remove_action('admin_print_scripts', 'print_emoji_detection_script');
    remove_action('wp_print_styles', 'print_emoji_styles');
    remove_action('admin_print_styles', 'print_emoji_styles');
    remove_filter('the_content_feed', 'wp_staticize_emoji');
    remove_filter('comment_text_rss', 'wp_staticize_emoji');
    remove_filter('wp_mail', 'wp_staticize_emoji_for_email');

    /*移除文章内的embed内容*/
    remove_action('wp_head', 'wp_oembed_add_discovery_links');
    remove_action('wp_head', 'wp_oembed_add_host_js');


    add_filter('wp_resource_hints', //移除WordPress头部加载DNS预获取(dns-prefetch)
        function ($hints, $relation_type) {
            if ('dns-prefetch' === $relation_type) {
                return array_diff(wp_dependencies_unique_hosts(), $hints);
            }

            return $hints;
        }, 10, 2); //头部加载DNS预获取(dns-prefetch)

}
add_action('after_setup_theme', 'initialize'); //去除博客无用代码

5.禁用区块编辑器

//禁止Gutenberg编辑器
add_filter('use_block_editor_for_post', '__return_false');
remove_action( 'wp_enqueue_scripts', 'wp_common_block_scripts_and_styles' );

6.切换经典小工具编辑器

//禁止新版小工具
add_filter( 'gutenberg_use_widgets_block_editor', '__return_false' );
add_filter( 'use_widgets_block_editor', '__return_false');

7.添加后台编辑器按钮

editor.addButton('PureHighlightjsInsert', {
	title : PureHighlightjsTrans.title,
	icon: 'wp_code',
	onclick: function() {
		editor.windowManager.open({
			title : PureHighlightjsTrans.title,
			minWidth : 700,
			body : [
				{
					type : 'listbox',
					name : 'lang',
					label : PureHighlightjsTrans.language,
					values : languageValues
				},
				{
					type : 'textbox',
					name : 'code',
					label : PureHighlightjsTrans.code,
					multiline : true,
					minHeight : 200
				}
			],
			onsubmit : function(e){
				var code = e.data.code.replace(/rn/gmi, 'n'),
					tag = 'code';

				code =  tinymce.html.Entities.encodeAllRaw(code);

				var sp = (e.data.addspaces ? '&nbsp;' : '');

				editor.insertContent(sp + '<pre class="pure-highlightjs"><code class="' + e.data.lang + '">' + code + 'n</code></pre>' + sp + '<p></p>');
			}
		});
	}
});

8.注册插件

tinymce.create('tinymce.plugins.info', {
	init : function(ed, url) {
		ed.addButton('info', {
			title : '蓝色背景栏',
			image : url+'/images/info.png',
			onclick : function() {
				 ed.selection.setContent('[info]' + ed.selection.getContent() + '[/info]');
			}
		});
	},
	createControl : function(n, cm) {
		return null;
	},
});
tinymce.PluginManager.add('info', tinymce.plugins.info);

9.wp版本比较

if ( version_compare( $GLOBALS['wp_version'], '5.3', '<' ) ) {}	

10.去除后台底部版权和文字提示

function remove_footer( $text ) {
    $text = '';
    return $text;
}

/*
 * 删除WordPress后台底部版权信息、版本号
 * */
add_filter('update_footer', 'remove_footer', 11);
add_filter('admin_footer_text', 'remove_footer', 11);

11.更换Gavatar镜像

/*
 * 替换Gravatar头像镜像站地址
 * */
function replace_https_avatar( $avatar ) {
    $Image = get_option( 'document_Gravatar' );
    //~ 替换为 https 的域名
    $avatar = str_replace( array(
        'secure.gravatar.com/avatar',
        "www.gravatar.com/avatar",
        "0.gravatar.com/avatar",
        "1.gravatar.com/avatar",
        "2.gravatar.com/avatar"
    ), $Image, $avatar );
    //~ 替换为 https 协议
    $avatar = str_replace( "http://", "https://", $avatar );

    return $avatar;
}

/*
 * 替换Gravatar镜像站地址
 * */
add_filter('get_avatar', 'replace_https_avatar');
add_filter('get_avatar_url', 'replace_https_avatar');

12.修改文章摘要字数

/*
 * 修改文字摘要字数
 * */
function article_excerpt_lengths( $length ) {
    return 300;
}

/*修改文章摘要的数量*/
add_filter( 'excerpt_length', 'article_excerpt_lengths', 999 );

13.添加页面模板

/*
 * 添加后台可选的页面模板
 * */
function add_page_template( $page_templates ) {
    $page_templates['template/page/posts.php']='文章聚合';
    return $page_templates;
}
add_filter( 'theme_page_templates', 'add_page_template' );
add_filter( 'theme_post_templates', 'add_page_template' );

14.修改页面的固定链接

/*
 * 修改页面的固定链接
 * */
add_action( 'init', 'custom_page_rules' );
function custom_page_rules() {
    global $wp_rewrite;
    $wp_rewrite->page_structure = $wp_rewrite->root . '%pagename%.html';
}

15.输出文章分页

官方文档:https://developer.wordpress.org/reference/functions/get_the_posts_pagination/

<?php
$pagination = get_the_posts_pagination( array(
	'prev_next'          => false,
	'current'            => max( 1, get_query_var( 'paged' ) ),  //当前页码
	'type'               => 'list'
) );
/*去除多余的元素*/
$pagination=preg_replace( '/^[sS]*?(<ul[sS]*>[sS]*</ul>)[sS]*?$/', "$1", $pagination );

16.输出评论分页

<?php if(get_comment_pages_count()>1){ ?>
        <div class="pagination">
            <?php paginate_comments_links( ['prev_next' => false]); ?>
        </div>
<?php } ?>

17.用户是否登录

<?php
//是否登录
$isLogin = is_user_logged_in();
//用户信息
$Info    = wp_get_current_user();

18.博客功能设置

<?php
/*
 * 主题功能
 * */
add_theme_support( 'post-thumbnails'); //开启主题缩略图
add_theme_support( 'menus'); //开启主题菜单功能
add_theme_support( 'widgets'); //开启自定义侧边栏
add_theme_support( 'widgets-block-editor'); //开启自定义侧边栏
remove_filter('the_content', 'wptexturize');  //关闭文章转义

模板循环

1.基本用法

<?php 
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        // 显示文章内容
    endwhile; 
endif; 
?>

注册主题菜单

  1. register_nav_menu(),注册单个自定义的主题页面菜单
  2. register_nav_menus(),注册多个自定义的主题页面菜单
  3. unregister_nav_menu(),删除菜单注册
  4. wp_nav_menu($args);给定一个theme_location参数,该函数显示分配给该位置的菜单。如果不存在这样的位置或没有为其分配菜单,则参数fallback_cb将确定显示的内容。如果没有给定theme_location参数,函数显示与menu参数给出的 ID、slug 或名称匹配的菜单;否则,第一个非空菜单;否则(或者如果 menu 给定的菜单为空),则输出fallback_cb参数给定的函数(默认为wp_page_menu());否则什么都没有。
  5. has_nav_menu(),判断某个注册的菜单是否已经被分配菜单

wp_nav_menu默认参数

<?php
$defaults = array(
	'menu'                 => '',
	'container'            => 'div',
	'container_class'      => '',
	'container_id'         => '',
	'container_aria_label' => '',
	'menu_class'           => 'menu',
	'menu_id'              => '',
	'echo'                 => true,
	'fallback_cb'          => 'wp_page_menu',
	'before'               => '',
	'after'                => '',
	'link_before'          => '',
	'link_after'           => '',
	'items_wrap'           => '<ul id="%1$s" class="%2$s">%3$s</ul>',
	'item_spacing'         => 'preserve',
	'depth'                => 0,
	'walker'               => '',
	'theme_location'       => '',
);

后台添加菜单、主题设置

1.添加菜单和页面

  • add_menu_page($page_title , $menu_title , $capability ,  $menu_slug , $callback ' , $icon_url ' , $position ),$menu_slug 为分节注册可用的page参数;$capability,代表用户需要什么权限才会显示这个菜单;
  • add_menu_page、remove_menu_page,注册、删除一个顶级菜单已经相对应的页面;
  • add_submenu_page、remove_submenu_page,注册、删除一个子菜单
  • add_dashboard_page() –index.php、add_posts_page() –edit.php、add_media_page() –upload.php、add_pages_page() –edit.php?post_type=page、add_comments_page() –edit-comments.php、add_theme_page() –themes.php、add_plugins_page() –plugins.php、add_users_page() –users.php、add_management_page() –tools.php、add_options_page() –options-general.php、add_options_page() –settings.php、add_links_page() – link-manager.php– WP 3.5 以后,需要一个插件才能使用。
<?php
// add top level menu
add_menu_page(page_title, menu_title, capability, handle, [function], [icon_url]);
// add sub-menu pages
add_submenu_page(parent, page_title, menu_title, capability, file/handle, [function]);
// add Options sub-menu
add_options_page(page_title, menu_title, capability, handle, [function]);
// add Management sub-menu
add_management_page(page_title, menu_title, capability, handle, [function]);
// add Pages sub-menu
add_pages_page( page_title, menu_title, capability, handle, [function]);
// add Posts sub-menu
add_posts_page( page_title, menu_title, capability, handle, [function]);
// add Appearances sub-menu
add_theme_page( page_title, menu_title, capability, handle, [function]); 

上面这些函数都有一个必须的参数capability。这意味着登录到后台的用户需要有相应的职能才能够看到这里添加的菜单选项。 如果你的主题或者插件有一个选项页,合理的 控制对该页的访问时非常重要的。例如,如果有一个主题选项页,你需要使用edit_themes这个职能(capability),如果是一个插件选项页,就需要使用edit_plugins职能。另一种方法是为插件和主题选项也使用manage_options这个职能.

2.添加设置

以下函数,可以编辑、修改、增加后台设置菜单的页面功能,以及新增菜单页面。

register_setting注册的能够通过表单自动更新、add_option只是普通的选项;

  •  register_setting('reading', 'wporg_setting_name',["type"=>"boolean","description"=>"描述"]); 为指定页面注册一个新设置(系统默认的有“general”、“discussion”、“media”、“reading”、“writing”和“options”),可以通过get_option获取register_setting的值;
  • add_settings_section($id,$title,$callback,$page) ,在指定的设置页面($page)上添加一个标题为$title、内容为$callback输出的新分节。
  • add_settings_field($id,$title,$callback,$page,$section,$args ) ,将指定标题的callback内容的新字段添加指定页面的指定分节上面。
  • unregister_setting(),如字面意思;
  • settings_fields( string $option_group ),输出register_setting注册的所有输入域;参数为option_group;(声明可以修改的选项)
  • do_settings_sections( $page ),打印添加到特定设置页面的所有设置部分(HTML代码)
  • submit_button( string $text = null, string $type = 'primary', string $name = 'submit', bool $wrap = true, array|string $other_attributes = null ),提供一个提交按钮;
  • settings_fields()、do_settings_sections()、do_settings_fields()、 add_settings_error()、get_settings_errors()、settings_errors()

3.settings_fields()

用于输出表单带有表单提交时用于验证的input隐藏元素;

4.do_settings_sections

用于按照wordpress内置的格式输出表单的分节

5.do_settings_fields

用于按照指定的回调输出表单元素

文章密码处理

  • post_password_required(),判断文章是否需要输入密码、是否已经输入密码;
  • get_the_password_form(),输出用于密码输入的表单

文章评论

评论相关函数必须运行在comments.php内,其它文件内调用无返回结果;

  • have_comments(),判断当前文章是否有评论;
  • comments_open(),是否打开了评论功能;
  • comment_form(),输出评论的表单;
  • wp_list_comments(),输出评论列表;
  • the_comments_navigation(),显示上、下一组评论;
  • get_comments_number(),获取文章评论数量;
  • is_user_logged_in(),当前访客是否登录;
  • wp_get_current_user(),获取当前登录的对象,返回 WP_User 对象。
  • wp_get_current_commenter(),获取当前评论着的姓名、电子邮件和 URL。
  • paginate_comments_links(),评论的分页结构
  • get_cancel_comment_reply_link(),获取取消回复的链接
  • comment_form_title(),获取当前的评论状态;
  • $reply_to_id = isset( $_GET['replytocom'] ) ? (int) $_GET['replytocom'] : 0;$comment = get_comment( $reply_to_id ); //获取回复的评论;

数据库操作

相关文章:http://www.sins7.cn/wordpress-wpdb-usage/

$wpdb是一个全局变量,包含多个关于数据库查询函数:

<?php
$wpdb -> get_results('query');  
$wpdb->query('query');  
$wpdb->get_var('query',column_offset,row_offset);  
$wpdb->get_row('query', output_type, row_offset);  
$wpdb->get_col('query',column_offset);  
$wpdb->get_results('query', output_type);  
$wpdb->insert( $table, $data, $format );  
$wpdb->update( $table, $data, $where, $format = null, $where_format = null );  
$wpdb->prepare( 'query' [, value_parameter, value_parameter ... ] );  
$wpdb->show_errors();  
$wpdb->hide_errors(); 
$wpdb->print_error();  
$wpdb->get_col_info('type', offset);  
$wpdb->flush();

瞬态数据

相较于选项,瞬态的区别是可以设置数据到期时间。

  • set_transient( $transient, $value, $expiration );
  • get_transient(),获取值
  • set_site_transient(),多站点时使用。
  • get_site_transient()多站点时使用。
  • delete_transient(),删除指定值。
  • delete_site_transient(),多站点时使用。

内置的时间单位常量:

MINUTE_IN_SECONDS  = 60 (seconds)
HOUR_IN_SECONDS    = 60 * MINUTE_IN_SECONDS
DAY_IN_SECONDS     = 24 * HOUR_IN_SECONDS
WEEK_IN_SECONDS    = 7 * DAY_IN_SECONDS
MONTH_IN_SECONDS   = 30 * DAY_IN_SECONDS
YEAR_IN_SECONDS    = 365 * DAY_IN_SECONDS

小部件 

小部件本质就是一段可直接调用的代码块(分为边栏和挂件)。官方文档:https://codex.wordpress.org/zh-cn:%E5%B0%8F%E5%B7%A5%E5%85%B7%E6%8E%A5%E5%8F%A3https://automattic.com/code/widgets/api/

1.register_widget

register_widget用于注册一个Wordpress默认的挂件;

提示
经过测试,register_widget注册的部件类中最终也是调用wp_register_sidebar_widget( WP_Widget类的567行调用了这个函数),注册的小部件。

2.the_widget

the_widget调用后,将输出指定的挂件

3.register_sidebars

register_sidebars用于注册一个侧边栏,可以指定一个索引进行注册

4.dynamic_sidebar

dynamic_sidebar用于输出注册好的侧边栏,通过索引指定输出某一个侧边栏

5.wp_register_sidebar_widget

wp_register_sidebar_widget用于注册一个边栏挂件。

5. is_active_sidebar( 'sidebar' )

判断指定的边栏是否有被激活的小工具;

用户角色和权限

官方文档:https://wordpress.org/support/article/roles-and-capabilities/

1.角色分类

WordPress 使用角色的概念来让博客的所有者对用户进行权限控制。博客所有者可以控制用户写文章、创建页面、管理插件、管理主题,以及管理其他用户的权限。博客所有者可以通过该工具分配用户权限。

  • Administrator – 系统管理员
  • Editor – 编辑,可以发布和编辑自己及他人发布的文章
  • Author – 作者,可以发布和管理他们自己的文章
  • Contributor –投稿者,他们可以投稿,和管理他们的文章,但是不能发布。
  • Subscriber – 订阅者,可以阅读评论和接收newsletter

2.current_user_can(  )

判断当前登录的用户是否具有指定的权限;检查当前用户是否有足够的职能去执行某些行为(action)

<?php

//加后一个参数时,判断用户对指定文章是否具有某种权限
current_user_can( 'edit_post', [$post_id ]); 

3.author_can( )

<?php
if ( author_can( $post, $capability ) ) {
// do something if the author of the post $post has $capability
}

4.自定义用户角色

<?php
add_role( $role_name, $display_name, $capabilities );
//例子
add_role( 'document_uploader', 'Document Uploader', array( 'organize_document' ) );

添加了一个新的角色叫做“document_uploader”,显示名称“Document Uploader"及一个职能的集合(在这个例子中,职能名称organize_document)。 可以使用current_user_can()检查当前用户是否被允许执行相应操作。

5.移除角色

<?php
 remove_role([role_name] )://移除指定的角色

6.修改已有角色的权限

<?php
// get the "author" role object
$role = get_role( 'author' );
 
// add "organize_gallery" to this role object
$role->add_cap( 'organize_document');

wp总数计算 

1.wp_count_posts

获取指定状态类型文章的总数量;

$count_posts = wp_count_posts();
 
if ( $count_posts ) {
    $draft_posts = $count_posts->draft;
}

2.wp_count_terms

wp_count_terms用于获取标签或分类的总数;

wp_count_terms('category'); //分类总数
wp_count_terms('post_tag'); //标签总数

3.评论总数

$comment =  count(get_comments());//评论总数

wp定时任务

1.wp_get_schedules

获取所有支持的定时任务时间间隔,看了一下源码,调用的是查看cron_schedules filter返回的数组;增加一个自定义的时间间隔:

<?php
   add_filter( 'cron_schedules',function($schedules){
	$schedules['nicen'] = array(
		'interval' => 3600,
		'display' => '定时任务'  //对于这个时间间隔的描述
	);
	return $schedules;	
   });

2.wp_schedule_event

wp_schedule_event用于添加一个定时任务;

wp_schedule_event("初次触发时间","间隔触发时间","触发的action hook");

3.wp_clear_scheduled_hook

wp_clear_scheduled_hook用于清理定时任务;

4.wp_unschedule_event

wp_unschedule_event用于删除一个间隔时间;

提示
添加计划任务之后,这个任务就独立了,每次只会去触发action,所有在插件被关闭后,没有这个action了,任务还会继续,所有在插件关闭时需要同步取消任务,同理表单的开关也需要同步任务的开启和关闭。

HTTP API

参考文档:https://developer.wordpress.org/plugins/http-api/

<?php

$request = wp_safe_remote_get( 'http://www.example.com/file.json' );

if ( is_wp_error( $request ) ) {
	return false;
}

$body = wp_remote_retrieve_body( $request );
$json = json_decode( $body );

1.wp_remote_get()

wp_remote_get用于进行Get请求,示例代码如下:

<?php

wp_remote_get($url,$args);

$url – 从中检索数据的资源。这必须是标准的 HTTP 格式
$args – 可选 – 您可以在此处传递一组参数来更改行为和标头,例如 cookie、跟随重定向等。
返回一个响应对象

2.获取请求结果

  • wp_remote_retrieve_body,获取响应的结果Body
  • wp_remote_retrieve_response_code,获取响应的状态码
  • wp_remote_retrieve_header,获取指定的响应头

3.wp_remote_post

wp_remote_post用于发起POST请求示例代码如下:

<?php
$args = array(
    'body'        => $body,
    'timeout'     => '5',
    'headers'=>[],
    'cookies'=>[],
    'sslverify' => false,
    'redirection' => '5',
    'httpversion' => '1.0',
    'blocking'    => true,
    'headers'     => array(),
    'cookies'     => array(),
);

$response = wp_remote_post( 'http://your-contact-form.com', $args );

4.wp_remote_request

wp_remote_request用于进行自定义请求;

提示
WP_Http_Curl对于HTTP请求的封装

前端调用媒体中心

首先通过wp_enqueue_media加载前端所需的调用媒体中心的代码

wp.media({
  title: '选择或上传图片', // 窗口标题
  button: {
    text: '选择', // 选择按钮文字
  },
  editable:   true,
  allowLocalEdits: true,
  displaySettings: true,
  displayUserSettings: true
  multiple: false // 是否允许多选
});

// 获取被选数据
media.state().get('selection').toJSON()

同样的还可以通过加载wp_enqueue_editor调用编辑器 。

1.wp_enqueue_media

wp_enqueue_media用于加载wp.media所需的JS文件

相关文档:https://developer.wordpress.org/reference/functions/wp_enqueue_media/

2.wp.media

wp.media用于前端创建一个wp媒体中心窗体。可传入参数如下:

  1. frame,代表创建的窗体类型,可选值select、post、manage、image、audio、video、edit-attachments
  2. on(),绑定事件。
  3. media.state().get('selection').toJSON()); ,被选的图片

wordpress元框

元框是WordPress后台的一个模块,它提供了一个用户友好的界面,让用户可以输入和管理与特定帖子或页面相关的额外信息。

1.元框类型

元框的类型:

  • 普通元框(Normal Meta Box):显示在编辑页面的右侧。
  • 高级元框(Advanced Meta Box):可以包含多个字段和布局选项。
  • 侧边元框(Side Meta Box):显示在编辑页面的侧边栏。

2.添加元框

add_meta_box()函数是被用来在文章编辑等页面添加一个设置的区域的函数。

创建的文章类型默认的仅有标题、作者、分类、标签、日期和评论,这些也许对博客已经足够使用了,但是对于产品类型的文章来说,不仅仅需要标题和正文,还需要单独设置一些其它的参数,如产品价格、产品型号、规格大小等,那么就需要给文章类型添加Meta Box,通俗点理解就是自定义字段表单,下面就来以实例讲解下这个函数的用法。

<?php add_meta_box(
    $id, 
    $title, 
    $callback, 
    $post_type, 
    $context, 
    $priority, 
    $callback_args
); 
?>
  • $id(字符串)(必需)字段id,唯一
  • $title(字符串)(必需)标题名称,显示在文章编辑页面
  • $callback(回调)(必需)回调函数
  • $post_type(字符串)(必需)文章类型
  • $context(字符串)(可选)显示位置,文章编辑页面包括’normal’, ‘side’, and ‘advanced’的形式,Menus meta boxes仅用’side’的形式
  • $priority(字符串)(可选)优先级,默认值: ‘default’
  • $callback_args(数组)(可选)传递到 callback 函数的参数。callback 函数将接收 $post 对象和其他由这个变量传递的任何参数。

实际例子:

add_action( 'add_meta_boxes', 'product_price' );
function product_price() {
    add_meta_box(
        'product_price',
        '产品价格',
        'product_price_meta_box',
        'store',
        'side',
        'low'
    );
}

输出表单之后,点击保存就会同时提交表单数据,wordpress不会自动处理这部分数据,需要自己判断并编写处理逻辑

参考:https://www.wuyanshuo.cn/93.htmlhttps://www.daimadog.com/2456.html/comment-page-1 

问题总结

1.save_post

wordpress自动保存也会触发这个钩子,可能导致异常输出;save_post钩子内进行wp_update_post会导致重复触发钩子

2.获取页面使用的模板

$template=get_page_template_slug( get_queried_object_id() );
if (strpos($template,"template/page/posts.php") !== false) {  }

3.获取访问的目录和标签对象

<?php

//获取访问的标签或分类对象
get_queried_object()->term_id;
//获取分类、标签的链接
get_term_link($tag->term_id); 

4.获取作者的指定信息

author.php页面可以通过这个函数获取需要的数据。

<?php
get_the_author_meta( 'display_name', $post->post_author )

5.设置代理

http_api_curl可以在请求之前对curl进行相关的处理。

add_filter( 'http_api_curl', function ( $handle, $args, $url ) {
	curl_setopt( $handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5 );
	curl_setopt( $handle, CURLOPT_PROXY, "socks5://8.217.181.168:7858" );
	curl_setopt( $handle, CURLOPT_FOLLOWLOCATION, true );
	return $handle;
}, 10, 3 );

6.对文章保存前的内容进行处理

wp_insert_post_data  在将文章数据插入数据库之前触发。可以使用这个钩子来修改保存的内容。

add_filter('wp_insert_post_data', 'my_custom_function', 10, 2);

function my_custom_function($data, $postarr) {
    // 获取保存的文章内容
    $content = $data['post_content'];
    // 在这里对内容进行自定义处理
    // 修改后的内容
    $data['post_content'] = $content;
    return $data;
}

content_save_pre 在将文章内容保存到数据库之前触发。可以使用这个钩子来对保存的内容进行进一步处理。

add_filter('content_save_pre', 'my_custom_function');

function my_custom_function($content) {
    // 在这里对内容进行自定义处理
    return $content;
}