如何验证 Laravel 中的模型对象实例?
How to validate model object instance in Laravel?
我有以下型号:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $guarded = ['id'];
public static function rules()
{
return [
'created_at' => 'nullable',
'updated_at' => 'nullable',
'name' => 'required|string|between:1,255',
'description' => 'required|string|between:1,255',
'date_added' => 'nullable',
'date_edited' => 'nullable',
'unit' => 'required|string|between:1,255',
'unit_type' => 'required|integer',
'stock' => 'nullable|string|between:0,255',
'barcode' => 'nullable|string|between:0,32',
'tax' => 'nullable|float',
'price' => 'nullable|float',
'category_id' => 'required|integer|gt:0'
];
}
}
还有一个控制器 ProductController
有一个动作 insertProduct
。
class class ProductController extends ApiController { // controller class
public function insertProduct(Request $request) {
$inputJson = $request->input('data_json', null);
if(empty($inputJson)) {
$inputJson = $request->getContent();
if(empty($inputJson)) {
return $this->errorResponse(
'Either data_json formdata parameter or request body should contain a JSON string.'
);
}
}
try {
$product = $this->extractProductFromJSON($inputJson);
} catch(\Exception $e) {
return $this->errorResponse($e->getMessage(), 400);
}
// When I dump the Product ($product) instance using dd(), it is just as expected and its
// properties contain the right values.
$validator = Validator::make($product, Product::rules());
/* Above line causes exception:
TypeError: Argument 1 passed to Illuminate\Validation\Factory::make() must be of the type
array, object given,
called in /.../vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php
on line 261 in file /.../vendor/laravel/framework/src/Illuminate/Validation/Factory.php
on line 98
*/
if($validator->fails()) {
return $this->errorResponse($validator->errors()->first());
}
// ...
}
// How I extract the data from the JSON string (which is input).
// Although I don't think this has anything to do with my problem.
private function extractProductFromJSON(string $json) {
$data = \json_decode($json);
if(\json_last_error() != JSON_ERROR_NONE) {
throw new \Exception('Error parsing JSON: ' . \json_last_error_msg());
}
try {
$productData = $data->product;
$productId = empty($productData->id) ? null : $productData->id;
// Product id is allowed to be absent
$product = new Product(); // My \App\Product model instance.
$product->id = $productId;
$product->name = $productData->name;
$product->description = $productData->description;
$product->date_added = $productData->date_added;
$product->date_edited = $productData->date_edited;
$product->unit = $productData->unit;
$product->unit_type = $productData->unit_type;
$product->stock = $productData->stock;
$product->barcode = $productData->barcode;
$product->tax = $productData->tax;
$product->price = $productData->price;
$product->category_id = $productData->category_id;
return $product;
} catch(\Exception $e) {
echo 'EXCEPTION...';
}
}
} // end of controller class
很明显下面一行有问题:
$validator = Validator::make($product, Product::rules());
我能想到的最简单的原因是验证器根本不接受对象而只需要数组。
如果不是,可能是什么问题?
如果 Laravel 的验证仅适用于数组,是否有可能以某种方式验证 对象 ?
是的!你是对的。如果我们查看 make 方法,我们可以看到它接受规则作为数组。
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return \Illuminate\Validation\Validator
* @static
*/
public static function make($data, $rules, $messages = [], $customAttributes = [])
{
/** @var \Illuminate\Validation\Factory $instance */
return $instance->make($data, $rules, $messages, $customAttributes);
}
我通常直接在控制器中验证数据
$validator = Validator::make($info, [
'shortDescription' => 'required',
'description' => 'required',
'countryId' => 'required',
'cities' => 'required | array | min:1',
]);
validator = Validator::make($product, Product::rules());
问题不是 Product::rules()
,而是 $product
。 Product::rules()
是正确的,因为它是 return 一个数组,但是 $product
是一个对象而不是数组。你应该 change/convert $product
给一个数组一个例子:
validator = Validator::make((array)$product, Product::rules());
class Cliente extends Eloquent
{
public static $autoValidates = true;
protected static $rules = [];
protected static function boot()
{
parent::boot();
// or static::creating, or static::updating
static::saving(function($model)
{
if ($model::$autoValidates) {
return $model->validate();
}
});
}
public function validate()
{
}
}
我有以下型号:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $guarded = ['id'];
public static function rules()
{
return [
'created_at' => 'nullable',
'updated_at' => 'nullable',
'name' => 'required|string|between:1,255',
'description' => 'required|string|between:1,255',
'date_added' => 'nullable',
'date_edited' => 'nullable',
'unit' => 'required|string|between:1,255',
'unit_type' => 'required|integer',
'stock' => 'nullable|string|between:0,255',
'barcode' => 'nullable|string|between:0,32',
'tax' => 'nullable|float',
'price' => 'nullable|float',
'category_id' => 'required|integer|gt:0'
];
}
}
还有一个控制器 ProductController
有一个动作 insertProduct
。
class class ProductController extends ApiController { // controller class
public function insertProduct(Request $request) {
$inputJson = $request->input('data_json', null);
if(empty($inputJson)) {
$inputJson = $request->getContent();
if(empty($inputJson)) {
return $this->errorResponse(
'Either data_json formdata parameter or request body should contain a JSON string.'
);
}
}
try {
$product = $this->extractProductFromJSON($inputJson);
} catch(\Exception $e) {
return $this->errorResponse($e->getMessage(), 400);
}
// When I dump the Product ($product) instance using dd(), it is just as expected and its
// properties contain the right values.
$validator = Validator::make($product, Product::rules());
/* Above line causes exception:
TypeError: Argument 1 passed to Illuminate\Validation\Factory::make() must be of the type
array, object given,
called in /.../vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php
on line 261 in file /.../vendor/laravel/framework/src/Illuminate/Validation/Factory.php
on line 98
*/
if($validator->fails()) {
return $this->errorResponse($validator->errors()->first());
}
// ...
}
// How I extract the data from the JSON string (which is input).
// Although I don't think this has anything to do with my problem.
private function extractProductFromJSON(string $json) {
$data = \json_decode($json);
if(\json_last_error() != JSON_ERROR_NONE) {
throw new \Exception('Error parsing JSON: ' . \json_last_error_msg());
}
try {
$productData = $data->product;
$productId = empty($productData->id) ? null : $productData->id;
// Product id is allowed to be absent
$product = new Product(); // My \App\Product model instance.
$product->id = $productId;
$product->name = $productData->name;
$product->description = $productData->description;
$product->date_added = $productData->date_added;
$product->date_edited = $productData->date_edited;
$product->unit = $productData->unit;
$product->unit_type = $productData->unit_type;
$product->stock = $productData->stock;
$product->barcode = $productData->barcode;
$product->tax = $productData->tax;
$product->price = $productData->price;
$product->category_id = $productData->category_id;
return $product;
} catch(\Exception $e) {
echo 'EXCEPTION...';
}
}
} // end of controller class
很明显下面一行有问题:
$validator = Validator::make($product, Product::rules());
我能想到的最简单的原因是验证器根本不接受对象而只需要数组。
如果不是,可能是什么问题?
如果 Laravel 的验证仅适用于数组,是否有可能以某种方式验证 对象 ?
是的!你是对的。如果我们查看 make 方法,我们可以看到它接受规则作为数组。
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
* @return \Illuminate\Validation\Validator
* @static
*/
public static function make($data, $rules, $messages = [], $customAttributes = [])
{
/** @var \Illuminate\Validation\Factory $instance */
return $instance->make($data, $rules, $messages, $customAttributes);
}
我通常直接在控制器中验证数据
$validator = Validator::make($info, [
'shortDescription' => 'required',
'description' => 'required',
'countryId' => 'required',
'cities' => 'required | array | min:1',
]);
validator = Validator::make($product, Product::rules());
问题不是 Product::rules()
,而是 $product
。 Product::rules()
是正确的,因为它是 return 一个数组,但是 $product
是一个对象而不是数组。你应该 change/convert $product
给一个数组一个例子:
validator = Validator::make((array)$product, Product::rules());
class Cliente extends Eloquent
{
public static $autoValidates = true;
protected static $rules = [];
protected static function boot()
{
parent::boot();
// or static::creating, or static::updating
static::saving(function($model)
{
if ($model::$autoValidates) {
return $model->validate();
}
});
}
public function validate()
{
}
}