如何为某些帖子创建有效的内容过滤器?

dun*_*unc 12 php ajax wordpress cron

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

情景
我运营的鱼网站上有许多热带鱼Species ProfilesGlossary参赛作品.

我们的网站围绕我们的个人资料.正如你所说,它们是网站的面包和黄油.

我希望实现的是,在提及另一个物种或词汇表条目的每个物种档案中,我都可以用链接替换这些词 - 比如你在这里看到的.理想情况下,我也希望这也出现在新闻,文章和博客文章中.

我们拥有近1400 species profiles1700 glossary entries.我们的物种概况通常很长,最后只统计我们的物种概况numbered more than 1.7 million words.

我目前正在尝试的
目前,我有一个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' ) );
    }
Run Code Online (Sandbox Code Playgroud)

这工作,因为(希望)通过代码的注释中描述,该方式是每个小时的WordPress运行的cron作业(这就像一个假的cron - 工作在用户点击,但没有真正的问题是时机不重要的)运行上面找到的过滤器.

每小时运行它的理由是,如果我们试图在每个帖子被保存时运行它,那将对作者造成损害.一旦我们让客座作者参与进来,这显然不是一种可行的方式.

问题......
几个月来,我一直遇到问题,让这个过滤器可靠运行.我不认为问题在于过滤器本身,而是用的功能之一,使过滤器-即cron作业,或者被过滤的职位,选择的功能,或准备生词等的功能过滤器.

不幸的是,诊断问题非常困难(我可以看到),这要归功于它在后台运行并且每小时运行一次.我一直在尝试使用WordPress的update_option功能(这基本上是写一个简单的数据库值),错误检查,但我没有多少运气-而且说实话,我为问题所在很困惑.

我们最终在没有此过滤器正常工作的情况下使网站正常运行 有时似乎有效,有时则不然.因此,我们现在有相当多的物种特征未被正确过滤.

我想要的......
我基本上都在寻求有关运行此过滤器的最佳方法的建议.

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

或者,WordPress管理页面是答案吗?如果我知道怎么做,那么沿着页面的某些方面 - 利用AJAX - 允许我选择帖子来运行过滤器将是完美的.有一个叫做AJAX Regenerate Thumbnails这样的插件,也许这会是最有效的吗?

注意事项

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

这是一个非常复杂的问题,我不可避免地(因为我在这个过程中被同事分散了大约18次)遗漏了一些细节.请随时向我探讨更多信息.

提前致谢,

Dam*_*S8N 5

在创建配置文件时执行此操作.

尝试颠倒整个过程.不是检查单词的内容,而是检查内容单词的单词.

  1. 在进入单词(空格)时打破内容帖子
  2. 消除重复数据,数据库中单词最小尺寸的副本,最大尺寸的副本以及您保留的"常用单词"列表中的副本.
  3. 检查每个表,如果您的某些表包含带空格的短语,请执行%text%搜索,否则执行直接匹配(更快)或甚至构建哈希表,如果它确实是一个大问题.(我会把它做成一个PHP数组并以某种方式缓存结果,没有意义重新发明轮子)
  4. 使用现在极小的列表创建链接.

你应该能够轻松地将其保持在1秒以内,即使你正在检查甚至100,000个单词.对于以前的贝叶斯过滤器,我已经完成了这个,而没有缓存单词列表.

随着较小的列表,即使它是贪婪的并且收集与"小丑"不匹配的单词将捕获"小丑泥鳅",所得到的较小的列表应该只有几个到几十个单词的链接.这将花费时间来查找和替换一大块文本.

上述内容并未真正解决您对旧配置文件的担忧.你没有确切地说有多少,只是有很多文字,并且它是在1400到3100(两个项目)放在一起.如果你有信息,你可以根据受欢迎程度做这个旧内容.或者在输入的日期,最新的第一个.无论如何最好的方法是编写一个暂停PHP时间限制的脚本,只需在所有帖子上批量运行加载/进程/保存.如果每个人花费大约1秒钟(可能少得多但最坏的情况),你说的是3100秒,这不到一个小时.