【问题标题】:String "returned" from function is broken, but "echo" works从函数“返回”的字符串被破坏,但“回声”有效
【发布时间】:2019-02-02 19:15:29
【问题描述】:

我正在开发我的第一个 Wordpress 插件,这很有趣。

我使用 echo 显示 HTML,但它显示在页面顶部。做了一些挖掘,我发现我应该在函数中使用“return”。切换到“返回”会导致其他问题。看起来我试图输出的字符串 () 被“return”破坏了。我可以使用 echo 输出字符串并且它可以工作(只是在错误的地方)。

有什么想法吗?

function v3grid_func($atts) {

// Get the parameters from the shortcode
$atts = shortcode_atts(

    array(
        'count' => 3,
        'link_to_all' => 'yes',
        'css_class' => 'v3grid',
        'categories' => '1'
    ), $atts

);

// Get list of recent posts
$args = array(
    'numberposts' => $atts['count'],
    'offset' => 0,
    'category' => 0,
    'orderby' => 'post_date',
    'order' => 'DESC',
    'include' => '',
    'exclude' => '',
    'meta_key' => '',
    'meta_value' =>'',
    //'post_type' => array('post', 'podcast', 'recipe', 'roundup'),
    'post_type' => array('roundup'),
    'post_status' => 'publish',
    'suppress_filters' => true
);

$recent_posts = wp_get_recent_posts( $args, ARRAY_A );

// Figure out width requirement for each grid item
$width = 100/$atts[count];

$output = '';

// Container for row start
$output .=  'Start -> <div style="margin:0 -10px 0 -10px; box-sizing: border-box; position:relative; display:block;">';

// Loop through posts
foreach( $recent_posts as $recent ){

        // Get the URL of the feature image for the post
        $thumbnail = htmlentities(get_the_post_thumbnail_url( $recent["ID"], 'full' ));

        $url = htmlentities(get_permalink($recent["ID"]));
        $title = htmlentities($recent["post_title"]);

        $output .=  '   1 - <div style="width:'.$width.'%; float:left; padding:10px; display:block;">';
        $output .=  '       2 - <div><img src="'.$thumbnail.'" style="display:block; width:100%;"></div>'; // <-- Problem likely here           
        $output .=  '       3 - <div><a href="'.$url.'">'.$title.'</a></div>';
        $output .=  '   4 - </div>';

    }

// Container for row end
$output .=  'End -> </div>';

echo $output; // Shows everything as expected
return $output; // Does not show everything as expected (need to use return)

wp_reset_query();

}

add_shortcode('v3grid', 'v3grid_func');

这里是 echo 和 return 的输出。我添加了开始、结束和数字,以便跟踪输出。认为这是我的foreach的问题。

在函数中使用“echo”的输出 - 输出很好。

Start -> <div style="margin:0 -10px 0 -10px; box-sizing: border-box; position:relative; display:block;">    

1 - <div style="width:25%; float:left; padding:10px; display:block;">       
2 - <div><img src="/wp-content/uploads/THUMBNAIL-150x150.jpg" style="display:block; width:100%;"></div>     
3 - <div><a href="/roundup/post1/">Post Title A</a></div>   
4 - </div>  

1 - <div style="width:25%; float:left; padding:10px; display:block;">       
2 - <div><img src="/wp-content/uploads/THUMBNAIL-1-150x150.jpg" style="display:block; width:100%;"></div>       
3 - <div><a href="/roundup/post2/">Post Title B</a></div>   
4 - </div>  

1 - <div style="width:25%; float:left; padding:10px; display:block;">       
2 - <div><img src="/wp-content/uploads/Thumbnail-Image-150x150.gif" style="display:block; width:100%;"></div>       
3 - <div><a href="/roundup/post3/">Post Title C</a></div>   
4 - </div>  

1 - <div style="width:25%; float:left; padding:10px; display:block;">       
2 - <div><img src="/wp-content/uploads/SnacksTHUMBNAIL-150x150.jpg" style="display:block; width:100%;"></div>       
3 - <div><a href="/roundup/post4/">Post Title D</a></div>   
4 - </div>

End -> </div>

如果在函数中使用“return”,则输出 - 输出错误/损坏

开始 ->

1 - <div style="width:25%; float:left; padding:10px; display:block;">       
2 - <div><img src="/wp-content/uploads/THUMBNAIL-150x150.jpg" style="display:block; width:100%;"></div>     
3 - <div></div>     
3 - <div></div>     
3 - <div><a href="/roundup/post3/">Post Title C</div>   
4 - </div>  

1 - <div style="width:25%; float:left; padding:10px; display:block;">       
2 - <div><img src="/wp-content/uploads/SnacksTHUMBNAIL-150x150.jpg" style="display:block; width:100%;"></div>       
3 - <div><a href="/roundup/post4/">Post Title D</div>   
4 - </div>

