1

I have a column in my database which it's json type: values.
But I need to enforce a schema.

  • It must be an array
  • Every object must have 2 and only 2 properties (required). code_name, and description
  • code_name must be unique inside that JSON array

Does Laravel has some out of the box feature for this? or do I need to manually decode the json on create and on update to validate that rules?

Till now. I only have this validation rules in my Model:

/**
 * The model validation rules.
 *
 * @var array
 */
public static $rules = [
    'values' => 'required|json', // TO BE CHECKED (values validation (json schema) and setter)
];

But that's not enough.

Important: this is not a duplicate question to: Laravel: validate json object

1
  • I don't believe there is any out-of-the-box validation available for this. Does this blog post help in casting it to an array and to get started on the custom validation required? qcode.in/use-mysql-json-field-in-laravel Commented Jun 30, 2018 at 0:34

1 Answer 1

6

Laravel supports adding your own custom validation rules.

To create a validation rule you should create a new class that implements the interface Illuminate\Contracts\Validation\Rule.

The artisan command php artisan make:rule {NAME} automatically generates a rule template for you in the App\Rules namespace.

Simply put, you write a passes($attribute, $value) function which returns a boolean that determines if the validation fails or succeeds.

I've written an example based on your requirements below.

Example

<?php
namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class ValuesSchemaRule implements Rule
{
    private $validProperties = ['code_name', 'description'];

    public function __construct()
    {
    }

    public function passes($attribute, $value)
    {
        $array = json_decode($value);

        if (is_array($array) === false) {
            return false;
        }

        $codeNames = [];

        foreach ($array as $object) {
            $properties = get_object_vars($object);

            if (count($properties) !== 2) {
                return false;
            }

            $propertyNames = array_keys($properties);

            if (in_array($this->validProperties, $propertyNames) === false) {
                return false;
            }

            array_push($codeNames, $object->code_name);
        }

        if (count($codeNames) !== count(array_unique($codeNames))) {
            return false;
        }

        return true;
    }

    public function message()
    {
        return 'The values does not comply to the JSON schema';
    }
}

To add it to your model validation you should just assign the 'values' property to a new instance of your Rule class:

/**
 * The model validation rules.
 *
 * @var array
 */
public static $rules = [
    'values' => new ValuesSchemaRule,
];
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, excellent response. I hope it will be useful to more people with the same question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.