首页 > 解决方案 > 编辑此代码段以仅运行一次

问题描述

我们有数千个自定义帖子,我们需要使用这个 PHP 片段更新 the_excerpt(保存单个帖子时效果很好)。有没有办法调整这段代码,以便我们可以运行一次(比如加载页面时)然后删除它?我们正在尝试根据此代码更新每个帖子的摘录,而无需手动编辑每个帖子。

// This saves the Short Description ACF field as the post excerpt.

add_action('acf/save_post', function($post_id) {
    
    $post_type = get_post_type( $post->ID );
    if ($post_type == "ultratech_product") {

  $post_excerpt   = get_field( 'short_description', $post_id );
        
        if ( '' != $post_excerpt ) {
        $post_excerpt = strip_shortcodes( $post_excerpt );
        $post_excerpt = apply_filters('the_content', $post_excerpt);
        $post_excerpt = str_replace(']]>', ']]>', $post_excerpt);
        $excerpt_length = 250; // 250 words
        $excerpt_more = apply_filters('excerpt_more', " " . '[...]');
        $post_excerpt = wp_trim_words( $post_excerpt, $excerpt_length, $excerpt_more );
    }

    // Update post options array
    $update_post_excerpt_args = array(
      'ID'          => $post_id,
      'post_excerpt'    => $post_excerpt,
    );

    wp_update_post( $update_post_excerpt_args );

    }
    }, 40);

标签: phpwordpressadvanced-custom-fields

解决方案


首先,请务必通读此处的所有内容。如果您对任何事情都不满意,我建议您联系开发人员,让他们代表您进行检查和运行。确保数以千计的帖子正确更新应该是很小的代价。

其次,进行完整备份并确保可以恢复它。

第三,将该备份保存在某个地方以备将来访问,以防此逻辑中存在您暂时找不到的缺陷。

有几种方法可以做到这一点。就我个人而言,我会构建一个 CLI 版本,因为我喜欢进度条和详细的状态消息,但这只是我自己。您还可以制作一个插件,使用查询字符串来触发特殊的 PHP 代码,使用魔法页面或页面模板,对于此代码,我将使用最后一个选项,页面模板。

将以下内容放入主题根目录中的新 PHP 文件中。从技术上讲,文件名并不重要,但按照惯例,我在模板前加上tpl,所以我建议调用这个新文件tpl-update.php。将以下代码粘贴到该文件中,但请确保在代码块之后继续阅读。

<?php

/**
 * Template Name: Excerpt Updater
 */

die('Remove me when ready');

// Turn on full error reporting
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

// Disable PHP timeouts
set_time_limit(0);

// Grab all products
$allProducts = get_posts(
    [
        'post_type' => 'ultratech_product',
        'posts_per_page' => -1,
    ]
);

foreach ($allProducts as $product) {
    echo 'Processing post ' . $product->ID . ';' . PHP_EOL;
    // We're guaranteed to only have our products, so we don't need to check the type anymore

    // Get the ACF field
    $post_excerpt = get_field('short_description', $product->ID);

    // If it has anything in it, apply the logic (which was untested)
    if ($post_excerpt) {
        $post_excerpt = strip_shortcodes($post_excerpt);
        $post_excerpt = apply_filters('the_content', $post_excerpt);
        $post_excerpt = str_replace(']]>', ']]>', $post_excerpt);
        $excerpt_length = 250; // 250 words
        $excerpt_more = apply_filters('excerpt_more', " " . '[...]');
        $post_excerpt = wp_trim_words($post_excerpt, $excerpt_length, $excerpt_more);

        // Only update the post if we made a change above

        // Update post options array
        $update_post_excerpt_args = array(
            'ID' => $product->ID,
            'post_excerpt' => $post_excerpt,
        );

        wp_update_post($update_post_excerpt_args);
    }
}

echo 'Done';

在 WordPress 中,创建一个新页面并为其分配摘录更新程序模板: WordPress 页面属性区域的屏幕截图.

上面的代码明确地die语句作为第一行逻辑,以便您可以测试 WordPress 是否正在使用该模板。需要明确的是,您可以发布和查看页面,您将看到的只是Remove me when ready没有任何工作将完成

看到该消息后,您可以在模板代码中注释掉该行,它将处理所有内容。这可能需要一段时间,所以我尝试禁用任何 PHP 超时,但是服务器或其他东西可能会取消脚本。

但是在运行实时代码之前,我还建议您将 的值更改posts_per_page为一个较小的数字,5这样您就可以确保一切正常。该代码将echo输出产品的 ID,以便您可以在后端检查它。

一旦您确认它按预期工作,您可以再次更改posts_per_page-1这意味着“所有帖子”(给定帖子类型)。

最后一件事,我并没有真正审查更新摘录本身的逻辑,我假设你已经这样做了,但乍一看似乎它是正确的。

好的,还有最后一件事。通常当我做这样的事情时,我会创建一个新的 ACF 字段,称为“摘录版本”,默认情况下为空。然后,我运行我的循环并说“如果摘录版本不是v2,请更新摘录并将版本设置为v2”。通过这样做,我可以保证逻辑只运行一次。您不必这样做,但如果您想批量运行代码(例如一次 10 次)来测试,这会很有帮助。如果您认为有一天您可能不得不再次更改摘录,这也会有所帮助。


推荐阅读