End -> </div>

【问题讨论】:

  • 方法wp_reset_query();有必要吗?因为 return 会阻止/停止执行,而 echo 不会。
  • 嗨@GabrielHeming 感谢您的回复。我看起来不需要 wp_query_reset -- 使用 WP_Query 或 get_posts 后不需要调用 wp_reset_query,因为它们不会修改主查询对象。而是使用 wp_reset_postdata - 我将其替换为 wp_reset_postdata,但它并没有“解决”问题。
  • get_the_post_thumbnail() 可能是罪魁祸首,因为如果无法获得正确的缩略图 ID,它可能会返回 false。在连接之前,您应该先检查它是否返回了一个字符串。

标签: php wordpress


【解决方案1】:

有几个问题。让我们谈谈它们。

  1. 您需要为宽度方程的键 count 加上引号,即 $atts['count'];
  2. 您想在 WordPress 中使用转义消毒剂,而不仅仅是 htmlentities
  3. 您需要在返回之前重置查询。最佳做法是将其放在 foreach 之后。
  4. 短代码必须返回而不是回显。它们使用do_shortcode() 或在处理内容时进行处理。

修改后的代码

这是实现上述内容的修改后的代码。我在我的沙盒站点中测试了这段代码,它没有问题。

add_shortcode( 'v3grid', 'v3grid_shortcode_processing' );
/**
 * v3grid shortcode processor.  It builds the HTML markup for
 * the most recent posts and assembles them into a grid markup
 * structure.
 *
 * @since 1.0.0
 *
 * @param array $atts Array of user-defined attributes
 *
 * @return string
 */
function v3grid_shortcode_processing( $atts ) {

    $atts = shortcode_atts(
        array(
            'count'       => 3,
            'link_to_all' => 'yes',
            'css_class'   => 'v3grid',
            'categories'  => '1',
        ), $atts, 'v3grid'
    );

    // Get list of recent posts
    $args = array(
        'numberposts' => (int) $atts['count'],
        'post_type'   => 'roundup',
        'post_status' => 'publish',
    );

    $recent_posts = wp_get_recent_posts( $args, ARRAY_A );
    if ( ! $recent_posts ) {
        return '<p>Sorry, there are no posts to display.</p>';
    }

    // Figure out width requirement for each grid item
    $width = 100 / (int) $atts['count'];

    // Container for row start
    $output = 'Start -> <div style="margin:0 -10px 0 -10px; box-sizing: border-box; position:relative; display:block;">';

    // Loop through posts
    foreach ( $recent_posts as $recent ) {
        $thumbnail = get_the_post_thumbnail_url( $recent["ID"], 'full' );
        $url       = get_permalink( $recent["ID"] );

        $output .= '   1 - <div style="width:' . (int) $width . '%; float:left; padding:10px; display:block;">';
        $output .= '       2 - <div><img src="' . esc_url( $thumbnail ) . '" style="display:block; width:100%;"></div>';
        $output .= '       3 - <div><a href="' . esc_url( $url ) . '">' . esc_html( $recent["post_title"] ) . '</a></div>';
        $output .= '   4 - </div>';
    }
    wp_reset_query();

    $output .= 'End -> </div>';

    return $output;
}

现在呢?

现在您已经解决了短代码功能中的问题。好的,但你说最初的问题是:当你 echo 时它工作得很好,但当你 return 时却不行。这意味着在您返回 HTML 文本后,有些东西正在过滤掉它。

对吗?如果 HTML 在回显时是完美的,但在通过网站处理并呈现到浏览器时却不稳定,那么您知道问题的其余部分可能是在您上面的代码之后。

我会先看看你的插件。确保你没有做这样的过滤the_content。禁用插件的其余代码并查看短代码是否正确呈现。

如果这不能解决问题,则禁用所有其他插件。问题会消失吗?切换到默认的 WordPress 主题。问题会消失吗?

这种方法就是我们所说的消除方法。您正在消除所有变量和可能的贡献者,将网站剥离到最基本的部分,以努力找到根本原因。

正如我所说,它在我的沙盒机器上运行没有问题。但是我的设置和你的不一样。将网站剥离到最基本的部分有助于您找出导致问题的原因。

改进提示

以下是对您也有帮助的改进列表:

  1. 您不需要在传递给wp_get_recent_posts() 的参数中包含默认状态元素。请注意,我在上面的代码中减少了它们。
  2. 您想验证wp_get_recent_posts 是否返回错误值。这意味着没有符合您条件的帖子。
  3. shortcode_atts 时包含短代码名称。虽然这不会导致您的问题,但更好的做法是允许其他开发人员访问。
  4. 使用类属性并将内联样式移动到样式表中。

关注点分离

