REST API调用中的GET_TEMPLATE_PART标头已发送错误

时间:2021-01-19 作者:Nico

来自的交叉柱StackOverflow

我已经查看了有关此警告的多个其他问题(标题已发送…等),以及this thorough explanation, 但我并没有为我所处理的情况找到解决方案:

我有一个自定义的Wordpress REST API端点returns the output of get_template_part. 当我打电话的时候get_template_part 通常在页面上没有警告。它仅在运行时出现register_rest_route\'s回调this library. 错误开始于我开始发出这些请求时。我已经尝试在模板部分的内部和外部发出请求,后者在register_rest_route\'s回调或作为init 行动img tag,我在哪里echo-将URL作为src 使用来自外部API响应的数据。还有其他echo 调用此模板,所以我怀疑这是问题所在

Code:

内部功能。php:

<?php

  //the api endpoint declaration
  add_action( \'rest_api_init\', function () {
    register_rest_route(
        \'theme/v2\',   // namespace
        \'/homepage\',  // route
        array(                  // options
            \'methods\'  => \'GET\',
            \'callback\' => \'build_home\',
        )
    );
  });

  //the callback for the wordpress api
  function build_home() {

    // this is the external API request, using their PHP library. 
    // I linked the library above. The request returns an object with a bunch of data
    include_once(get_template_directory()."/arena/arena.php");
    $arena = new Arena();
    $page = $arena->set_page(); 
    $per = 8; 
    $slug = \'concepts-bo-6ajlvpqg\'; 
    $channel = $arena->get_channel($slug, array(\'page\' => $page, \'per\' => $per));

    //I\'m passing the response from the external API (in $channel) to get_template part
    //get_template_part is then the output for the wordpress API request
    get_template_part(\'custom-home-template\',null,array(\'channel\'=>$channel));
 }

 ?>
模板内部零件:

<?php
  $channel=$args["channel"];
  ?>

  <div id="concepts-box" class="bodycontent reg-width">
    <?php foreach ($channel->contents as $item) { if($item->class=="Image"){
      $img=$item->image["square"]["url"];
      ?>
    <div class="concept-wrapper">
      <!-- the line below is the one that triggers the error -->
      <img lozad src="<?=$img; ?>">
    </div>
    <?php }} ?>
  </div>
完全警告:

<b>Warning</b>:  Cannot modify header information - headers already sent by (output started at /filepath/wp-content/themes/theme/custom-home-template.php:63) in <b>/filepath/wp-includes/rest-api/class-wp-rest-server.php</b> on line <b>1372</b><br />

1 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

I have a custom Wordpress REST API endpoint that returns the output of get_template_part

Note that the REST API expects your endpoint callback to always return the response (e.g. the template part output in your case), and not echo it or anything else. And after the callback is called, the REST API will send some headers, by default an Allow header and then any extra headers from your response — see WP_REST_Server::serve_request(), particularly lines #440 and #472.

So because of that, you should not echo anything in your callback, because for example echo \'foo\'; header( \'Allow: GET\' ); will cause the "headers already sent" error because the echo started the output, hence PHP issues a warning if you try to send a (HTTP) header afterwards.

Therefore, despite you said, "The error started when I started making these requests.", I\'m pretty sure the problem is with your call to get_template_part() which (despite the name) actually simply loads the template part and if successful, the function returns nothing.

And if the template part echo something (which is what happens in most cases) just like yours as in the question, then that will result in the "headers already sent" warning. Try commenting out the get_template_part() call and see if the warning goes away. :)

But even if not, please ensure your callback is not echoing anything because doing so will invalidate the JSON response (both header and content) which is the default response type returned by the REST API endpoint. However, if you need to echo something, then you would want to use output buffering like so in your case:

function build_home() {
    ob_start();

    // ... your code.
    get_template_part( ... your code ... );
    $data = ob_get_clean();

    // The array key ("html") below can be any other name that you prefer.
    return new WP_REST_Response( array(
        \'html\' => $data,
    ) );
}

And please always set the permission_callback for your endpoint, because otherwise, you\'d get a (_doing_it_wrong()) notice like so:

The REST API route definition for theme/v2/homepage is missing the required permission_callback argument. For REST API routes that are intended to be public, use __return_true as the permission callback.

So for example, your code would look like so:

register_rest_route(
    \'theme/v2\',  // namespace
    \'/homepage\', // route
    array(       // options
        \'methods\'             => \'GET\',
        \'callback\'            => \'build_home\',
        \'permission_callback\' => \'__return_true\', // always set a permission callback
    ),
);

And BTW, if you want a different response type (i.e. Content-Type) for your endpoint, then you can use the rest_pre_serve_request hook — see an example in my answer here.

相关推荐

Execute shortcodes in PHP

我在帖子编辑器中添加了一个地理位置快捷码,可以根据用户的位置显示不同的信息,将其放在帖子页面的内容中,效果非常好。如何在主题的PHP文件中执行此短代码[地理位置][地理位置]?我正在使用免费修改Wordpress主题,我想添加一个新的<span>[geolocation][/geolocation]Information text content</span> 但在主题的内部。php文件,我如何才能做到这一点?如果我直接加上<span>[geolocation][/ge