Laravel 路由解析自定义数据类型
Posted
技术标签:
【中文标题】Laravel 路由解析自定义数据类型【英文标题】:Laravel route resolve custom data type 【发布时间】:2021-10-05 02:10:51 【问题描述】:我在routes/api.php
有以下路线:
Route::get('items/item', function(Guid $item) ...);
Route::get('users/user', function(Guid $user) ...);
由于Guid
是一个自定义类型,我该如何通过依赖注入解决这个问题?如图,路由参数item
与回调参数type-hint:Guid
不同,无法自动解析。
这就是我在 app/Providers/AppServiceProvider.php
中尝试过的:
class AppServiceProvider extends ServiceProvider
/**
* Register any application services.
*
* @return void
*/
public function register()
$this->app->bind(Guid::class, function(Application $app, array $params)
return Guid::fromString($params[0]);
);
我希望$params
是这样的:[ 'item' => 'guid' ]
——但它是:[]
。
【问题讨论】:
item
与 Guid $item
的差异有多大?第一个是字符串(URL-.Path 的子字符串),而第二个根本不是字符串?根据您的理解,Laravel 通常如何将 URL-Path 子字符串映射到 any PHP 对象类型?还是您在其他地方看到了不同之处?
item 路由参数是一个 guid 字符串,而 Guid 是一个包装器对象,它具有一些实用方法,如验证。 Laravel 通常映射到模型。但是由于我必须自己实现模型(它不是像 Laravel 的模型那样的数据库模型),我想,这样解决它比实现整个 URLRoutable
合约更容易。
【参考方案1】:
您可以使用explicit bindingLaravel Routing:
在RouteServiceProvider::boot()
:
public function boot()
Route::model('item', Guid $item);
Route::model('user', Guid $user);
如果 Guid
不是 模型,则使用 闭包 映射到字符串:
Route::bind('user', function ($value)
return Guid::fromString($value);
);
更新
我找到了另一种更好的方法——实现UrlRoutable contractLavaravel API:
<?php
namespace App\Models;
use Illuminate\Contracts\Routing\UrlRoutable;
class Guid implements UrlRoutable
private string $guid;
public function setGuid(string $guid)
$this->guid = $guid;
return $this;
public function getGuid(): string
return $this->guid;
public static function fromString(string $guid): self
//you cannot set props from constructor in this case
//because binder make new object of this class
//or you can resolve constructor depts with "give" construction in ServiceProvider
return (new self)->setGuid($guid);
public function getRouteKey()
return $this->guid;
public function getRouteKeyName()
return 'guid';
public function resolveRouteBinding($value, $field = null)
//for using another "fields" check documentation
//and maybe another resolving logic
return self::fromString($value);
public function resolveChildRouteBinding($childType, $value, $field)
//or maybe you have relations
return null;
而且,有了这个,你可以使用你想要的路由,因为Guid
现在实现了UrlRoutable
,并且可以将item
(或其他)URL 路径子字符串标记转换为 Guid s per 依赖注入(根据你要求的类型提示):
Route::get('items/item', function(Guid $item)
return $item->getGuid();
);
顺便说一句:永远不要在路由中使用闭包,因为你不能缓存闭包路由 - 路由很适合优化,缓存有助于 Laravel 路由。
【讨论】:
但是Guid
不是模型。它只是一个自定义复合类型。关闭仅用于演示目的 - 感谢您的提示!
非模型更新
谢谢,但在这种情况下,每次我想使用 guid,路由参数都必须命名为 user 或者我必须手动为每个参数创建一个绑定,对吗?
@shaedrich 我正在更新答案,请检查:)
@hakre 可以通过使用控制器元组 ([ YourController::class, 'yourMethod' ]
) 或字符串 (YourController::yourMethod'
) 来防止关闭【参考方案2】:
利用路由绑定回调的简单助手。
if (!function_exists('resolve_bind'))
function resolve_bind(string $key, mixed $value)
return call_user_func(Route::getBindingCallback($key), $value);
用法
resolve_bind('key', 'value');
【讨论】:
以上是关于Laravel 路由解析自定义数据类型的主要内容,如果未能解决你的问题,请参考以下文章
Swift之Codable自定义解析将任意数据类型解析为想要的类型
Swift之Codable自定义解析将任意数据类型解析为想要的类型