Php 如何为某些帖子创建一个高效的内容过滤器?

Php 如何为某些帖子创建一个高效的内容过滤器?,php,ajax,wordpress,cron,Php,Ajax,Wordpress,Cron,我已经将这篇文章标记为WordPress,但我不完全确定它是WordPress特有的,所以我将它发布在StackOverflow上,而不是WPSE上。解决方案不必是特定于WordPress的,只需PHP即可 场景 我用一些热带鱼物种概况和词汇表条目运行了一个数据库 我们的网站以我们的个人资料为导向。正如你所说,他们是网站的主要部分 我希望实现的是,在每一个提到另一个物种或词汇表条目的物种简介中,我可以用一个链接替换这些单词,如您将看到的。理想情况下,我也希望这种情况出现在新闻、文章和博客文章中

我已经将这篇文章标记为WordPress,但我不完全确定它是WordPress特有的,所以我将它发布在StackOverflow上,而不是WPSE上。解决方案不必是特定于WordPress的,只需PHP即可

场景
我用一些热带鱼
物种概况
词汇表
条目运行了一个数据库

我们的网站以我们的个人资料为导向。正如你所说,他们是网站的主要部分

我希望实现的是,在每一个提到另一个物种或词汇表条目的物种简介中,我可以用一个链接替换这些单词,如您将看到的。理想情况下,我也希望这种情况出现在新闻、文章和博客文章中

我们有近1400个物种概况和1700个词汇表条目。我们的物种简介通常很长,最后仅统计我们的物种简介就有170多万字的信息

我当前正在尝试的内容
目前,我有一个
filter.php
,它有一个函数,我相信它能完成我所需要的功能。代码相当长,可以找到完整的代码

此外,在我的WordPress主题的
functions.php
中,我有以下内容:

# ==============================================================================================
# [Filter]
#
# Every hour, using WP_Cron, `my_updated_posts` is checked. If there are new Post IDs in there,
# it will run a filter on all of the post's content. The filter will search for Glossary terms
# and scientific species names. If found, it will replace those names with links including a 
# pop-up.

    include "filter.php";

# ==============================================================================================
# When saving a post (new or edited), check to make sure it isn't a revision then add its ID
# to `my_updated_posts`.

    add_action( 'save_post', 'my_set_content_filter' );
    function my_set_content_filter( $post_id ) {
        if ( !wp_is_post_revision( $post_id ) ) {

            $post_type = get_post_type( $post_id );

            if ( $post_type == "species" || ( $post_type == "post" && in_category( "articles", $post_id ) ) || ( $post_type == "post" && in_category( "blogs", $post_id ) ) ) {
                //get the previous value
                $ids = get_option( 'my_updated_posts' );

                //add new value if necessary
                if( !in_array( $post_id, $ids ) ) {
                    $ids[] = $post_id;
                    update_option( 'my_updated_posts', $ids );
                }
            }
        }
    }

# ==============================================================================================
# Add the filter to WP_Cron.

    add_action( 'my_filter_posts_content', 'my_filter_content' );
    if( !wp_next_scheduled( 'my_filter_posts_content' ) ) {
        wp_schedule_event( time(), 'hourly', 'my_filter_posts_content' );
    }

# ==============================================================================================
# Run the filter.

    function my_filter_content() {
        //check to see if posts need to be parsed
        if ( !get_option( 'my_updated_posts' ) )
            return false;

        //parse posts
        $ids = get_option( 'my_updated_posts' );

        update_option( 'error_check', $ids );

        foreach( $ids as $v ) {
            if ( get_post_status( $v ) == 'publish' )
                run_filter( $v );

            update_option( 'error_check', "filter has run at least once" );
        }

        //make sure no values have been added while loop was running
        $id_recheck = get_option( 'my_updated_posts' );
        my_close_out_filter( $ids, $id_recheck );

        //once all options, including any added during the running of what could be a long cronjob are done, remove the value and close out
        delete_option( 'my_updated_posts' );
        update_option( 'error_check', 'working m8' );
        return true;
    }

