wordpress插件开发基础

#wordpress插件开发
##了解插件
[推荐学习网站](https://www.wpzhiku.com/document/wordpress-plugin-basics/)
###概念：  
WordPress插件可以是一个程序，也可以是PHP语言编写的一个或一组函数。它可以通过插件API提供的一系列方法和接口，来向WordPress博客中增加一些特定的功能或服务，并且让它们看上去就像是WordPress原有的功能一样。
###认为插件优势的几点：
  1. 一个插件可以在所有的主题上使用。
  2. 对于全网站的修改很方便。例如每个页面对于相同位置的修改或者增加一个通用功能时，相对于修改整个网站，增加一个插件很快。  
[官方文档](https://codex.wordpress.org/zh-cn:%E5%BC%80%E5%8F%91%E4%B8%80%E4%B8%AA%E6%8F%92%E4%BB%B6)。

###加载顺序
先加载激活的插件，然后加载主题下的functions.php，简单的功能也可以写在functions.php中
##创建插件
###名字
 不能与其他插件同名
###文件
插件文件夹的名称最好和插件PHP主文件的名称相同，文件夹放到wp-content/plugins/目录下
###标准插件信息头  
    <?php
    /*
    Plugin Name: 插件名称
    Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates 插件主页地址
    Description: 插件的简单描述
    Version: 插件版本号, 例如: 1.0
    Author: 插件作者
    Author URI: http://URI_Of_The_Plugin_Author作者地址
    */
    ?>
###插件的函数
   [官方文档](https://codex.wordpress.org/zh-cn:%E6%8F%92%E4%BB%B6_API)           
     
    function my_plugin_activate() {
     do_action( 'my_plugin_activate' );
    }
    function myplugin_deactivate() {
     do_action( 'myplugin_deactivate' );
    }
    //注册插件启动时调用的方法
    register_activation_hook( __FILE__, 'my_plugin_activate' ); 
    //注册插件停用时调用的方法   
    register_deactivation_hook( __FILE__, 'myplugin_deactivate' );    
###插件卸载执行的函数
建立uninstall.php文件，卸载时会执行其中的代码。
##常用钩子函数
###动作（action）
  1.向hook_name钩子挂载一个新的方法callback， priority函数的优先级，数值越小越被早执行，accepted_args钩子函数接收的参数的个数，会传递给callback函数，所以callback也要接收同等数量的参数。每个钩子函数可以接收的参数个数查询[官方文档](https://codex.wordpress.org/zh-cn:Plugin_API/Action_Reference)
  
     add_action( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 )
  2.执行hook_name钩子动作，一切挂载在hook_name钩子上的方法全部执行。arg，传入的参数
    
    do_action( string $hook_name, mixed $arg )
###过滤器
过滤器是 WordPress 用于修改即将要保存或者发送出去的数据的一种钩子。与动作的区别，有返回值。所有过滤器钩子[官方文档](https://codex.wordpress.org/Plugin_API/Filter_Reference)
1，执行过滤器hook_name及一切挂载在过滤器上的方法。value需要过滤的数据，var传递的变量

    apply_filters( string $hook_name, mixed $value， $var. . . )
2.添加过滤器hook_name过滤器名，callback要挂载的方法，priority优先级，accepted_args过滤器接收参数的数量

    add_filter( string $hook_name, callable $callback, int $priority = 10, int $accepted_args = 1 )
##小工具
 Widgets 在 Appearance -> Widgets 下面，并可以在你的模板中任何注册过的 sidebar 中添加。这个 API 允许在 sidebar 里面添加一个 widget 的多个实例。[官方文档](https://codex.wordpress.org/zh-cn:%E5%B0%8F%E5%B7%A5%E5%85%B7%E6%8E%A5%E5%8F%A3)
###基本用法

    class My_Widget extends WP_Widget {

	/**
	 * 设置小部件的名称等
	 */
	public function __construct() {
		$widget_ops = array( 
			'classname' => 'my_widget', 
			'description' => 'My Widget is awesome', //描述
		);
		parent::__construct( 'my_widget', '部件名称', $widget_ops );
	}

	/**
	 * 在前台输出小部件的内容
	 *
	 * @param array $args
	 * @param array $instance
	 */
	public function widget( $args, $instance ) {
		// outputs the content of the widget
	}

	/**
	 * 在管理员页面上输出选项表单
	 *
	 * @param array $instance The widget options
	 */
	public function form( $instance ) {
		// outputs the options form on admin
	}

	/**
	 * 保存时处理小部件选项
	 *
	 * @param array $new_instance The new options
	 * @param array $old_instance The previous options
	 *
	 * @return array
	 */
	public function update( $new_instance, $old_instance ) {
		// processes widget options to be saved
	}
    }
然后可以使用 widgets_init 钩子注册小部件：  

    add_action( 'widgets_init', function(){
	  register_widget( 'My_Widget' );
    });
##保存插件设置
1.创建菜单，需要挂载到admin_menu钩子中，page_title页面title，menu_title用于菜单的名称，capability要浏览菜单所需要的最低权限，menu_slug设置菜单的别名，必须唯一。function显示菜单对应的页面的内容的函数icon_url菜单的icon url，position吹安在菜单列表中的次序

     add_menu_page( string $page_title, string $menu_title, string $capability, string $menu_slug, callable $function = '', string $icon_url = '', int $position = null )
2.注册要存储的字段，需要挂载到admin_init钩子中,option_group分组名称，区分各个设置具体属于哪个分组，option_name存储字段名称，args（可选）用于描述注册时设置的数据。

    register_setting( string $option_group, string $option_name, array $args = array() )
3.添加选项设置的区域，需要挂载到admin_init钩子中
用于显示选项的区域，最终各个选项将显示在指定的区域中
      
    //id区域名称，title该区域的标题，callback回调函数显示自定义的信息，page分组名称
    add_settings_section( string $id, string $title, callable $callback, string $page )
4.菜单对应的页面的表单需要修改。
  
    （1）action=“options.php”
    （2）settings_fields(string $option_group) //输出一些必要字段包括验证信息     
    （3）do_settings_sections(string $option_group) //输出选项设置区域
    （4）submit_button（）  //输出提交按钮
5.添加字段，需要挂载到admin_init钩子中
在选项设置区域中输出字段的控件

    //id字段的id，title字段的标题，callback输出字段的控件的函数，page分组名称，section属于哪一个选项设置区域，args（可选）输出字段时使用的额外参数。
    add_settings_field( string $id, string $title, callable $callback, string $page, string $section = 'default', array $args = array() )
##短代码
为你的插件提供短代码支持。短代码是一个可以让你通过类似这样[shortcode]的方法调用一个 PHP 函数的钩子。
###添加短代码 

    //tag短代码名，callback运行的回调函数
    add_shortcode( string $tag, callable $callback )
###在模版中使用短代码

    //content短代码的名字，ignore_html如果不想执行HTML元素中的短代码，请指定 true，
    do_shortcode( string $content, bool $ignore_html = false 
##引用css和js
###引用脚本文件
  
    <?php
        //引用脚本文件
        function tone_front_script() {  
            //$handle调用的脚本名称，用于区别其它js，因此不能和其它js文件命名相同。
           //$src–js文件的路径（即url），不要直接使用域名url,要使用路径函数
           //$deps –非必需。 依赖关系，加载的js文件所依存的其它js的标识字串数组（array:string），即需要在本代码之前加载的代码的名称
           //$ver – 加载js文件的版本号，作为查询字串附加在路径的末尾，作用是确保正确的版本信息传递给了客户端，以免受到缓存的影响，默认为false
           // $in_footer – boolean类型，设置js文件调用代码是否放置在html底部，设置为ture则放在底部，设置为false则放置在head部分 
           wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
        }
       add_action( 'wp_enqueue_scripts', 'tone_front_script' );
    ?>
###引用css文件  
    ​ <?php
    ​   //引用css文件
       function admin_jscss() {  
      //$handle – 调用的样式文件名称，唯一性，因此不能和其它css文件命名相同。  
      //$src – css文件的路径（即url），不要直接使用域名url，要使用路径函数
      //$deps – 非必需。依赖关系，如果依赖其他css文件，你可以使用该参数设置“依赖关系”。
      //$ver – 加载的css文件的版本号，设置为null则不使用版本号。默认为false
      //$media – 是指CSS的媒体类型，比如“screen”或“handheld”或“print”。如果不知道是否需要，就留空。默认为“all
      wp_enqueue_style( $handle, $src, $deps, $ver, $media);
     ​}
    add_action('wp_enqueue_scripts', 'admin_jscss');
     ?>
###调用ajax的方法
1.引入需要发送ajax请求的js文件

    add_action( 'wp_enqueue_scripts', 'my_enqueue' );
    function my_enqueue( $hook ) {
    wp_enqueue_script( 'ajax-script',
      plugins_url( 'js/myjquery.js', __FILE__ ),
      array( 'jquery' )
    );
    }
2.本地化
由PHP创建全局JavaScript对象的过程，称之为本地化。注意：所有的Ajax请求都要发送到wp-admin/admin-ajax.php中

    // array-jquery使用的数据，my_ajax_obj-jQuery的全局对象
    wp_localize_script( 'ajax-script', 'my_ajax_obj', array(
      'ajax_url' => admin_url( 'admin-ajax.php' )
     ) );
3.编写有ajax请求的js文件

    jQuery(document).ready(function($) {      
    $(.pref).change(function() {         
        $.ajax({
              type:"POST",
              //action参数的值加上前缀wp_ajax_是一个钩子函数，需要在插件文件中挂载ajax的处理方法
              data:"color="+$(this).val()+"&action=myfunction"  
              //第二步本地化定义的对象
              url:my_ajax_obj.ajax_url 
              下略
           });
        });
       });
4.编写ajax的处理方法

     //钩子函数是第三步的action参数的值加上前缀wp_ajax_
     add_action("wp_ajax_myfunction",'my_ajax_handler')
     function my_ajax_handler() {
        // Handle the ajax request
      }
###未登录的用户使用Ajax 
   如果我们的 Ajax 交互可以允许未登录的用户使用，将第4步的钩子函数名改为wp_ajax_nopriv_myfunction
##推荐debug插件
##Query Monitor
类似浏览器的开发者工具，能看到HTTP API調用。对于wordpress有一些特殊的功能，比如能看到数据库的查询信息、PHP的错误信息、页面上使用的钩子函数，使用钩子函数插入的js和css等。