最近在用laravel-s改造手頭上的一個laravel專案,作為這塊目前最火的輪子,確實好用,贊一下作者。由於目前所處理的專案需要呼叫大量api,使用同步序列呼叫效率低下,因此開始嘗試使用swoole的協程客戶端來呼叫api。
這裡我本地的環境如下:
Component | Version |
---|---|
PHP | 7.1.17 |
Swoole | 2.1.2 |
Laravel Framework | 5.5.40 |
先來個demo體驗一下:
<?php
namespace App\Http\Controllers;
class TestController extends Controller
{
public function index()
{
$cli = new \Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$cli->setHeaders([
'Host' => 'test.me',
]);
$cli->get('/');
$result = $cli->body;
$cli->close();
return response()->json($result);
}
}
啟動請求之後發現卡死,這下懵逼了,以前在其他地方都是可以用的協程客戶端,這裡不能用了,WTF。在群裡求助,群主提及到不能在魔術方法和call_user_func之類的方法裡使用(官方連結)。一語驚醒夢中人,laravel這個框架可是這類方法橫行,於是研究了下Controller類的執行方式。框架在執行Controller時,會通過Illuminate\Routing\Controller
類的callAction
方法執行具體的Controller類的方法,而這個方法如下:
/**
* Execute an action on the controller.
*
* @param string $method
* @param array $parameters
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function callAction($method, $parameters)
{
return call_user_func_array([$this, $method], $parameters);
}
總算找到問題所在了,接下來便是解決問題。其實解決問題的方式swoole的文件裡也寫了,使用\Swoole\Coroutine::call_user_func
和\Swoole\Coroutine::call_user_func_array
代替即可。那麼我們只需要在App\Http\Controllers\Controller
中重寫一下callAction
方法,程式碼如下:
public function callAction($method, $parameters)
{
return \Swoole\Coroutine::call_user_func_array([$this, $method], $parameters);
}
注意如果在__call()
這樣的魔術方法裡面需要使用$obj->$method(...$arguments)
這種方式去處理用\Swoole\Coroutine::call_user_func_array
還是會出現問題。
Done!
目前只是遇到這個坑,以後遇到再更新。