我正在做一个项目,在这个项目中我使用 Spatie 的 laravel-data 包 (https://spatie.be/docs/laravel-data/v2/introduction) 来管理数据传输对象 (DTO)。我有一些 DTO 目前工作正常,直到我遇到这个我面临 2 个问题:
1 到目前为止,我已经能够在我的控制器中使用 DTO 作为参数,并且请求已正确转换为 DTO,例如:
public function store(ProductData $data) : ProductsResource
{
$product = UpsertProductAction::execute($data);
return new ProductsResource($product->load('category'));
}
现在我有一个客户实体的自定义路由。路线定义如下:
Route::post('customers/individuals', [ CustomersController::class, 'addIndividual' ]);
我控制器中的
addIndividual
方法是:
public function addIndividual(IndividualData $data)
{
echo "here";
print_r($data);
dd("watup");
}
但是当我从我的 REST 客户端访问路由时,我什么也得不到。调试时它似乎没有击中控制器。我收到 200 OK 响应和 Laravel 的主页,仅此而已。
但是如果我修改我的方法是:
public function addIndividual(Request $request)
{
$data = IndividualData::from($request->all());
dd($data);
}
现在我看到
dd
被击中了。
这是怎么回事?
这是我的数据类:
<?php
namespace Domain\Customer\DataTransferObjects;
use Illuminate\Validation\Rule;
use Spatie\LaravelData\Data;
class IndividualData extends Data
{
public function __construct(
public readonly ?string $id,
public readonly string $identification,
public readonly string $identification_type,
public readonly string $first_name,
public readonly ?string $middle_name,
public readonly string $last_name,
public readonly ?string $second_last_name,
public readonly ?string $primary_phone_number,
public readonly ?string $primary_phone_number_type,
) {}
public static function rules() : array
{
return [
'identification' => [
'required',
'string',
],
'identification_type' => [
'required',
'string',
],
'first_name' => [
'required',
'string',
],
'middle_name' => [
'string',
'nullable',
'sometimes'
],
'last_name' => [
'required',
'string',
],
'second_last_name' => [
'string',
'nullable',
'sometimes'
],
'primary_phone_number' => [
'string',
'nullable',
'sometimes'
],
'primary_phone_number_type' => [
'string',
'nullable',
'sometimes'
],
];
}
}
2 第二个问题与第一个问题相关。所以用以前的方法,比如
public function store(ProductData $data) : ProductsResource
{
$product = UpsertProductAction::execute($data);
return new ProductsResource($product->load('category'));
}
如果有一些数据在
ProductData
中按要求声明但未通过,那么我会得到一个很好的错误,如:
{
"message": "The barcode field is required. (and 1 more error)",
"errors": {
"barcode": [
"The barcode field is required."
],
"name": [
"The name has already been taken."
]
}
}
但是现在,如果我简单地使用请求并将其注入数据对象:
$data = IndividualData::from($request->all());
并且请求中缺少必需的数据然后我收到 500 错误消息,例如:
Could not create `Domain\Customer\DataTransferObjects\IndividualData`: the constructor requires 9 parameters, 8 given.Parameters given: id, identification_type, first_name, middle_name, last_name, second_last_name, primary_phone_number, primary_phone_number_type.
如果我在
try/catch
声明中注入创建 DTO 的请求:
try {
$data = IndividualData::from($request->all());
$dto = $data;
$customer = UpsertCustomerAction::execute($data);
} catch (\Exception $exception) {
return $exception;
}
然后我得到:
参数计数错误: 域\客户\DataTransferObjects\IndividualData::__construct(): 参数 #2 ($identification) 未传入 /Users/hansgruber/Desktop/webdev/projects/dundermifflin-be/src/Domain/Customer/DataTransferObjects/IndividualData.php:10 堆栈跟踪:#0 /Users/hansgruber/Desktop/webdev/projects/dundermifflin-be/vendor/spatie/laravel-data/src/Resolvers/DataFromArrayResolver.php(57): Domain\Customer\DataTransferObjects\IndividualData->__construct(NULL, NULL,'CC','Inigo',NULL,'Montoya','Arias','6464654635','cel')#1 /Users/hansgruber/Desktop/webdev/projects/dundermifflin-be/vendor/spatie/laravel-data/src/Resolvers/DataFromArrayResolver.php(38): Spatie\LaravelData\Resolvers\DataFromArrayResolver->createData(对象(Spatie\LaravelData\Support\DataClass), 对象(照明\支持\集合))#2 /Users/hansgruber/Desktop/webdev/projects/dundermifflin-be/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(731): Spatie\LaravelData\Resolvers\DataFromArrayResolver->Spatie\LaravelData\Resolvers{闭包}(对象(照明\支持\集合)) #3 /Users/hansgruber/Desktop/webdev/projects/dundermifflin-be/vendor/spatie/laravel-data/src/Resolvers/DataFromArrayResolver.php(38): Illuminate\Support\Collection->pipe(Object(Closure))#4 /Users/hansgruber/Desktop/webdev/projects/dundermifflin-be/vendor/spatie/laravel-data/src/Resolvers/DataFromSomethingResolver.php(45): Spatie\LaravelData\Resolvers\DataFromArrayResolver->execute('Domain\Customer...', 对象(照明\支持\集合))#5
为什么我不再收到格式正确的错误?
谢谢。
花了几个小时四处寻找这个问题!事实证明,我的 REST 客户端的请求中没有设置以下标头:
Accept: application/json
最糟糕的是,我所有的其他请求都有它,但其中大部分是具有标题的请求的修改副本,我手动创建了失败的请求,原因是我忘记了它