# ==============================================================================================
# A "difference" function to make sure no new posts have been added to `my_updated_posts` whilst
# the potentially time-consuming filter was running.

    function my_close_out_filter( $beginning_array, $end_array ) {
        $diff = array_diff( $beginning_array, $end_array );
        if( !empty ( $diff ) ) {
            foreach( $diff as $v ) {
                run_filter( $v );
            }
        }
        my_close_out_filter( $end_array, get_option( 'my_updated_posts' ) );
    }
正如(希望如此)代码注释所描述的那样,它的工作方式是每小时WordPress运行一个cron作业(就像一个假cron,在用户点击时工作,但这并不重要,因为时间并不重要),该作业运行上面找到的过滤器

每小时运行一次的基本原理是,如果我们试图在保存每个帖子时运行它,这将对作者不利。一旦我们让客座作者参与进来,这显然不是一种可以接受的方式

问题…
几个月来,我一直无法让这个过滤器可靠地运行。我认为问题不在于过滤器本身,而在于启用过滤器的其中一个功能,即cron作业,或选择过滤哪些帖子的功能,或为过滤器准备单词列表等的功能

不幸的是,诊断这个问题是相当困难的(我可以看到),这要感谢它在后台运行,而且只能每小时运行一次。我一直在尝试使用WordPress的update\u option函数(它基本上写一个简单的数据库值)进行错误检查,但我运气不好——老实说,我很困惑问题出在哪里

我们最终在这个过滤器无法正常工作的情况下启动了网站。有时它似乎起作用,有时不起作用。因此,我们现在有相当多的物种剖面没有被正确过滤

我想要什么…
我基本上是在寻求关于运行这个过滤器的最佳方法的建议

Cron工作就是答案吗?我可以设置一个每天运行的
.php
文件,这不是问题。它将如何确定哪些帖子需要过滤?它在运行时会对服务器产生什么影响

或者,WordPress管理页面是答案吗?如果我知道怎么做的话,在页面上使用AJAX,这样我就可以选择要运行过滤器的帖子了。有一个名为“
AJAX重新生成缩略图”的插件,它是这样工作的,也许这是最有效的

注意事项

  • 受影响/读取/写入的数据库/信息的大小
  • 过滤哪些帖子
  • 筛选器对服务器的影响;特别是考虑到我似乎无法将WordPress的内存限制提高到32Mb以上
  • 实际过滤器本身是否高效、有效和可靠

这是一个相当复杂的问题,我不可避免地遗漏了一些细节(因为我在这个过程中被同事们分散了大约18次注意力)。请随时调查我的进一步信息


提前感谢,创建配置文件时请执行此操作

试着把整个过程颠倒过来。与其检查内容中的单词,不如检查内容中的单词

  • 将输入的文章内容拆分为文字(空格)
  • 消除重复项、数据库中最小字号下的重复项、最大字号上的重复项以及保留的“常用字词”列表中的重复项
  • 检查每个表,如果您的某些表包含带空格的短语,请执行%text%搜索,否则进行直接匹配(速度快得多),如果问题真的很严重,甚至可以构建哈希表。(我会将其作为一个PHP数组来执行,并以某种方式缓存结果,没有意义重新发明轮子)
  • 用现在大大缩小的列表创建链接
  • 你应该能够轻松地将这一点保持在1秒以内,即使你要检查的字数达到100000个。我以前在没有缓存单词列表的情况下,为贝叶斯过滤器做过这样的工作

    对于较小的列表,即使它贪婪地收集与“小丑”不匹配的单词,也会捕获“小丑泥鳅”,由此产生的较小列表应该只有几个到几十个带有链接的单词。这根本不需要花时间在一块文本上进行查找和替换

    上述内容并不能真正解决您对旧配置文件的担忧。你并没有说到底有多少条,只是有很多文字,而且是1400到3100条(两项)放在一起。如果你有这些信息,你可以根据受欢迎程度来制作这些旧内容。或在输入的日期,最新的第一个。不管怎样,最好的方法是编写一个脚本,暂停PHP的时间限制,并在所有帖子上批处理运行load/process/save。如果每一个都需要大约1秒(可能要少得多,但最坏的情况)y