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

想问一个关于在 laravel 里异步执行代码的简单方法

  •  
  •   zengguibo · 311 天前 · 2078 次点击
    这是一个创建于 311 天前的主题,其中的信息可能已经有所发展或是发生改变。

    class AdminController extends BaseAdminController {

    public function __construct()
    {
        
    }
    
    public function store(Request $request)
    {
        //下面的代码放在后台运行
        UserModel::insert($data);
        //直接返回成功
        $this->success(['desc' => '成功']);
    }
    

    } 就是前台调用这个 api 的时候,UserModel::insert($data);这一段放在后台运行,而函数直接返回成功,用队列什么的有点重了,有没有简单点的方法

    20 条回复    2023-07-07 17:24:58 +08:00
    ysc3839
        1
    ysc3839  
       311 天前 via Android   ❤️ 2
    没办法。PHP 官方至今还是只支持传统的 CGI 模式,即有请求来了就从头执行脚本,直到脚本退出才算请求完成。因此只要后台执行的代码不退出,客户端的请求就不会完成,会一直等着。
    zengguibo
        2
    zengguibo  
    OP
       311 天前
    @ysc3839 感谢你的回复,这个问题我研究了很久也没找到方法,对于这种运行时间太长的 api ,只能用队列的方式了吗
    yesC
        3
    yesC  
       311 天前
    Laravel 的中间件中有个 terminate 方法,可以在把数据响应给客户端后,做一些逻辑处理。
    vjnjc
        5
    vjnjc  
       311 天前
    PHP 的本质上是单个 request 走到底,没有线程池
    异步依赖于 redis 这种中间件
    xiaoxuan6
        6
    xiaoxuan6  
       311 天前
    为什么最近老是遇到问这种问题的?既然用 php 了就别纠结这个问题,直接用队列简单方便
    https://learnku.com/laravel/t/78187
    via
        7
    via  
       311 天前 via iPhone
    我把队列包装了一下,直接把一个函数传递过去就可以了,下面是调用方法:

    Async::run(function(){ /* your code here */ });
    dedemao
        9
    dedemao  
       311 天前
    ```
    $pid = pcntl_fork();
    if ($pid == -1) {
    die('could not fork');
    } else if ($pid) {
    //下面的代码放在后台运行
    UserModel::insert($data);
    pcntl_wait($status);
    } else {
    //直接返回成功
    $this->success(['desc' => '成功']);
    }
    ```
    james122333
        10
    james122333  
       311 天前 via Android
    楼上正解 不过不只如此
    楼上应该不用讲 框架使用者通常都这样
    westoy
        11
    westoy  
       311 天前
    扔队列, 让消费者去消化

    就算原生协程的方案, 这种操作一样是扔队列的

    不然被人 C 一下, 这种高耗操作不做任何限制就直接打到上游了
    james122333
        12
    james122333  
       311 天前 via Android
    对他们而言 没招可放是很常见的 偏偏混的很好
    westoy
        13
    westoy  
       311 天前
    @james122333

    当年 php 官方的态度就是,pcntl 你在 cli 下面用用就好了, 别拿去在 web 下面跑

    我还以为十几年没写过 php , 官方转性了, 也没啊

    这种常识现在都成冷知识了?

    https://www.php.net/manual/en/intro.pcntl.php


    """
    Process Control support in PHP implements the Unix style of process creation, program execution, signal handling and process termination. Process Control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment.
    """

    --enable-pcntl Enable pcntl support (CLI/CGI only)
    james122333
        14
    james122333  
       311 天前 via Android
    @westoy

    不是冷门 但对某些人想破头都不知 他们的知识面被侷限
    james122333
        15
    james122333  
       311 天前 via Android
    不管如何他们都还是会解决 只是解法很不漂亮然后不怎么好而已
    veike
        16
    veike  
       311 天前
    insert 放在后置操作方法里,但是这样要解决什么问题?
    demoshengxw
        17
    demoshengxw  
       311 天前 via iPhone
    我看到有多进程的,但是多进程是不可以宅 fpm 里使用的。但是有一个把 insert 那段代码放在 fastcgi_finish_request 之后执行
    thinkingbullet
        18
    thinkingbullet  
       310 天前
    public function store(Request $request)
    {
    //直接返回成功
    $this->success(['desc' => '成功']);
    // 此函数会让后面的操作在后台静默运行,仅限于 nginx+php
    fastcgi_finish_request();
    //下面的代码放在后台运行
    UserModel::insert($data);

    }
    flyqie
        19
    flyqie  
       310 天前 via Android
    php 执行异步代码想不做队列还是歇歇吧。

    任何语言执行异步请求最稳妥的办法都是搞队列或者任务池。。
    guanguans
        20
    guanguans  
       295 天前
    简单一点 afterResponse 就可以了。也可以用 terminate 中间件。原理一样都是 fastcgi_finish_request 。

    ```php
    dispatch(function () {
    // UserModel::insert($data);
    })->onConnection('sync')->afterResponse();
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   876 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:37 · PVG 05:37 · LAX 14:37 · JFK 17:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.