从 PHP 业务逻辑中删除 HTML 是一种最佳做法。将 HTML 放入视图文件中。为什么?关注点分离。它还提高了可读性。

这是给你的一个例子。

这是视图文件。我们称之为views/v3grid.php。请注意,它是原生 HTML,更易于阅读。

<!-- Start v3grid -->
<div style="margin:0 -10px 0 -10px; box-sizing: border-box; position:relative; display:block;">
<?php foreach ( $recent_posts as $recent ) :
    $thumbnail = get_the_post_thumbnail_url( $recent["ID"], 'full' ); ?>
    <!-- v3grid item -->
    <div class="v3grid--item" style="width: <?php echo (int) $width; ?>%; float: left; padding: 10px; display: block;">
        <div class="v3grid--thumbnail">
            <img src="<?php echo esc_url( $thumbnail ); ?>" style="display: block; width: 100%;">
        </div>
        <div class="v3grid--entry-title">
            <a href="<?php echo esc_url( get_permalink( $recent["ID"] ) ); ?>"><?php esc_html_e( $recent["post_title"] ); ?></a>
        </div>
    </div>
<?php endforeach; ?>
<!-- End v3grid --></div>

然后在您的简码函数中,您可以像这样替换此代码:

add_shortcode( 'v3grid', 'v3grid_shortcode_processing' );
/**
 * v3grid shortcode processor.  It builds the HTML markup for
 * the most recent posts and assembles them into a grid markup
 * structure.
 *
 * @since 1.0.0
 *
 * @param array $atts Array of user-defined attributes
 *
 * @return string
 */
function v3grid_shortcode_processing( $atts ) {

    .. this all remains the same as above

    // Figure out width requirement for each grid item
    $width = 100 / (int) $atts['count'];

    ob_start();
    include( __DIR__ .'/views/v3grid.php' );
    $html = ob_get_clean();

    wp_reset_query();

    return $html;
}

然后你可以拉出所有的内联样式并将它们添加到外部样式表中。

【讨论】:

  • 哇,非常感谢您花时间提供帮助。很酷。我不确定发生了什么,我已经实施了您的建议,但我仍然遇到同样的问题。一旦我得到它的工作和你的建议删除 HTML,我会移动 CSS ......非常聪明,我也会这样做。
  • 如果我把它注释掉,它会起作用...$output .= '2 - &lt;div&gt;&lt;img src="'.esc_url($thumbnail).'" style="display:block; width:100%;"&gt;&lt;/div&gt;';
  • @InsuredApple 您需要查看$thumbnail 中的值。确保该变量中有一个 URL。
  • 是的,我就是这么想的,但是当我将它们呼应出来时,它们看起来还不错。普通的网址……太奇怪了。
  • 有趣....这项工作:$output .= '2 - &lt;div&gt;'.esc_url($thumbnail).'&lt;/div&gt;'; 但一旦我添加了 img 标签,它就会中断。这打破了它$output .= '2 - &lt;div&gt;&lt;img src="'.esc_url($thumbnail).'"&gt;&lt;/div&gt;';
【解决方案2】:

在编写shortcode 时,您将return 在它的函数中,并在您使用的.php 文件中调用它:echodo_shortcode()

考虑只使用通常的回显功能,除非它应该由您的插件用户通过仪表板使用。

【讨论】:

  • 感谢您的回复...您的回复让我有点困惑。我使用简码作为 [v3grid] 并返回 $output 变量。但是退货会引起问题。
  • Echo 对我不起作用,因为当我回显字符串时,它总是显示为页面上的第一个元素。
  • 好的,但是你如何调用你的函数呢?
  • 这是通过简码完成的。我将 [v3grid] 作为文本插入页面,然后 Wordpress 执行该功能。我在函数中有一个回显并返回(在底部) - 使用相同的变量 $output。 Echo 有效,但 return 不会返回完整的 $output。
【解决方案3】:

正如manual 所说:

如果短代码生成大量 HTML,则 ob_start 可用于捕获输出并将其转换为字符串[...]

因此,您的代码必须使用回显并返回生成的字符串:

function v3grid_func() {
    ob_start(); // open the buffer

    /**
       all your code
    **/

    echo $output; // as you did

    return ob_get_clean(); // return from buffer and clean the buffer
}

【讨论】:

  • 有趣。我不确定这是否是进步,因为最终输出仍然“损坏”。使用 echo $output 并返回 ob_get_clean();导致代码显示在简码所在的位置(这很好),但输出仍然损坏。
  • 你的 WP 版本是多少? 2.5有一个bug。以及其他一些可以纠正您的代码的提示
  • 我使用的是 4.7 版的 Wordpress。
猜你喜欢
  • 2021-10-26
  • 2011-06-26
  • 1970-01-01
  • 2020-02-17
  • 2017-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
相关资源
最近更新 更多