Laravel 如何从不是控制器方法的方法发送响应?

Laravel 如何从不是控制器方法的方法发送响应?,laravel,laravel-5,laravel-5.2,Laravel,Laravel 5,Laravel 5.2,我有一个Controller.php,它的show($id)方法被路由击中 public function show($id) { // fetch a couple attributes from the request ... $this->checkEverythingIsOk($attributes); // ... return the requested resource. return $response; } 现在,在checkEver

我有一个
Controller.php
,它的
show($id)
方法被路由击中

public function show($id)
{
    // fetch a couple attributes from the request ...

    $this->checkEverythingIsOk($attributes);

    // ... return the requested resource.
    return $response;
}
现在,在
checkEverythingIsOk()
中,我执行了一些验证和授权工作。这些检查对于同一控制器中的多个路由是通用的,因此我想提取这些检查,并在每次需要执行相同操作时调用该方法

问题是,我无法通过此方法发送一些响应:

private function checkEverythingIsOk($attributes)
{
    if (checkSomething()) {
        return response()->json('Something went wrong'); // this does not work - it will return, but the response won't be sent.
    }

    // more checks...
    return response()->callAResponseMacro('Something else went wrong'); // does not work either.

    dd($attributes); // this works.
    abort(422); // this works too.
}

注意:是的,我知道通常可以使用中间件或验证服务在请求到达控制器之前执行检查,但我不想这样做。我需要这样做。

您可能正在寻找:

function checkEverythingIsOk(){
    if (checkSomething()) {
        return Response::json('Something went wrong', 300);
    }
    if(checkSomethingElse()) {
        return Response::someMacro('Something else is wrong')
    }
    return null; // all is fine
}
在控制器方法中:

$response = $this->checkEverythingIsOk();
if(!is_null($response)) {
    return $response;
}

这可能是杀伤力过大,但无论如何我还是要把它扔掉。您可能需要查看内部请求。另外,这只是伪代码,我实际上并没有这样做,所以请谨慎使用这些信息

// build a new request
$returnEarly = Request::create('/returnearly');

// dispatch the new request
app()->handle($newRequest);

// have a route set up to catch those
Route::get('/returnearly', ...);
现在,您可以让一个控制器坐在该路由的末尾并解释参数,或者使用由多个控制器/方法应答的多个路由。。。由您决定,但方法保持不变

更新

好的,我自己也尝试过,创建一个新的请求并发送它,它是这样工作的。问题是,在子请求退出后,执行不会停止。它在父请求中继续。这使得整个方法都毫无用处

但我在考虑另一种方法,为什么不抛出一个异常并在适当的位置捕获它以返回指定的响应呢

事实证明,这已经内置于Laravel中:

// create intended Response
$response = Response::create(''); // or use the response() helper

// throw it, it is a Illuminate\Http\Exception\HttpResponseException
$response->throwResponse();  

现在通常会记录一个异常,如果您处于调试模式,您会在屏幕上看到它等等。但是如果您查看
render
方法中的
\light\Foundation\Exceptions\Handler
,您可以看到它检查抛出的异常,如果它是
HttpResponseException
的实例。如果是,则会立即返回响应。

从Laravel 5.6开始,您现在可以使用例如
Response()->json([1])->send()

它不需要是控制器方法的返回值


请注意,调用
send()
不会终止输出。您可能需要调用
exitsend()

之后手动执行code>错误消息响应格式与每种错误类型不同。有时我想调用一个响应宏,它将从数据库中获取其他数据,有时我只需打印一条消息、中止等等……如何
return$this->checkEverythingIsOk($attributes)
dd()
abort()
无论如何都会取消脚本执行。如果一切正常,您可以返回
null
,如果没有,则返回响应,然后在控制器方法中进行简单检查。这通常是PHP的正确答案,但是Boris D.Teoharov使用
->send()
响应方法对laravel有更好的答案。我感谢您花时间解决这个问题,但是,您的方法本质上与@Vojo123相同,只是捕获异常而不是空检查,并且增加了创建和处理内部请求的复杂性。如果你看一下Laravel API文档,你会发现除了控制器方法之外,没有其他方法可以发送完整的请求,所以这两种解决方法都很好。内部请求部分无论如何都不起作用。别理它。抛出的响应本身就是一个解决方案,您也可以将其写在一行中,如Response(…)->throwResponse();由于捕获已经内置在Laravel中,有人甚至可能会争辩说,这不是一个解决方法,而是实际的预期用例。如果使用sonarqube分析,它将引发多回报问题(超过3)。使用此方法可以重写。