How to validate model object instance in Laravel?

I’ve got the following model:

<?php
namespace App;
use IlluminateDatabaseEloquentModel;

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'
        ];
    }
}

And there’s a controller ProductController that has an action 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 IlluminateValidationFactory::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 AppProduct 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

It seems pretty clear there’s something wrong with the following line:
$validator = Validator::make($product, Product::rules());
The simplest cause I can think of, is that the validator simply does not accept objects and only wants arrays.
If not, what could be the problem?
If Laravel’s validation only works with arrays, is it somehow possible to validate an object?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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

the problem is not Product::rules() but $product. Product::rules() is correct because it’s return an array, but $product is an object instead of an array. You should change/convert $product to an array an example:

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

Method 2

Yes! You’re right. If we look at the make method, we can see that it accepts rules as an array.

     * @param array $data
     * @param array $rules
     * @param array $messages
     * @param array $customAttributes
     * @return IlluminateValidationValidator 
     * @static 
     */ 
    public static function make($data, $rules, $messages = [], $customAttributes = [])
    {
                    /** @var IlluminateValidationFactory $instance */
                    return $instance->make($data, $rules, $messages, $customAttributes);
    }

I usually validate data directly in the controller

    $validator = Validator::make($info, [
        'shortDescription' => 'required',
        'description' => 'required',
        'countryId' => 'required',
        'cities' => 'required | array | min:1',
    ]);

Method 3

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()
    {
    }
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x