【问题标题】:How to validate model object instance in Laravel?如何在 Laravel 中验证模型对象实例?
【发布时间】:2021-07-15 23:55:28
【问题描述】:

我有以下型号:

<?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 的验证仅适用于数组,是否可以通过某种方式验证 object

【问题讨论】:

  • 错误信息是什么?

标签: php laravel validation frameworks typeerror


【解决方案1】:

是的!你说得对。如果我们查看 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',
    ]);

【讨论】:

  • 你说它接受 rules 作为数组(我知道),但我的问题是关于要验证的实际数据。不是规则,而是数据。在我的情况下,该数据是一个对象,我想知道是否有可能以某种方式验证一个对象实例。
【解决方案2】:
    validator = Validator::make($product, Product::rules());

问题不是Product::rules(),而是$productProduct::rules() 是正确的,因为它返回一个数组,但 $product 是一个对象而不是数组。您应该将 $product 更改/转换为数组示例:

    validator = Validator::make((array)$product, Product::rules());

【讨论】:

  • 框架中没有任何东西可以让我直接验证对象吗? (例如,如果框架在内部动态访问对象属性,就像它如何验证关联数据数组一样)。否则,您的答案似乎是唯一的解决方案。
  • @user2190492 您不能直接验证对象,除非您创建自己的验证库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
  • 2013-08-27
  • 1970-01-01
相关资源
最近更新 更多