V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
SomeBottle
V2EX  ›  PHP

PHP 在 echo 后发送 header 的问题

  •  
  •   SomeBottle · 2018-08-19 11:53:42 +08:00 · 4006 次点击
    这是一个创建于 2289 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前玩 PHP 尝试在 echo 后发送 Header,但是直接写在一起是没法送出去头的..

    根据网上的方法我把 echo 和 header 丢到了 ob 缓冲区里,就像下面这个图一样..

    本地 phpStudy 环境测试非常成功..但是扔到服务器(Linux - Nginx)上后就出现了发送不出去头的问题, 本来我期待在 echo 执行完后关闭连接转服务端执行的...结果 header 发不出去只会全部执行完再返回数据..

    求问我是哪里写错了吗...还是说这种方法已经不可行了,测试 PHP 版本是 5.4...

    第 1 条附言  ·  2018-08-19 12:33:23 +08:00

    我在header前还写了个session:

    第 2 条附言  ·  2018-08-19 12:58:20 +08:00
    使用 fastcgi_finish_request();( PHP-fpm )可以强制断开客户端连接,可以暂时替代。
    16 条回复    2018-08-19 18:14:07 +08:00
    bao0541
        1
    bao0541  
       2018-08-19 12:04:16 +08:00
    请注意 header() 必须在任何实际输出之前调用,不管是普通的 HTML 标签,还是文件或 PHP 输出的空行,空格。这是个常见的错误,在通过 include,require,或者其访问其他文件里面的函数的时候,如果在 header()被调用之前,其中有空格或者空行。 同样的问题也存在于单独的 PHP/HTML 文件中。
    SomeBottle
        2
    SomeBottle  
    OP
       2018-08-19 12:07:15 +08:00
    @bao0541 我现在的问题就在于不懂为什么会这样,不然早就解决了...前面没有任何输出,我打开全部报错也没有任何报错,这是用于 ajax 请求的一个后端,只有这一句 echo 输出.
    chinvo
        3
    chinvo  
       2018-08-19 12:14:01 +08:00 via iPhone
    你第二行 echo 就是输出,header 必须放在任何输出前
    batnss
        4
    batnss  
       2018-08-19 12:15:17 +08:00
    header 2 句放最后试试
    SomeBottle
        5
    SomeBottle  
    OP
       2018-08-19 12:34:07 +08:00
    @chinvo 询问一下 session 算输出吗..
    @batnss 这样行不通,obflush 直接输出了缓冲区的 echo
    NextAccount
        6
    NextAccount  
       2018-08-19 12:50:39 +08:00   ❤️ 1
    @SomeBottle session 本质上是 header set-cookie,所以不算输出。这里的输出指的是 response body 的部分。

    我测试了一下 Content-Length 输出成功,但是 Connection 头仍然是 Keep-Alive,这个和 HTTP 服务器配置有关系。

    "本来我期待在 echo 执行完后关闭连接转服务端执行的...结果 header 发不出去只会全部执行完再返回数据.." --- 这句话是什么意思?
    SomeBottle
        7
    SomeBottle  
    OP
       2018-08-19 12:54:40 +08:00
    @NextAccount 就是如果没有关闭连接就要等待 flush 后的程序执行完才会返回 echo,不过刚刚我在想 fastcgi_finish_request();有没有作用..
    chinvo
        8
    chinvo  
       2018-08-19 13:01:21 +08:00
    header 放到 ob_start 之前
    chinvo
        9
    chinvo  
       2018-08-19 13:03:22 +08:00   ❤️ 1
    你现在的写法把 header 包在 ob cache 里面了
    SomeBottle
        10
    SomeBottle  
    OP
       2018-08-19 13:05:15 +08:00
    @chinvo 我换了好多 header 的位置还是不行,你提示的这个地方我也试过,只有 Content-Length 被设置了,看来是 http 服务器设置有问题..
    NextAccount
        11
    NextAccount  
       2018-08-19 13:08:31 +08:00
    @SomeBottle 即使你成功输出 Connection: close 头信息,也并不会关闭当前的 HTTP 连接。你完全可以 有条件的 return 掉不行么?
    NextAccount
        12
    NextAccount  
       2018-08-19 13:10:54 +08:00
    fastcgi_finish_request() 会结束客户端连接,也许可行。但是后面的代码仍然会执行。
    SomeBottle
        13
    SomeBottle  
    OP
       2018-08-19 13:14:35 +08:00
    @NextAccount 我需要的就是继续在服务端执行后面的代码。fastcgi_finish_request 虽然有环境的限制,但是我记得很多网站服务器 PHP 模块都支持 fastcgi 协议
    NextAccount
        14
    NextAccount  
       2018-08-19 13:14:38 +08:00   ❤️ 1
    终于明白了楼主的意思。楼主是想要尽快输出,但是有一部分代码在服务器端继续执行。

    你有几个选择:

    1. fastcgi_finish_request
    2. 通过消息系统或者直接 exec 开后台子进程去异步执行。
    mrcn
        15
    mrcn  
       2018-08-19 14:49:22 +08:00 via Android
    搞个后台队列是最方便的。

    header 发送的是 http 头,必须在所有输出之前,就像你必须先拿碗才能装菜一样。
    otakustay
        16
    otakustay  
       2018-08-19 18:14:07 +08:00
    如果你想尽快输出内容,那么就别用 Content-Length,用 chunked encoding 输出
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2735 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 06:55 · PVG 14:55 · LAX 22:55 · JFK 01:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.