Laravel:如何检索命名路由,但稍后分配参数

问题描述 投票:0回答:1

我喜欢尽可能简化我的控制器。在处理 API 时,我有时会使用服务类(存储库?)方法,该方法需要一些输入以及

RedirectResponse
,如下所示:

use App\Http\Controllers\Controller;

class MyController extends Controller
{
    public function create(Request $request)
    {
        $validated = $request->validate([...]);
        return MyService::createWithResponse(
            input: $validated,
            response: back()
        );
    }
}

我可以在这里专注于I/O。

MyService::createWithResponse
将处理所有存储库逻辑,但它也将处理错误/成功消息传递:

use \Illuminate\Http\RedirectResponse;

class MyService
{
    public static function createWithResponse(array $input, RedirectResponse $response)
    {
        // ...repository logic dealing with the third-party API
        if (/* the API sends me an error */) {
            return $response->with(['error' => $some_error]);
        }
        $resourceId = /**/;
        return $response->with(['success' => 'Your resource has been created!']);
    }
}

好吧,假设我有:

Route::get('/resources/{resourceId}', ...)->name('resources.show');

并且我正在尝试找到一种使用

createWithResponse
来调用
response()->redirectToRoute('resources.show')
的方法,但我想稍后传递路由参数(即
$resourceId
);在运行存储库逻辑之前,我还不知道
resourceId

我不能只将路由名称字符串传递到

createWithResponse
中,因为预期的
RedirectResponse
可能不是用于命名路由,或者我可能在传递它之前已经向
RedirectResponse
添加了参数。 (无论如何,
MyService
应该是不可知的,并且该信息应该保留在控制器中。)

我如何传递按名称检索的

Route
,然后附加参数?或者还有其他方法可以做到这一点吗?几周来我一直在断断续续地寻找解决方案。

php laravel routes repository-pattern
1个回答
0
投票

一种选择是将成功/失败回调传递给您的服务方法。回调闭包可以接受结果中的数据作为参数。

考虑:

use \Illuminate\Http\RedirectResponse;

class MyService
{
    public static function create(
        array $input,
        callable $onSuccess,
        callable $onFailure
    )
    {
        // ...repository logic dealing with the third-party API
        if (/* the API sends me an error */) {
            return $onFailure($some_error);
        }
        $resourceId = /**/;
        return $onSuccess($resourceId);
    }
}
use App\Http\Controllers\Controller;

class MyController extends Controller
{
    public function create(Request $request)
    {
        $validated = $request->validate([...]);
        return MyService::create(
            input: $validated,
            onSuccess: fn(string $resourceId) => response()
                ->redirectToRoute('resources.show', $resourceId)
                ->with(['success' => 'Your resource has been created!']),
            onFailure: fn(string $errorMsg) => back()
                ->with(['error' => $errorMsg])
        );
    }
}

这将 I/O 逻辑完全保留在控制器中。服务方法不需要知道响应应该是什么类型,让控制器定义它。现在应用程序的其他部分可以使用该服务方法并定义自己的输出。

此外,您可以使用一些 PHPDoc“泛型”(

@template
) 语法糖来帮助您的 IDE 并使这一点更加明显:


class MyService
{
    /**
     * @template TSuccess of mixed
     * @template TFailure of mixed
     * @param array $input
     * @param callable(string):TSuccess $on_success
     * @param callable(string):TFailure $on_failure
     * @return TFailure|TSuccess
     */
    public static function create(
        array $input,
        callable $onSuccess,
        callable $onFailure
    )
    {
    ...
© www.soinside.com 2019 - 2024. All rights reserved.