Giter Club home page Giter Club logo

validation-composite's People

Contributors

klimov-paul avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

validation-composite's Issues

Issue with using `required_with` for nested objects

Hi, I have an issue using composite rules.

Namely, I'm accepting an object with two properties in my form request, and I want to have composite rules for each of the properties.

In order to ensure the structure of the object, I want to use required_with in both composite rules, and that's proven to be highly problematic.

Here's what I need:

Form request:

<?php

namespace App\Http\Requests\Api;

use App\Http\Requests\FormRequest;
use App\Rules\CurrencyPriceAmountRule;
use App\Rules\CurrencyPriceCurrencyRule;

class ExpenseRequest extends FormRequest
{
    public function rules()
    {
        return [
            'total_price' => ['nullable', 'array'],
            'total_price.amount' => CurrencyPriceAmountRule::forPrice('total_price'),
            'total_price.currency' => CurrencyPriceCurrencyRule::forPrice('total_price'),
        ];
    }
}

Composite rule for amount:

<?php

namespace App\Rules;

use Illuminatech\Validation\Composite\CompositeRule;

class CurrencyPriceAmountRule extends CompositeRule
{
    private string $priceObject;

    public static function forPrice(string $priceObjectName): self
    {
        $rule = new self();

        $rule->priceObject = $priceObjectName;

        return $rule;
    }

    protected function rules(): array
    {
        return [
            "required_with:{$this->priceObject}",
            'numeric',
        ];
    }
}

Composite rule for currency:

<?php

namespace App\Rules;

use Illuminatech\Validation\Composite\CompositeRule;

class CurrencyPriceCurrencyRule extends CompositeRule
{
    private string $priceObject;

    public static function forPrice(string $priceObjectName): self
    {
        $rule = new self();

        $rule->priceObject = $priceObjectName;

        return $rule;
    }

    protected function rules(): array
    {
        return [
            "required_with:{$this->priceObject}",
            "string",
            "size:3",
        ];
    }
}

And everything's working well when there is valid input, however when there is no total_price field in the input validation fails. If total_price.amount were present without total_price.currency, or vice versa, validation should fail. However, if total_price is completely missing validation should not fail.

I've tracked the issue down to this line:

Arr::set($data, $attribute, $value); // ensure correct validation for array attributes like 'item_ids.*' or 'items.*.id'

What happens is the CompositeRule::passes() method receives total_price.amount as the $attribute argument, and null as the $value argument, and then the Arr::set() invocation creates the following structure for the $data variable:

[
    'total_price' => [
        'amount' => null,
    ],
]

And then validation fails because it detects total_price is present, however total_price.amount is null.

I'd be happy to think about a possible solution and submit a PR, I just want to know that what I'm describing is indeed undesired behaviour and a proper PR would get merged.

Will this work with custom validation rules?

Thanks for the nice-looking package.

I'm just wondering if this package is intended to be used with custom validation rules and form requests. For instance, are you aware if there would be any problem with trying to do this:

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}
class PasswordCompositeRule extends CompositeRule
{
    protected function rules(): array
    {
        return ['string', 'min:8', 'max:200', new Uppercase];
    }
}
use Illuminate\Foundation\Http\FormRequest;

class UserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => ['required', 'min:5', new PasswordCompositeRule],
        ];
    }
}

Additional info

Q A
This Package Version 1.1
Laravel Framework Version 6.0

Composite Rule not working with nested/array fields

What steps will reproduce the problem?

Great package! I just ran into this when trying to validate request data containing array fields.

If you have a set of rules that contain dot notation fields representing array validation the CompositeRule doesn't run, see example:

public function rules() {
    return [
        'enabled' => 'required|boolean',        
        'attributes.url' => ['required', new SecureUrl], // Composite seems to get skipped
        'attributes.tags.*' => ['required', new TagsAllowed], // Composite seems to get skipped
        // Wildcards can be anywhere in the key 'person.*.email'
    ];
}

What is the expected result?

CompositeRule validation is executed.

What do you get instead?

Validation rules seem to be skipped.

Solution?

In the below code from the passes method the [$attribute => $value] part I think is the issue as the attribute/data structure may need to be converted to the correct array structure.

/** CompositeRule::passes... */

$validator = $this->getValidatorFactory()->make([$attribute => $value], [
    $attribute => $this->rules(),
]);

Laravel must handle this translation from dot notation to array somewhere in their validation code. So I assume the solution is out there.

You can transform the dot notation field to an array using something like the below:

/** CompositeRule::passes... */

$fields = [];

// Transform attribute to matching array with value
\Arr::set($fields, $attribute, $value);

$validator = $this->getValidatorFactory()->make($fields, [
    $attribute => $this->rules(),
]);

The Arr::set transforms the dot notation to an array.

Additional info

Q A
This Package Version 1.0.0
Laravel Framework Version 5.8.*
PHP version 7.1
Operating system Ubuntu

not sure on this?

why cant we create custom RULES a feature laravel already provides - we can then use these anywhere we want just like urs.

Hability to customize validation messages

Should be possible to specify the error message for each of the rules.

Something like:

<?php

namespace App\Rules;

use Illuminatech\Validation\Composite\CompositeRule;

class PasswordRule extends CompositeRule
{
    protected function rules(): array
    {
        return ['string', 'min:8', 'max:200'];
    }

    protected function messages(): array
    {
        return [
            'string' => 'My custom string message',
            'min' => 'My custom min message',
            'max' => 'My custom max message',
        ];
    }
}

Is there some way to achieve this implemented already? Looking at the code I see no way of passing the custom messages to the validator instance that is used to perform the checks.

Q A
This Package Version 1.1.0
Laravel Framework Version 6.11.0
PHP version 7.4
Operating system Ubuntu 19.10

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.