【发布时间】:2018-10-23 07:28:41
【问题描述】:
目前我正在做一个项目,我们正在尝试创建一个 RESTful API。此 API 使用一些默认类,例如 ResourceController,用于在需要时可以覆盖的基本行为。
假设我们有一个 API 资源路由:
Route::apiResource('posts', 'ResourceController');
这条路线将使用ResourceController:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Repositories\ResourceRepository;
class ResourceController extends Controller
{
/**
* The resource class.
*
* @var string
*/
private $resourceClass = '\\App\\Http\\Resources\\ResourceResource';
/**
* The resource model class.
*
* @var string
*/
private $resourceModelClass;
/**
* The repository.
*
* @var \App\Repositories\ResourceRepository
*/
private $repository;
/**
* ResourceController constructor.
*
* @param \Illuminate\Http\Request $request
* @return void
*/
public function __construct(Request $request)
{
$this->resourceModelClass = $this->getResourceModelClass($request);
$this->repository = new ResourceRepository($this->resourceModelClass);
$exploded = explode('\\', $this->resourceModelClass);
$resourceModelClassName = array_last($exploded);
if (!empty($resourceModelClassName)) {
$resourceClass = '\\App\\Http\\Resources\\' . $resourceModelClassName . 'Resource';
if (class_exists($resourceClass)) {
$this->resourceClass = $resourceClass;
}
}
}
...
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request, $this->getResourceModelRules());
$resource = $this->repository->create($request->all());
$resource = new $this->resourceClass($resource);
return response()->json($resource);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$resource = $this->repository->show($id);
$resource = new $this->resourceClass($resource);
return response()->json($resource);
}
...
/**
* Get the model class of the specified resource.
*
* @param \Illuminate\Http\Request $request
* @return string
*/
private function getResourceModelClass(Request $request)
{
if (is_null($request->route())) return '';
$uri = $request->route()->uri;
$exploded = explode('/', $uri);
$class = str_singular($exploded[1]);
return '\\App\\Models\\' . ucfirst($class);
}
/**
* Get the model rules of the specified resource.
*
* @param \Illuminate\Http\Request $request
* @return string
*/
private function getResourceModelRules()
{
$rules = [];
if (method_exists($this->resourceModelClass, 'rules')) {
$rules = $this->resourceModelClass::rules();
}
return $rules;
}
}
您可能会说我们没有使用模型路由绑定,而是使用存储库来执行我们的逻辑。
您还可以看到,我们使用一些脏逻辑getResourceModelClass() 来确定执行逻辑所需的模型类。这种方法不是很灵活,并且限制了应用程序的目录结构(非常讨厌)。
解决方案可能是在注册路由时添加有关模型类的一些信息。这可能看起来像:
Route::apiResource('posts', 'ResourceController', [
'modelClass' => Post::class
]);
但是看起来这是不可能的。
是否有人对如何使这项工作或如何使我们的逻辑更加简洁和灵活有任何建议。灵活性和易用性是重要因素。
【问题讨论】:
标签: php laravel rest api routes