如何从非控制器方法的方法发送响应?

daz*_*per 10 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;
}
Run Code Online (Sandbox Code Playgroud)

现在,在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.
}
Run Code Online (Sandbox Code Playgroud)

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

Bor*_*rov 8

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

无需将其作为控制器方法的返回值。

请注意,调用send()不会终止输出。您可能要在exit;之后手动拨打电话send()


Ala*_*nde 7

对我来说,最简单、最优雅的方法是:

response()->json($messages_array, $status_code)->throwResponse();
Run Code Online (Sandbox Code Playgroud)

(不需要退货)

它可以从私有函数或另一个类调用......

我在辅助类中使用它来检查权限,如果用户没有权限,我会抛出上面的代码。


Voy*_*sky 6

你可能正在寻找这个:

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
}
Run Code Online (Sandbox Code Playgroud)

并在控制器方法中:

$response = $this->checkEverythingIsOk();
if(!is_null($response)) {
    return $response;
}
Run Code Online (Sandbox Code Playgroud)


mwa*_*sch 6

这可能有点矫枉过正,但无论如何我都会把它扔进去。您可能想查看内部请求。此外,这只是伪代码,我实际上并没有这样做,所以请谨慎使用这些信息。

// 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', ...);
Run Code Online (Sandbox Code Playgroud)

现在,您可以在该路由的末尾放置一个控制器并解释参数,或者您可以使用由多个控制器/方法回答的多个路由......由您决定,但方法保持不变。

更新

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

但是我在想另一种方式,为什么不抛出异常并在适当的地方捕获它以返回指定的响应?

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

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

// throw it, it is a Illuminate\Http\Exception\HttpResponseException
$response->throwResponse();  
Run Code Online (Sandbox Code Playgroud)

现在通常一个异常将被记录和你,如果你是在调试模式下,你会看到它在屏幕上等等等等。但是,如果你看看到\Illuminate\Foundation\Exceptions\Handler的内render方法,你可以看到它检查抛出的异常,如果它是一个实例的HttpResponseException。如果是,则 Response 将立即返回。