标签: WordPress插件开发

  • WordPress 使用 wp_count_posts() 函数快速获取文章数量

    WordPress 使用 wp_count_posts() 函数快速获取文章数量

    还记得老季之前想要获取 WordPress 站点的所有文章总数统计网上的教程,以及在某些地方的使用也都是直接使用 SQL 语句直接查询数据来做总数统计,现在相信还真的是费时费力,原因就是不知道 WordPress 还有 wp_count_posts()这样一个函数,具体是哪个版本出来就懒得去看了,反正随时都保持 WordPress 最新版。

    其实在很多的 WordPress 主题上都会有一个统计或者文章归档的页面,就需要统计一些 WordPress 站点上已经发布多少文章了,以此来展示自己的站点或者给自己一个统计,当然我们在开发某些特别的功能或者逻辑计算时也可能会用到,最近在开发一个插件的时候就多次用到了,不想再去写 SQL 来统计,费时费力并且 WordPress 本身就有的功能为什么就不好好利用呢,果断就想起了 wp_count_posts 函数。

    wp_count_posts 函数是在 WordPress 中用来统计文章数量的函数,可以统计的类型有文章(post)和页面(page)。并且能够直接统计出文章各个不同状态的数据,使用起来非常的便捷,两行代码即可搞定。

    //获取文章数量
    $postcount = wp_count_posts();
    //获取页面数量
    $pagecount = wp_count_posts('page');

    默认是获取的 post 文章类型的,当然如果是自定义类型应该也是可以支持的,这个目前没有测试,不过相信 WordPress 是绝对考虑到了兼容性的,值得注意的是,上面说过了是两行代码,所以上面的例子并不能直接输出,因为 wp_count_posts 函数返回的是一个对象数据,如下。

    // WordPress wp_count_posts 函数返回值
    stdClass Object
    (
        [publish] => 11 //已发布
        [future] => 0   //定时发布
        [draft] => 0    //草稿
        [pending] => 0  //待审
        [private] => 0  //私有
        [trash] => 0    //垃圾箱
        [auto-draft] => 34  //自动草稿
        [inherit] => 0  //修订版本
        [request-pending] => 0
        [request-confirmed] => 0
        [request-failed] => 0
        [request-completed] => 0
    )
    

    所以,获取已发布状态文章的完整统计代码如下:

    //WordPress 已发布文章数量
    $count_posts = wp_count_posts();  
    $publish_posts = $count_posts->publish;

    其它的就举一反三,相信也都能看得懂了,老季就不再过多的赘述。最后在补充一点,有时候我们可能喜欢代码的简单性,所以在写法上面就比较大胆,没有怎么考虑兼容性,一行代码就能搞定,所以在不考虑兼容性的情况下还有以下的一种写法:

    //WordPress 已发布文章数量,不兼容 PHP5.4 以前
    $publish_posts = wp_count_posts()->publish;

    比较喜欢用吧,不过使用这种写法请一定保证你的 PHP 版本在 5.4 以上即可正常运行。

  • wordpress自定义侧边栏小工具widget

    wordpress自定义侧边栏小工具widget

    wordpress提供了主题小工具支持(后台——外观——小工具),可以实现自由拖动功能模板到侧边栏,实现相关的调用显示。wordpress默认提供了若干个小工具,但大部分不能满足博主的建站需求,因此对小工具自定义扩展非常有必要。以下通过转载添加分类文章列表小工具的教程详细了解如何自定义侧边栏小工具。

    概念性的东西:wordpress提供了一个WP_Widget类,我们只需要扩展WP_Widget类,就可以制作自己的小工具(widget),此类文件位于 wp-includes\widgets.php。

    下面老季给出一个完整的调用分类文章模块的widget工具完整代码:

    <?php
    /**
    * 功能:调用某分类下的文章列表
    * 调用:在主题functions.php文件里引入本文件
    **/
    /** 
     * Add function to widgets_init that'll load our widget. 
     * @since 0.1 
     */
    add_action('widgets_init', 'load_relation_widgets');
    /** 
     * Register our widget. 
     * 'Example_Widget' is the widget class used below. 
     * 
     * @since 0.1 
     */
    function load_relation_widgets()
    {
        register_widget('jtag_post_widget');
    }
    
    class jtag_post_widget extends WP_Widget
    {
        public function jtag_post_widget()
        {
            $widget_ops  = array(
                'classname'                   => 'widget_custom_html',
                'description'                 => __( '关联标签分类文章调用.' ),
                'customize_selective_refresh' => true,
                'show_instance_in_rest'       => true,
            );
            $this->__construct('jtag_post_widget', $name = '关联标签分类文章调用', $widget_ops);
        }
        //小工具的选项设置表单
        public function form($instance)
        {
            $instance = wp_parse_args((array)$instance, array('title' => '分类文章', 'showPosts' => 10, 'cat' => 0)); //默认值
            $title = htmlspecialchars($instance['title']);
            $showPosts = htmlspecialchars($instance['showPosts']);
            $cat = htmlspecialchars($instance['cat']);
            echo '<p style="text-align:left;"><label for="' . $this->get_field_name('title') . '">标题:<input style="width:200px;" id="' . $this->get_field_id('title') . '" name="' . $this->get_field_name('title') . '" type="text" value="' . $title . '" /></label></p>';
            echo '<p style="text-align:left;"><label for="' . $this->get_field_name('showPosts') . '">文章数量:<input style="width:200px;" id="' . $this->get_field_id('showPosts') . '" name="' . $this->get_field_name('showPosts') . '" type="text" value="' . $showPosts . '" /></label></p>';
            echo '<p style="text-align:left;"><label for="' . $this->get_field_name('cat') . '">分类ID(多个分类ID,可用逗号分割):<input style="width:200px" id="' . $this->get_field_id('cat') . '" name="' . $this->get_field_name('cat') . '" type="text" value="' . $cat . '" /></label></p>';
        }
        public function update($new_instance, $old_instance)
        {
            $instance = $old_instance;
            $instance['title'] = strip_tags(stripslashes($new_instance['title']));
            $instance['showPosts'] = strip_tags(stripslashes($new_instance['showPosts']));
            $instance['cat'] = strip_tags(stripslashes($new_instance['cat']));
            return $instance;
        }
        public function the_rand_posts($args = '')
        {
            $default = array('showPosts' => 10, 'cat' => '1');
            $r = wp_parse_args($args, $default);
            extract($r);
            $args = array(
                'cat'   =>  $cat,
                'showposts' =>  $showPosts,
                'orderby'   =>  'desc',
            );
            $the_query = new WP_Query($args);
            if ($the_query->have_posts()) {
                echo '<ul>';
                while ($the_query->have_posts()) {
                    $the_query->the_post();
                    echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
                }
                echo '</ul>';
            }
            // Restore original Post Data
            wp_reset_postdata();
        }
        //小工具在前台显示效果
        public function widget($args, $instance)
        {
            extract($args);
            $title = apply_filters('widget_title', empty($instance['title']) ? __('分类文章<i>Title</i>') : $instance['title']);
            $showPosts = empty($instance['showPosts']) ? 10 : $instance['showPosts'];
            $cat = empty($instance['cat']) ? 0 : $instance['cat'];
            echo $before_widget;
            if ($title) echo $before_title . $title . $after_title;
            $this->the_rand_posts("showPosts=$showPosts&cat='$cat'");
            echo $after_widget;
        }
    }
    
  • JBatches批量上传附件添加文章插件 支持ripro-v2主题 文档在线预览

    JBatches批量上传附件添加文章插件 支持ripro-v2主题 文档在线预览

    前几日,小伙伴让我帮忙开发了一个通过批量上传附件,已添加多个文章。

    2021.11.11 更新主要功能如下:

    • 支持腾讯云COS对象存储
    • 支持PDF,DOC等格式得文件在线预览。并能控制在线预览的页数。
    • 在线预览图片路径加密
    • 支持ripro-v2主题付费阅读下载功能。添加文章时自动将文档设置为付费文档。
    • 支持ripro-v2主题的主题栏目功能
    • 支持WordPress标签库,匹配到标题后自动将标签打进文章中。

    有需要的小伙伴可以联系我们(非免费)~

  • WordPress wp_set_post_terms 函数 给文章设置分类和标签信息 使用注意事项

    WordPress wp_set_post_terms 函数 给文章设置分类和标签信息 使用注意事项

    我们在写插件的时候,可以使用 wp_set_post_terms 函数给文章设置分类标签信息,需要特别注意的时候,设置这两种不同的分类模式时候,这个函数的参数会有细微的差异。

    wp_set_post_terms 函数参数的差异

    function wp_set_post_terms( $post_id = 0, $terms = '', $taxonomy = 'post_tag', $append = false )

    首先我们看看 wp_set_post_terms 函数的参数:

    • $post_id:文章 ID。
    • $terms:分类或者标签数据。
    • $taxonomy:分类模式,默认 post_tag
    • $append:是否附加还是直接覆盖,默认覆盖,如果要添加,这个参数设置为 false。

    这个函数的重点就是地第二个参数 $terms,根据官方的注释,$terms 可以是数组或者逗号分隔的字符串。

    如果你设置的是层级关系的分类模式,比如分类(category),则使用 IDs,如果添加是没有层级关系的分类模式,比如标签(tag),则使用名字。

    标签也想用 IDs?

    那么如果是没有层级关系的分类模式(比如 tag),也要使用 IDs,怎么处理呢?那么 $terms 参数为:标签 ID 组成的数组,数组中的 ID 必须是数字类型。

    这是因为 term 也可能为数字,wp_set_post_terms 调用 term_exists 函数进行term 是否存在判断的时候,无法区别字符串类型的数字到底是 ID 还是标签名,所以这个函数就强制要求,term 必须为数字类型才做 ID 判断。

    为什么分类使用 IDs 不用数字类型

    那么为什么层级关系的分类模式,比如分类(category),可以使用字符串类型的数字呢?因为 wp_set_post_terms 使用 intval 函数在处理层级关系的分类模式时对 $terms 数组中的每个元素做了强类型转换。所以也为了防止冲突,他也直接接受 IDs 方式的参数。

    wp_set_object_terms 也可以给给文章设置分类,但是他就没有类型转换的功能。这也是要注意的一点。

  • WordPress开发wp_ajax_{$action}和wp_ajax_nopriv_{$action}的区别

    WordPress开发wp_ajax_{$action}和wp_ajax_nopriv_{$action}的区别

    用admin-ajax.php来处理Ajax请求

    Ajax请求应该被指向wp-admin/admin-ajax.php, 文件名中的”admin”可能会引起困惑, 但是不管是前台的还是后台的Ajax请求都是在admin-ajax.php处理的.
    向admin-ajax.php发送请求的时候, 有一个必须的参数是action, 因为admin-ajax.php需要根据用户是否登陆了来触发不同的hooks

    // 如果没登陆, 会触发这个hook
    do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );
     
    // 如果登陆了, 会触发这个hook
    do_action( 'wp_ajax_' . $_POST['action'] );

    发出Ajax请求的代码大概如下:

    jQuery.post(
           MyAjax.ajaxurl,
           {
                action : 'myajax-submit',
                postID : MyAjax.postID
           },
           function( response ) {
                alert( response );
           }
    );

    现在, 我们只需要在我们的主题文件中处理一下Ajax请求, 并不需要在单独的文件中来处理

    add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
    add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
     
    function myajax_submit() {
    	$postID = $_POST['postID'];
    	$response = json_encode( array( 'success' => true ) );
     
    	header( "Content-Type: application/json" );
    	echo $response;
     
    	// 这个很关键啊有木有: 别忘记 "exit"
    	exit;
    }
  • 织梦Dedecms转WordPress方法 图文教程

    织梦Dedecms转WordPress方法 图文教程

    WordPress 是一个非常不错的免费开源系统,很多做 SEO 的站长都会选择这个程序,而如今织梦 DEDECMS 开始强调商业授权使用,所有很多企业站点想要继续使用 DEDECMS 就需要付授权费用,如果想要免费,那么就只有换程序,下面给大家介绍关于织梦 CMS 数据转换到 WordPress 程序的教程和步骤。

    织梦 DedeCMS 开始商业授权收费

    也就是说,对于商用的个人和企业站点,均需要需要获得 DedeCMS 授权而且缴费 5800 元。对于尚未获得授权的商用站点,DEDECMS 官方要求在 2021 年 10 月 25 日 24 时前购买相关授权。针对逾期未获得授权的网站,将保留民事索赔的权利,届时除了需要支付商业使用授权费外,还需承担相应的合理维权费用。

    文章标题等基本数据导入

    织梦 dedecms 的文章标题、正文和栏目分别存放在三个不同的表上,但 WordPress 把文章标题和正文放在一个表上,栏目放在另外一个表上。为了简化后面的工作,第一步我首先把织梦 dedecms 的全站 RSS 文件(rss.php)保存下来,然后使用 WordPress 自带的 RSS 导入该文件。这样就可以使 WordPress 在 wp_posts 上生成文章标题,在 dede_terms 上生成文章目录,并匹配起来。通过 RSS 导入,wp_posts 上还导入了文章的摘要、日期、自定义网址等数据。但 RSS 导入不会导入全文。

    文章全文导入

    织梦数据库的文章全文储存在 dede_addonarticle 表上的 body 里,我们要把这个 body 的内容转到 Worpress 数据库里 wp_posts 表上的 post_content 里。这个转换,需要使用一个桥梁——那就是 dede_archives,即 dede_addonarticle 上 body 的内容先转到 dede_archives 上,再从 dede_archives 上再转到 wp_posts 上的 post_content 里。这两次转换的匹配点,分别是织梦里的文章 id,以及 WordPress 里已经导入了的文章标题(这与织梦里的文章标题是一样的)。具体步骤如下:

    进入 phpMyAdmin,在织梦数据库里的 dede_archives 表上,添加一个列,命名为 body,然后用 UPDATE 命令把 dede_addonarticle 上的全文(body)导入到 dede_archives 的 body 上,以 dede_addonarticle 上的 aid 和 dede_archives 上的 id 为匹配点:

    ALTER TABLE dede_archives ADD body longtext NOT NULL
    UPDATE `dede_archives`,`dede_addonarticle` SET `dede_archives`.`body`= `dede_addonarticle`.`body` WHERE `dede_archives`.`id` = `dede_addonarticle`.`aid`

    接下来把整个 dede_archives 表导入到 WordPress 的数据库上,使其与 wp_posts 同在一个数据库下。

    再次使用 UPDATE 命令把,把 dede_archives 上的 body 导入到 wp_posts 上的 post_content 上,以文章标题为匹配点 (前提是,你的文章标题都是唯一的):

    UPDATE `wp_posts`,`dede_addonarticle` SET `wp_posts`.`post_content`= `dede_archives`.`body` WHERE `wp_posts`.`post_title` = `dede_archives`.`title`

  • WordPress 通过自定义分类法获取自定义文章类型的相关文章

    WordPress 通过自定义分类法获取自定义文章类型的相关文章

    有时候我们需要为网站添加一个自定义文章类型,但是当访问此文章类型页面时,如何获取相关联的文章呢?请看以下代码:

    $terms = get_the_terms($post->ID, 'product_tags', 'string');
    $term_ids = wp_list_pluck($terms, 'term_id');
    $second_query = new WP_Query(array(
        'post_type' => 'products',
        'tax_query' => array(
            array(
                'taxonomy' => 'product_tags',
                'field' => 'id',
                'terms' => $term_ids,
                'operator' => 'IN' //Or 'AND' or 'NOT IN'
            )
        ),
        'posts_per_page' => 3,
        'ignore_sticky_posts' => 1,
        'orderby' => 'rand',
        'post__not_in' => array($post->ID)
    ));
    if ($second_query->have_posts()) {
        while ($second_query->have_posts()) : $second_query->the_post();
        //loop
        endwhile;
        wp_reset_query();
    }
  • WordPress Advanced Custom Fields(ACF)获取 自定义分类法 自定义字段

    WordPress Advanced Custom Fields(ACF)获取 自定义分类法 自定义字段

    在WordPress的模板主题插件开发中,我们使用Advanced Custom Fields(ACF)插件设置自定义分类法的自定义字段时,在模板或插件中可以使用如下代码来获取值

    get_field('bg_img', $term->taxonomy.'_'.$term->term_id);
  • WordPress 分类法 get_terms 函数 自定义字段排序

    WordPress 分类法 get_terms 函数 自定义字段排序

    我们在实际WordPress模板插件开发中,可能需要用到分类法的自定义字段的排序,这里我们使用get_terms函数,自定义字段名:ranking

    不管ranking有没有值,都能出所有的对应分类结果,下面我们记录一下代码段:

    $taxonomy_name = 'products';
    $args = array(
        'taxonomy' => $taxonomy_name,
        'orderby' => 'meta_value_num',
        'order' => 'DESC',
        'hide_empty' => false,
        'hierarchical' => false,
        'parent' => 0,
        'meta_query' => array(
            'relation' => 'OR',
            array(
                'key' => 'ranking',
                'type' => 'NUMERIC',
            ), array(
                'key'           =>  'ranking',
                'compare'      => 'NOT EXISTS',
            )
        ),
    );
    $terms = get_terms($args);

  • 关闭WordPress新用户注册邮件通知

    关闭WordPress新用户注册邮件通知

    WordPress自带有邮箱重置密码以及新用户注册邮件通知功能,但很多时候我们并不想要这些个鸡肋的功能。这里我们通过WordPress的Hook机制很轻松关闭它们。

    新用户注册邮件通知

    注册时的邮件通知,一共两封邮件:一个是向管理员发邮件通知,一个向用户发邮件通知。随着网站时间的推移,站长对注册用户也没啥太在意的。管理员邮件是没必要的存在故关闭之,如果没加验证遇到机器人垃圾注册,会被这些通知邮件撑爆邮箱,对于个人博客这个功能是安心关闭的。向用户发邮件通知这个功能其实也无所谓,如果自己有花时间专门做了欢迎邮件模板,想要好一点的体验的话,也可以保留。

    通过邮箱重置密码

    站长是个人博客忘记了密码,走邮箱找回密码很鸡肋有木有?同时存在邮箱账号被盗导致整站被黑的安全隐患,作为有权限直接操作数据的个人站长为啥要走一波邮件这种绕弯路的操作?让我们把对外开放会导致整站沦陷,却可有可无的功能直接屏蔽掉吧!

    关闭WordPress邮箱重置密码以及新用户注册邮件通知的代码实现

    //关闭新用户注册通知站长的邮件
    add_filter( 'wp_new_user_notification_email_admin', '__return_false' );
    //关闭新用户注册用户邮件通知
    add_filter( 'wp_new_user_notification_email', '__return_false' );
    //禁止用户密码重置
    apply_filters( 'allow_password_reset', '__return_false' );
    

    代码使用方法

    复制以上代码直接扔进当前WoresPress主题的 function.php 文件中即可。

  • 黄聪:WordPress动作钩子函数add_action()、do_action()源码解析

    黄聪:WordPress动作钩子函数add_action()、do_action()源码解析

    WordPress常用两种钩子,过滤钩子和动作钩子。过滤钩子相关函数及源码分析在上篇文章中完成,本篇主要分析动作钩子源码。

    然而,在了解了动作钩子的源码后你会发现,动作钩子核心代码竟然跟过滤钩子差不多!是的,至此,我不得不告诉你,动作钩子只是WP开发者为了区分概念而把过滤钩子另外命名的一种东西!当然,它们还是有一些细微的差别,下面我们将从源码来深入解读。

    动作钩子概念:动作钩子是WP代码执行到某处或某个事件发生时触发的一系列函数,插件可以利用动作钩子API在WP代码执行的特定点之前插入一系列函数以控制执行。它跟过滤钩子极像,唯一不同的是过滤钩子返回一个处理后的值,而动作钩子仅完成函数执行并不返回值,如果钩子不存在则返回NULL并新增该钩子。

    动作钩子原理:由于动作钩子和过滤钩子几乎一样,所以它们的实现原理也是一样的。它主要利用一个全局变量$wp_filter,增加动作函数时使用add_action()函数给全局变量$wp_filter增加了一个数组元素,这个元素键名中含有钩子名,值中含有对应函数及执行优先级等信息,在调用do_action()函数使用动作钩子时,它通过循环查找出所有跟钩子关联的函数并将其依次调用,最后返回处理后的数据。

    实例

    # ======= Somewhere in a (mu-)plugin, theme or the core ======= #
     
    /**
     * You can have as many arguments as you want,
     * but your callback function and the add_action call need to agree in number of arguments.
     * Note: `add_action` above has 2 and 'i_am_hook' accepts 2. 
     * You will find action hooks like these in a lot of themes & plugins and in many place @core
     * @see: https://codex.wordpress.org/Plugin_API/Action_Reference
     */
     
    # ======= e.g., inside your functions.php file ======= #
     
    /**
     * Define callback function
     * Inside this function you can do whatever you can imagine
     * with the variables that are loaded in the do_action() call above.
     */
    function wpdocs_who_is_hook( $a, $b ) {
        echo '<code>';
            print_r( $a ); // `print_r` the array data inside the 1st argument
        echo '</code>';
     
        echo '<br />'.$b; // echo linebreak and value of 2nd argument
    }
     
    // then add it to the action hook, matching the defined number (2) of arguments in do_action
    // see [https://codex.wordpress.org/Function_Reference/add_action] in the Codex 
     
    // add_action( $tag, $function_to_add, $priority, $accepted_args );
    add_action( 'wpdocs_i_am_hook', 'wpdocs_who_is_hook', 10, 2 );
     
    // Define the arguments for the action hook
    $a = array(
        'eye patch'  => 'yes',
        'parrot'     => true,
        'wooden leg' => 1
    );
    $b = __( 'And Hook said: "I ate ice cream with Peter Pan."', 'textdomain' ); 
     
    // Executes the action hook named 'i_am_hook'
    do_action( 'wpdocs_i_am_hook', $a, $b );

    运行结果

    Array (     
    ['eye patch'] => 'yes'    
    ['parrot'] => true    
    ['wooden leg'] => 1
    )
    And hook said: "I ate ice cream with Peter Pan."

    动作钩子使用步骤:

    由于PHP代码会经过Zend等引擎翻译,代码中步骤的先后顺序并不重要,所以以下步骤仅为便于理解钩子原理的伪步骤,不具有实际参考意义!

    1、创建钩子(可省略):使用do_action()函数可以创建一个没有挂载函数的钩子,挂载函数可以通过add_action()添加,最后再使用do_action()调用执行;

    2、创建动作函数:它可以有传入参数也可以无传入参数,其他与创建普通函数没有任何区别,函数的作用为完成某项动作;

    3、挂载函数:即使用add_action()将函数挂载到指定钩子上;

    4、执行动作钩子:使用do_action()可以依次执行挂载在指定钩子上的所有函数以完成指定任务;

    动作钩子函数详解:

    在看动作钩子函数作用、参数说明等时,你会发现几乎是跟过滤钩子重复的。至于为什么会这样,那就要看源码了,我保证,看完源码后你会感慨自己被WP开发者涮了!

    add_action($tag,$function_to_add,$priority = 10,$accepted_args = 1)

    add_action()作用:该函数用于给指定的动作钩子$tag添加指定的挂载函数$function_to_add,同时它可以确定挂载函数执行优先级及其可接收参数个数;

    add_action()参数说明:

    $tag为钩子名;

    $function_to_add为挂载函数名;

    可选参数$priority为该挂载函数执行的优先级,默认为10,该数字越小则越早执行,数字相同则按其添加到钩子上的顺序执行,越早添加越早执行;

    可选参数$accepted_args确定挂载函数接收的参数个数,默认为1;

    add_action()源码分析:

    function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
        return add_filter($tag, $function_to_add, $priority, $accepted_args);
    }

    怎么样,看到了吧!被坑了有木有!add_action()函数的代码竟然是调用一次add_filter()!这尼玛完全是一个人的大名和小名的问题有木有!

    2、do_action($tag, $arg = ”)

    do_action()作用:该函数调用挂载在过滤钩子$tag上的所有函数以完全特定的任务;

    do_action()参数说明:

    $tag为钩子名;

    $arg为动作钩子上挂载函数的传入参数,默认为空;

    do_action()源码分析:

    function do_action($tag, $arg = '') {
        global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
        if ( ! isset($wp_actions) )
            $wp_actions = array();
    # 如果$wp_actions变量未设置过,则将其定义为数组;
        if ( ! isset($wp_actions[$tag]) )
            $wp_actions[$tag] = 1;
        else
            ++$wp_actions[$tag];
        # 如果$wp_actions[$tag]未设置则将其赋值为1,否则将其值加1;
        if ( isset($wp_filter['all']) ) {
            $wp_current_filter[] = $tag;
            $all_args = func_get_args();
            _wp_call_all_hook($all_args);
        }
        # 跟apply_filters()中的all钩子处理方式完全一样!_wp_call_all_hook()源码分析见上篇文章过滤钩子源码解析;
        if ( !isset($wp_filter[$tag]) ) {
            if ( isset($wp_filter['all']) )
                array_pop($wp_current_filter);
            return;
        }
        # 当前钩子不存在,则直接返回,不再执行以后代码;
        if ( !isset($wp_filter['all']) )
            $wp_current_filter[] = $tag;
        # 将当前钩子设置为$tag;
        $args = array();
        if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) )
            $args[] =& $arg[0];
        else
            $args[] = $arg;
        # do_action()若有传入参数,且为一个数组,该数组仅此一个元素,该元素有值则将$args值设置为引用$arg[0],否则直接赋值;
        for ( $a = 2; $a < func_num_args(); $a++ )
            $args[] = func_get_arg($a);
        # 通过for循环,若do_action()有不只一个传入参数,将这些值赋给数组$args;
        if ( !isset( $merged_filters[ $tag ] ) ) {
            ksort($wp_filter[$tag]);
            $merged_filters[ $tag ] = true;
        }
        # 跟apply_filter()函数排序代码完全一样!详解见上文;
        reset( $wp_filter[ $tag ] );
        do {
            foreach ( (array) current($wp_filter[$tag]) as $the_ )
                if ( !is_null($the_['function']) )
                    call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
        } while ( next($wp_filter[$tag]) !== false );
        array_pop($wp_current_filter);
    }
        # 除了少了一行return $value其他跟apply_filters()完全一样!

    php中call_user_func 与 call_user_func_array的使用

  • WordPress插件 Advanced Custom Fields Pro 的PHP配置文件转化为JSON文件

    WordPress插件 Advanced Custom Fields Pro 的PHP配置文件转化为JSON文件

    Advanced Custom Fields 是一款非常强大的自定义字段插件,允许你自己添加多种形式的自定义字段类型,比如 Image、Checkbox、File、Text、Select、True / False、Link、Textarea 等等,可以集成为一个或多个面板,支持导出字段为 xml 或 php 代码,还可以集成到主题或插件里。你可以使用这个 wordpress 插件为页面、文章、分类、用户建立自定义字段。可以用这个插件创建一个网站设置的页面字段,可以用来自由编辑网站的标题、LOGO、banner,版权文字等等只要你想得到的都可以。

    我们使用别人写好的主题修改自定义字段时,就需要将php文件转化为json然后读取到数据库中进行修改。

    我们将 Advanced Custom Fields Pro 的配置 从 PHP 转化为 JSON 格式,具体步骤如下

    新建一个插件

    在 /wp-content/plugins 文件夹中新建一个文件名为:acf-php-to-json.php

    <?php
    /**
     * Plugin Name: Convert ACF PHP to JSON
     * Description: Convert Advanced Custom Fields Pro configuration from PHP to JSON.
     */
    namespace ConvertAcfPhpToJson;
    /**
     * Add submenu item under 'Custom Fields'
     */
    function admin_menu() {
        add_submenu_page('edit.php?post_type=acf-field-group', 'Convert PHP fields to JSON', 'PHP to JSON', 'manage_options', 'acf-php-to-json', __NAMESPACE__ . '\\admin_page');
    }
    add_action('admin_menu', __NAMESPACE__ . '\\admin_menu', 20);
    /**
     * Output the admin page
     */
    function admin_page() {
        ?>
        <div class="wrap">
            <h1>Convert PHP fields to JSON</h1>
            <?php
            if (!isset($_GET['continue']) || $_GET['continue'] !== 'true') {
                admin_page_intro();
            }
            else {
                admin_page_convert();
            }
            ?>
        </div>
        <?php
    }
    /**
     * Output the introductory page
     */
    function admin_page_intro() {
        $groups = get_groups_to_convert();
        if (empty($groups)) {
            echo '<p>No PHP field group configuration found. Nothing to convert.</p>';
            return;
        }
        else {
            echo sprintf('<p>%d field groups will be converted from PHP to JSON configuration.</p>', count($groups));
            echo '<a href="edit.php?post_type=acf-field-group&page=acf-php-to-json&continue=true" class="button button-primary">Convert Field Groups</a>';
        }
    }
    /**
     * Convert the field groups and output the conversion page
     */
    function admin_page_convert() {
        $groups = get_groups_to_convert();
        echo sprintf('<p>Converting %d field groups from PHP to JSON configuration...</p>', count($groups));
        echo '<ol>';
        foreach ($groups as $group) {
            if (convert_group($group)) {
                echo sprintf('<li>Converted: <strong>%s</strong> (%s)</li>', $group['title'], $group['key']);
            }
            else {
                echo sprintf('<li><strong>Failed to convert: %s</strong> (%s)</li>', $group['title'], $group['key']);
            }
        }
        echo '</ol>';
        echo '<p>Done. Now remove the PHP field group configuration.</p>';
    }
    /**
     * Get the PHP field groups which will be converted.
     *
     * @return array
     */
    function get_groups_to_convert() {
        $groups = acf_get_local_field_groups();
        if (!$groups) return [];
        return array_filter($groups, function($group) {
            return $group['local'] == 'php';
        });
    }
    /**
     * Convert a field group to JSON
     *
     * @param array $group
     * @return bool
     */
    function convert_group($group) {
        $group['fields'] = acf_get_local_fields($group['key']);
        return acf_write_json_field_group($group);
    }

    启用插件

    再插件列表中启用插件 Convert ACF PHP to JSON

WeChat
↑