GithubHelp home page GithubHelp logo

validating's Introduction

Validating, a validation trait for Laravel

Build Status Total Downloads Latest Stable Version Latest Unstable Version License

Validating is a trait for Laravel Eloquent models which ensures that models meet their validation criteria before being saved. If they are not considered valid the model will not be saved and the validation errors will be made available.

Validating allows for multiple rulesets, injecting the model ID into unique validation rules and raising exceptions on failed validations. It's small and flexible to fit right into your workflow and help you save valid data only.

Laravel 4.2+

Looking to use Validating on Laravel 4.2+? Take a look at the 0.10.x branch for documentation and installation instructions.

The Laravel 4.2 version is better suited to doing form validation; it supports custom validation messages, confirmation rules and multiple rulesets. Because Laravel 5.0 has FormRequest validation Validating is now designed to keep your core data valid and leave form validation to the framework.

Laravel 5.0 - 5.2

Looking to use Validating on Laravel 5.0 to 5.2? Take a look at the 2.x branch for documentation and installation instructions.

The Laravel 5.0 - 5.2 version used a since-deprecated ValidationException contract from the Laravel framework. For Laravel 5.3 we now extend the core validation ValidationException which means the framework will automatically redirect back with errors when a validation error occurs, much like a FormRequest would.

Laravel 5.3+

Just read on - these instructions are for you!

Installation

Simply go to your project directory where the composer.json file is located and type:

composer require watson/validating

View installation instructions for Laravel 4.2+. View installation instructions for Laravel 5.0 - 5.2.

Overview

First, add the trait to your model and add your validation rules and messages as needed.

use Watson\Validating\ValidatingTrait;

class Post extends Eloquent
{
	use ValidatingTrait;

	protected $rules = [
		'title'   => 'required',
		'slug'    => 'required|unique:posts,slug',
		'content' => 'required'
	];
}

You can also add the trait to a BaseModel if you're using one and it will work on all models that extend from it, otherwise you can just extend Watson\Validating\ValidatingModel instead of Eloquent.

Note: you will need to set the $rules property on any models that extend from a BaseModel that uses the trait, or otherwise set an empty array as the $rules for the BaseModel. If you do not, you will inevitably end up with LogicException with message 'Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation'.

Now, you have access to some pleasant functionality.

// Check whether the model is valid or not.
$post->isValid(); // true

// Or check if it is invalid or not.
$post->isInvalid(); // false

// Once you've determined the validity of the model,
// you can get the errors.
$post->getErrors(); // errors MessageBag

Model validation also becomes really simple.

if ( ! $post->save()) {
    // Oops.
    return redirect()->route('posts.create')
        ->withErrors($post->getErrors())
        ->withInput();
}

return redirect()->route('posts.show', $post->id)
    ->withSuccess("Your post was saved successfully.");

Otherwise, if you prefer to use exceptions when validating models you can use the saveOrFail() method. Now, an exception will be raised when you attempt to save an invalid model.

$post->saveOrFail();

You don't need to catch the exception, if you don't want to. Laravel knows how to handle a ValidationException and will automatically redirect back with form input and errors. If you want to handle it yourself though you may.

try {
    $post->saveOrFail();

} catch (Watson\Validating\ValidationException $e) {
    $errors = $e->getErrors();

    return redirect()->route('posts.create')
        ->withErrors($errors)
        ->withInput();
}

Note that you can just pass the exception to the withErrors() method like withErrors($e) and Laravel will know how to handle it.

Bypass validation

If you're using the model and you wish to perform a save that bypasses validation you can. This will return the same result as if you called save() on a model without the trait.

$post->forceSave();

Validation exceptions by default

If you would prefer to have exceptions thrown by default when using the save() method instead of having to use saveOrFail() you can just set the following property on your model or BaseModel.

/**
 * Whether the model should throw a ValidationException if it
 * fails validation. If not set, it will default to false.
 *
 * @var boolean
 */
protected $throwValidationExceptions = true;

If you'd like to perform a one-off save using exceptions or return values, you can use the saveOrFail() and saveOrReturn methods.

Validation messages

To show custom validation error messages, just add the $validationMessages property to your model.

/**
 * Validation messages to be passed to the validator.
 *
 * @var array
 */
protected $validationMessages = [
    'slug.unique' => "Another post is using that slug already."
];

Unique rules

You may have noticed we're using the unique rule on the slug, which wouldn't work if we were updating a persisted model. Luckily, Validation will take care of this for you and append the model's primary key to the rule so that the rule will work as expected; ignoring the current model.

You can adjust this functionality by setting the $injectUniqueIdentifier property on your model.

/**
 * Whether the model should inject it's identifier to the unique
 * validation rules before attempting validation. If this property
 * is not set in the model it will default to true.
 *
 * @var boolean
 */
protected $injectUniqueIdentifier = true;

Out of the box, we support the Laravel provided unique rule. We also support the popular felixkiss/uniquewith-validator rule, but you'll need to opt-in. Just add use \Watson\Validating\Injectors\UniqueWithInjector after you've imported the validating trait.

It's easy to support additional injection rules too, if you like. Say you wanted to support an additional rule you've got called unique_ids which simply takes the model's primary key (for whatever reason). You just need to add a camel-cased rule which accepts any existing parameters and the field name, and returns the replacement rule.

/**
 * Prepare a unique_ids rule, adding a model identifier if required.
 *
 * @param  array  $parameters
 * @param  string $field
 * @return string
 */
protected function prepareUniqueIdsRule($parameters, $field)
{
    // Only perform a replacement if the model has been persisted.
    if ($this->exists) {
        return 'unique_ids:' . $this->getKey();
    }

    return 'unique_ids';
}

In this case if the model has been saved and has a primary key of 10, the rule unique_ids will be replaced with unique_ids:10.

Events

Various events are fired by the trait during the validation process which you can hook into to impact the validation process.

To hook in, you first need to add the $observeables property onto your model (or base model). This simply lets Eloquent know that your model can respond to these events.

/**
 * User exposed observable events
 *
 * @var array
 */
protected $observables = ['validating', 'validated'];

When validation is about to occur, the eloquent.validating: ModelName event will be fired, where the $event parameter will be saving or restoring. For example, if you were updating a namespaced model App\User the event would be eloquent.validating: App\User. If you listen for any of these events and return a value you can prevent validation from occurring completely.

Event::listen('eloquent.validating:*', function($model, $event) {
    // Pseudo-Russian roulette validation.
    if (rand(1, 6) === 1) {
        return false;
    }
});

After validation occurs, there are also a range of validated events you can hook into, for the passed, failed and skipped events. For the above example failing validation, you could get the event eloquent.validated: App\User.

Testing

There is currently a bug in Laravel (see issue #1181) that prevents model events from firing more than once in a test suite. This means that the first test that uses model tests will pass but any subseqeuent tests will fail. There are a couple of temporary solutions listed in that thread which you can use to make your tests pass in the meantime.

Since Laravel has switched to Liferaft for the purpose of tracking bugs and pull requests, the issue mentioned above may not be available. This Gist has an example TestCase.php which shows you how to reset the events of all your models between tests so that they work as expected.

Controller usage

There are a number of ways you can go about using the validating validating model in your controllers, however here is one example that makes use of the new FormRequest in Laravel 5 (if you'd like to see another controller example without the FormRequest, check the 4.2+ version of this package.

This example keeps your code clean by allowing the FormRequest to handle your form validation and the model to handle its own validation. By enabling validation exceptions you can reduce repetitive controller code (try/catch blocks) and handle model validation exceptions globally (your form requests should keep your models valid, so if your model becomes invalid it's an exceptional event).

<?php namespace App\Http\Controllers;

use App\Http\Requests\PostFormRequest;
use Illuminate\Routing\Controller;

class PostsController extends Controller
{
    protected $post;

    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    // ...

    public function store(PostFormRequest $request)
    {
        // Post will throw an exception if it is not valid.
        $post = $this->post->create($request->input());

        // Post was saved successfully.
        return redirect()->route('posts.show', $post);
    }
}

You can then catch a model validation exception in your app/Exceptions/Handler.php and deal with it as you need.

public function render($request, Exception $e)
{
    if ($e instanceof \Watson\Validating\ValidationException) {
        return back()->withErrors($e)->withInput();
    }

    parent::render($request, $e);
}

validating's People

Contributors

ajohnson6494 avatar barryvdh avatar danielgsoftware avatar danydev avatar dwightwatson avatar dylan-dpc avatar erickcomp avatar gazugafan avatar gregpeden avatar illovativ avatar jatubio avatar jbrooksuk avatar jordanlev avatar jwohlfert23 avatar likemusic avatar lucasmichot avatar maiorano84 avatar morphatic avatar nyholm avatar omranic avatar pjona avatar propaganistas avatar ricardogobbosouza avatar ricardovigatti avatar samnela avatar snipe avatar sp4r74cus avatar spencerrlongg avatar tobz-nz avatar vinkla 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

validating's Issues

Password Confirmed Not Matching

Passwords are always fickle, especially when working with hashed passwords.

I am hashing my password using the following in my Users model:

    public function setPasswordAttribute($password)
    {
        $this->attributes['password'] = Hash::make($password);
    }

When I validate using the following ruleset:

    protected $fillable = [
        'email',
        'password'
    ];

    protected $rules = [
        'creating' => [
            'email' => 'required|email|unique:users,email',
            'password' => 'required|confirmed'
        ]
    ];

I always get passwords don't match. I assume this is because of two things:

  1. The password_confirmation field is not saved in the model.
  2. The password is already hashed before the validation begins.

Soooo, the big question is: how do you recommend dealing with password validation? :) Thanks!

Switch to using exceptions by default

It seems like most are interested in exceptions as a model failing validation is an "exceptional" event, so I will move to making exceptions the default behaviour. You will still be able to use the current "return boolean" mechanism either through a configuration option, custom save function or another method.

Can we get a method to set attribute names?

The validation class has a method "setAttributeNames" where an array can be passed in with nice names for each of the attributes.

It would be great if there was a hook or some place we could set that.

Preferably, we could set a property in the model, say
public $attributeNames = [
'f_name' => "First Name",
]

And the validator would simply check if that exists, if it does, send it to setAttributeNames.

Deprecate isInvalidOrFail()

The method isInvalidOrFail() https://github.com/dwightwatson/validating/blob/master/src/ValidatingTrait.php#L292-L308 doesn't serve much purpose and only leads to confusing language when the exception is actually thrown. Using it would be like saying "Make sure this model is invalid otherwise tell the developer that the valid model is not valid." It is one thing to see if a model is not valid but it's another thing to throw an exception when it is valid but the expectation was that it was not valid.

It doesn't make much sense so I recommend deprecating it so it doesn't become common place to have double negatives throughout code.

Handling Multiple Forms on a Single Page

I've been thinking this should be possible through some simple additions:

  • If the validated form has a name, create a bucket for the form using the form's name, and use that as the message bucket in addition to adding all messages in the general bucket (for when the user has a form name, but doesn't use the named message bucket).

This way one could access the errors for their form via something like:

$errors->myFormName->first('fieldName', '<span class="help-block col-sm-4">:message</span>');

as well as the traditional route.
(See "Named Error Bag" in this section: http://laravel.com/docs/validation#error-messages-and-views).

Or has this already been implemented? (I assumed not, since it wasn't documented.)
Thoughts?

With Error and With Input not working in My Modules

Hi this is not working when i used inside my module

i used this for my modules https://github.com/pingpong-labs/modules

this is error message when i try

try
{
$item->saveOrFail();
}
catch (Watson\Validating\ValidationException $e)
{
$errors = $e->getErrors();
return Redirect::back()
->withErrors($errors)
->withInput();
}
Modules\Master\Models\Item model could not be persisted as it failed validation

it's working fine when i used

if ( ! $item->save())
{
return \Redirect::back()
->withErrors($item->getErrors())
->withInput();
} 

but error message and input not show up in my form

Unit tests and docs

Until this issue is resolved (either by better docs on the Laravel site, or an actual solution) - might be a good idea to make a mention of this in the README to save headaches for future testers?

laravel/framework#1181

Unique rules with additional WHERE clauses

I think additional WHERE clauses in uniqueness rules break validation on existing models.

I have a rule set like this:

protected $rules = [
    'code' => [
        'unique' => 'users,code,NULL,id,deleted_at,NULL'
    ]
];

With that, creating new items works, but updating them results in an error, so it seems the current item's ID is not being inserted correctly.

If I remove the last four parameters from that, like so:

protected $rules = [
    'code' => [
        'unique' => 'users,code'
    ]
];

...everything seems to work, but obviously now its not excluding soft-deleted models from the check, so if I try to re-use a code value I get an error.

isValid() does not throw ValidationException

Is the above description correct in 0.9.0? I run the isValid function on models that don't meet the criteria, and no exception is thrown, instead it returns a boolean, in this case false, which is expected.

What call can I make that does trigger validationexception without saving?

Sorry I'm having so many issues getting things in place, for some reason I keep bumping into edge cases. :)

When using `saving` ruleset get an error

Error message

object(Illuminate\Support\MessageBag)[331]  protected 'messages' =>     array (size=1)      'saving' =>         array (size=1)          0 => string 'The saving field is required.' (length=29)  protected 'format' => string ':message' (length=8)

My model

<?php

use \Watson\Validating\ValidatingTrait;

class AccountRole extends Eloquent {

    use ValidatingTrait;

    protected $table = 'account_roles';

    protected $rules = [
        'saving' => [
            'name' => 'required'
        ]
    ];

    protected $fillable = ['name', 'description', 'user_id'];

}

error messages comes out as json object

Hi

When validating an invalid form submit the errors produced by

return Redirect::route('users.create')
                ->with('danger', $user->getErrors())
                ->withInput();

gives me the following error:

{"username":["Username is required"],"password_confirmation":["Confirmation password is required"],"email":["Email is required"],"first_name":["First name is required"],"last_name":["Last name is required"]}

Here is my User Model:

use Toddish\Verify\Models\User as VerifyUser;
use Watson\Validating\ValidatingTrait;

class User extends VerifyUser
{
    use ValidatingTrait;

    protected $injectUniqueIdentifier = true;

    protected $rules = array(
        'username' => 'required|alpha_dash|unique|max:30',
        'password' => 'required|max:60',
        'password_confirmation' => 'required|confirmed',
        'email' => 'required|email|unique|max:255',
        'first_name' => 'required|max:50',
        'last_name' => 'required|max:50',
        'phone' => 'min:4|max:20',
    );

    protected $messages = array(
        'username.required' => 'Username is required',
        'username.alpha_dash' => 'Username can only contain letters and dashes',
        'username.unique' => 'Username is already in use',
        'password.required' => 'Password is required',
        'password_confirmation.required' => 'Confirmation password is required',
        'email.required' => 'Email is required',
        'email.email' => 'Email has a wrong format',
        'email.unique' => 'Email is already in use',
        'first_name.required' => 'First name is required',
        'last_name.required' => 'Last name is required',
    );
}

Validation Not Triggered

I'm not exactly sure what I'm doing wrong here, but for some reason I can't get it to validate as described in the documentation; it doesn't seem to trigger validation on save. Here is my code, using 0.8.4:

RolesController.php

use GeneaLabs\Role;

class RolesController extends \BaseController
{
    private $role;

    public function __construct(Role $role)
    {
        $this->role = $role;
    }

    public function store()
    {
        $role = $this->role->fill(Input::only('name', 'description'));
        $role->save();

        return Redirect::route('roles.index');
    }
}

BaseModel.php

namespace GeneaLabs;

use Watson\Validating\ValidatingModel;

class BaseModel extends ValidatingModel
{

}

Role.php

namespace GeneaLabs;

class Role extends BaseModel
{
    protected $rules = [
        'saving' => [
            'name' => 'required|min:3|unique:roles,name',
            'description' => 'required|min:10',
        ],
    ];

    protected $fillable = [
        'name',
        'description',
    ];

    public function users()
    {
        return $this->belongsToMany('GeneaLabs\User');
    }

    public function permissions()
    {
        return $this->belongsToMany('GeneaLabs\Permission');
    }
}

global.php:

App::error(function(ValidationException $exception, $code) {
    Flash::warning('Form validation failed');
    return Redirect::back()->withErrors($exception->getErrors())->withInput();
});

Update: did some more testing, and I can't get it to validate using ->isValid() either. Also tried using the trait directly on the model to see if that would make a difference, but no. :(

attributes nice names

Hey

I think it will be useful if we would be able to add nice names for some attributes.
Laravel has a function to do that
setAttributeNames on a Validator instance
I'm thinking if we can define in the model something like:

protected $validationAttributes = [
    'attr-name' => 'My Nice Attr Name',
];

Thank you

Optional password validation on updating

First of all thank you very much for this amazing package =)

I have a User Model that extends the esensi/model model, but since this is a validation issue I am posting it here. My current rules are as following:

protected $rulesets = [
        'creating' => [
            'password' => 'required|min:8|confirmed',
        ],
        'updating' => [
            'password' => 'min:8|confirmed',
        ],
        'saving'   => [
            'user_name'             => 'required|alpha_num|unique:users,user_name',
            'password_confirmation' => null
        ]
    ];

Furthermore it uses the hashing feature of esensi/model for 'password' and the purging feature for 'password_confirmation'. The issue that i am facing right now comes, when i want to save the user, for example because i changed some of the other attributes which i didn't specify for simplicity, but i don't want to change the users password.

In other words, I have a user model object which contains the hash of the user password in 'password' and i want to call save on it again. This will lead to 'password' being validated against the updating ruleset. This will of course fail, since 'password_confirmation' isn't set, since i don't want to change the password and therefore the 'confirmed' rule will fail.

What I actually would need to be able to tell the validator is:
Is password a hash? If yes then valid, if no then check for 'min:8|confirmed'

This should be solvable with laravels conditional validation rules but unfortunately these need to be called on the validator object. Therefore i would propose a new array for example named $conditionalRules which can contain the parameters for conditional rules, which will them get added to the validator by the package.

EDIT:
Another possibility i came up with just now would be an option which would only validate changed attributes of the model, in other words validate Model::getDirty instead of Model::getAttributes which is being done currently

static $rules (?)

How about changing this:

public function getRules()
{
    return $this->rules ?: [];
}

to this:

public function getRules()
{
    return self::rules ?: [];
}

And in Model write public static $rules and use them to frontend validation?

getRules should return default saving ruleset?

Hi

Thanks for writing this trait. In my use case, I'm using Former and Twigbridge. And in my view I populate the form and add rules using the function getRules(). And as I'm wanting to only set the password field required on creation (otherwise I use the sometimes validation rule), I've set up a ruleset saving with passwords as "sometimes", and a custom rule of "passwordRequired" with them now required.

So, my issue is this. Shouldn't the getRules method first attempt to return $rules. If that's empty, should it not then attempt to return $rulesets['saving']?

It's super simple to do manually, setting the rules before calling the isValid model, but intuitively to me, reading the docs, if $rules is empty it should return the saving ruleset as that is the default ruleset that the rules should use.

Observer and getModel communication

The only issue I foresee with the recent getModel changes is that when outside of an Eloquent setting, the Observer class will not communicate properly with the class leveraging the trait, as the trait functions are being called on the model directly.

This can be alleviated by possibly using a second set of events fired by the observer for the original class to capture.

Lastly, static::observe(new ValidatingObserver) on line 9 of ValidatingTrait.php will need to change to something along the lines of $this->getModel()::observe(new ValidatingObserver).

This introduces a new conundrum however, since we're in static scope and cannot use $this. Would introducing a boolean argument to the getModel method help with this issue?

public function getModel($static=false){
    return $static ? self : $this; //I do not believe you can return static here
}

If this doesn't generate errors, then $this->getModel(true)::observe(new ValidatingObserver) should work as expected.

UPDATE: The above won't work, as we still can't use $this in static scope. Not sure if self->getModel(true) would work either, as I don't believe there's any instance to call upon. Should getModel be static by default? IE:

public static function getModel(){
    return self;
}

Validating form with extra fields

When creating a new user (first_name, last_name, email, password), I'd like to create a new company from 2 fields on the same from (company_name and company_size), but, since the two fields are not on the User attributes, validating them as required always returns false and the validator says that the fields are required.

Is there a way to have their values when the validator checks other user attributes?

No validation of accessor attributes

I want to know whether something like below is possible or would it need to be added. I have a table with a lot of foreign keys for URL parts. The full URL string is not stored in the table. I use an accessor to build the full URL. It would be nice to have validation on this accessor.

protected $rulesets = [
'creating' => [
'apiurl' => 'url|unique:publishersiteinstallation,apiurihash,NULL,id,deleted_at,NULL',
...
...

protected $appends = array('apiurl');

public function getApiurlAttribute()
{
//Return full url string from url part relationships, scheme, domain, tld, path, file, fragment
}

Unit Testing Models

When creating a unit test on a model that uses the ValidatingTrait, the model saves successfully. Even though I have intentionally left out required fields.

Using the model validation in my app works 100%, but the validation does not work in a unit test.

Error using $throwValidationExceptions property

Using model property to throw an Exception by default

protected $throwValidationExceptions = true;

( I've added this in User model directly )

I get this error:
schermata 2014-07-08 alle 19 30 21

Removing this property and using saveOrFail() method all works fine

Exceptions not thrown despite being default.

I'm trying to setup some exception throwing via model events and have encountered an issue where exceptions are not thrown despite being setup to do so.

I've got a debugger hooked on the performValidation method of the Observer. It catches and I step into isValid. IsValid calls performValidation of the trait object - it passes the ruleset (how do I use the global ruleset here? It defaults to 'saving') and false. The second parameter of performValidation is $throwException which we've just set to false.

line 341 we check that value and then fail to throw and exception.

I'm not sure how the default is set atm given that it's being hardcoded in the isValid method.

Enum validation

Hi,

How are (or how should you) validate enum fields?
I can't seem to find any information in either laravel documentation or even the whole web :)

Thanks in advance,

$post->save() syntax saves invalid model

Hi

Love your work. Not sure if I have stumbled onto something, but for me this approach works ...

$post->isValid(); // true

... and this approach does not

if ( ! $post->save()) ...

I tested this out using the 'alpha' rule and when I entered numbers, $post->isValid() - or my equivalent thereof - returned FALSE (which is good) but $post->save() actually saved the invalid model and returned TRUE.

Hope this is a valid issue.

validating files

I'm having trouble validating uploaded files - I'm not sure if its possible within this context.

The problem is the 'image' rule checks the actual file that's uploaded, however I need to save the filename in the model's attributes - this means the validation will fail because the value is now a string & not the file object.

Any idea how to get around this issue?

unique composition

Hi,

I have a model that in combination of 3 fields it needs to be unique.

for example:

protected $rules = array(
        'week_start' => 'required|date',
        'status' => 'required',
        'project_id' => 'required',
        'user_id' => 'required'
    );

what I need is an object to be unique when week_start, project_id and user_id in combination are unique. Is this possible?

Ignoring validation

Hello. There's my controller code:

$site = new Site;
$site->fill(Input::only('name', 'slug', 'content', 'hidden'));

if(!$site->save())
    return Redirect::action('SitesController@create')
            ->withErrors($site->getErrors())
            ->withInput();

Session::flash('message', 'Strona dodana pomyślnie');
return Redirect::action('SitesController@index');

And there's model:

use Watson\Validating\ValidatingTrait;

class Site extends Eloquent {
    use ValidatingTrait;

    protected $fillable = ['name', 'content', 'slug', 'hidden'];
    protected $rules = [
        'name' => 'required',
        'slug' => 'required|alpha_dash|unique:sites',
        'content' => 'required'
    ];
    protected $messages = [
        'name.required' => 'Musisz podać nazwę strony',
        'slug.required' => 'Musisz podać adres strony',
        'slug.alpha_dash' => 'Adres strony może zawierać tylko litery, cyfry, myślniki i podłogi',
        'slug.unique' => 'Strona z takim adresem już istnieje',
        'content.required' => 'Strona musi mieć treść'
    ];
}

But it always redirects me - $site->save() return true. But why? For example: I don't pass a name field and I type spaces in slug. It redirects me to index.

dd($site->isValid()); // return false if I type values against rules
dd($site->getErrors()); // return null if I type values against rules

Any ideas?

Ability to validate if a relationship is valid

I've got this logical problem I keep running into. I'm sure other people must have the same problem - as it would seem to be a common issue to me - and I've searched around, but I cant seem to find a (good) solution.

Lets say we have a standard one to many relationship - user who has many addresses.

class User extends Eloquent {
    public function addresses()
    {
        return $this->hasMany('Address');
    }
}

class Address extends Eloquent {
    public function user()
    {
        return $this->belongsTo('User');
    }
}

Later on, I have a shipping form where the user has to pick which address_id to use from a dropdown list of all their addresses. This list of addresses is just a list() generated by Eloquent - so technically the only supplied variables to the user are their own.

But how do I validate that the returned selected address_id on the form actually belongs to user as part of my validation?

i.e. what happens if someone 'hacks'/'edits' the html form before posting it back - and changes the address_id to 666. It will then use someone elses address_id who they should not have access to?

I cant just use the exists rule - because the address_id will exist - but that doesnt mean that the relationship is valid.

I think the answer lies possibly with the in:foo,bar... validation rule. The idea would be to be able to do something like this:

'address_id' => 'required|in:{list_of_valid_relationship_ids_here}'

But I'm not sure how to inject that list as part of your validation trait.

isValid returning true when it should return false with ruleset

Using $rules worked fine - however when i changed to $rulesets isValid() is returning true when it should be returning false because of invalid input.

My Model:

<?php
use Watson\Validating\ValidatingTrait;
use Illuminate\Database\Eloquent\SoftDeletingTrait;

class PrintEnquirer extends Eloquent {
  use ValidatingTrait;
  use SoftDeletingTrait;
  protected $fillable = [
    'title',
    'name',
    'email',
    'company_name',
  ];

  protected $rulesets = [
    'deleting' => [
      'name' => '',
      'company_name' => ''
    ],
    'saving' => [
      'name' => 'required',
      'company_name' => 'required',
    ],
  ];

My Controller

<?php

class PrintEnquirersController extends BaseController {
public function update($id)
  {
    $input = array_except(Input::all(), '_method');


      $print_enquirer = $this->print_enquirer->find($id);
      $print_enquirer->fill($input);
      $print_enquirer->save();
      if($print_enquirer->isValid()) 
        return Redirect::route('admin.print-enquirers.index')
        ->with('success', 'Enquirer has been edited.');

    return Redirect::route('admin.print-enquirers.edit', $id)
      ->withInput()
      ->withErrors($print_enquirer->getErrors())
      ->with('message', 'There were validation errors.');
  }

When name is empty save is returning false (and does not save changes) which is good, however, isValid is returning true and redirects me to my index action.

I get the same issue if I use update($input) instead of fill + save.

Am I doing something wrong or is this a bug?

Bypass validation on delete

Is there is a way to bypass all validation on deletion, without having to specify separate rule sets? Something similar to forceSave()?

Purging of _confirmation, and other "_" attributes

Hi,

Love trait, thank! But purging is bit of an issue.

Can someone please help. Seems like the trait doesn't purge _confirmation attributes from the model before saving to the persistence layer.

Any help would be appreciated.

Thanks!

Errors: store (new) works, update (existing) does not

Sorry mate, I may have another one.

The 0.8 release works great with creating new records, but updating existing records ... I think this

if ( ! $post->save())

is working fine - it is not saving if validation fails. However, I think that when it fails a validation it is not sending back an error message.

To test this I used the code I in a store method I have in my controller, which worked fined (so my view should be ok), and pasted it into an update controller. I made one change (so it would find the right record, of course) and ... well ... no error message on Redirect::back().

Then I used some alternate validation I have in place (based on a Laracasts episode) and my validations and errors worked fine. I did this just to test my validators and they seemed to work just fine.

So I thought I should raise this with you. Model code below, and it was the unique validator in particular that I was testing to fail. Again this works fine for store (new), but not for update (existing).

Cheers

<?php

use Illuminate\Database\Eloquent\SoftDeletingTrait;
use Watson\Validating\ValidatingTrait;


class Client extends Eloquent {

    use SoftDeletingTrait;
    use ValidatingTrait;

    protected $throwValidationExceptions = false;
    protected $dates = ['deleted_at'];
    protected $fillable = ['name'];
    protected $rules = ['name' => ['required', 'unique:clients']];

    public function users()
    {
        return $this->hasMany('User');
    }

    public function contracts()
    {
        return $this->hasMany('Contract');
    }

}

Submit Error

i got this error when submit form

exception 'ErrorException' with message 'Missing argument 1 for Illuminate\Http\RedirectResponse::withErrors(), called in /Applications/MAMP/htdocs/admin/app/controllers/UsersController.php on line 50 and defined' in /Applications/MAMP/htdocs/admin/vendor/laravel/framework/src/Illuminate/Http/RedirectResponse.php:118 

my controller

public function store()
    {

        $user = new User;
        $user->username = Input::get('username');
        $user->password = Input::get('password');
        $user->email = Input::get('email');


        if ( ! $user->save())
        {
            // The user did not save due to validation errors.
            return Redirect::route('user.users.create')
            ->withErrors($e)
            ->withInput();
        }

        // Post was saved successfully.
        return Redirect::route('user.users.show', $user->id);

    }

Model

<?php

use Toddish\Verify\Models\User as VerifyUser;
use Laracasts\Presenter\PresentableTrait;
use Watson\Validating\ValidatingTrait;

class User extends VerifyUser
{
    protected $table = 'users'; 

    use ValidatingTrait;

    protected $rules = [
        'username'  => 'required|unique:users',
        'email'     => 'required|unique:users',
        'password'  => 'required'
    ];

    protected $validationMessages = [
        'username.unique' => "Username Already Exist"
    ];

    use PresentableTrait;

    protected $presenter = 'UserPresenter';


}

Add $injectUniqueIdentifier attribute as a default

I never realized that $injectUniqueIdentifier isn't a part of the trait by default, and that I had to explicitly add it to my models. Even if it defaults to false, it'd be nice to have the default property value set by default.

[Proposal] Add eloquent.validated event for always listeners.

In the readme for the latest changes on events you have:

After validation occurs, there are also a range of validated events you can hook into, for the passed, failed and skipped events. For the above example failing validation, you could get the event eloquent.validated.passed: App\User.

What about when a dev wants to do something after every validation? What about adding eloquent.validated which is always fired much like eloquent.validated.validating. Another optional name would be eloquent.validated.always.

Default ruleset that others can inherit from to reduce duplication

At the moment if you want different rulesets for say creating and updating but they are mostly the same except for one or two differences there will be a lot of unnecessary duplication. I think it will be best to implement some sort of default ruleset which all others can inherit from to keep things DRY.

Validating 'required' only not triggering.

I've noticed that if I validate a form field using only required, it doesn't fail validation.

Here is my code:

class User extends Eloquent implements UserInterface, RemindableInterface {

    use UserTrait;
    use RemindableTrait;
    use ValidatingTrait;

    protected $table = 'users';
    protected $hidden = array('password', 'remember_token');
    protected $fillable = [
        'email',
        'password'
    ];
    protected $rules = [
        'creating' => [
            'email' => 'required|email|unique:users,email',
            'password' => 'required|confirmed'
        ],
        'logging_in' => [
            'email' => 'required|email',
            'password' => 'required'
        ]
    ];
    protected $injectIdentifier = true;
    protected $throwValidationExceptions = true;

    public function setPasswordAttribute($password)
    {
        $this->attributes['password'] = Hash::make($password);
    }
}

global.php:

App::error(function(Watson\Validating\ValidationException $exception, $code)
{
//    Log::error($exception);
    return Redirect::back()->withInput()->withErrors($exception->getErrors());
});
    public function store()
    {
        $user = $this->user->fill(Input::all());
        $user->isValid('logging_in');
        if (Auth::attempt(Input::only('email', 'password'))) {
            return Redirect::intended('home');
        }

        return Redirect::back()->withInput()->withFlashMessage('Invalid login credentials provided. Please try again.');
    }
                    <div class="form-group{{ (count($errors) > 0) ? (($errors->has('password')) ? ' has-feedback has-error' : ' has-feedback has-success') : ''; }}">
                        {{ Form::label('password', 'Password', ['class' => 'control-label col-sm-4']) }}
                        <div class="col-sm-8">
                            {{ Form::password('password', ['class' => 'form-control', 'required']) }}
                            @if (count($errors))
                            <span class="glyphicon {{ ($errors->has('password')) ? ' glyphicon-remove' : ' glyphicon-ok'; }} form-control-feedback"></span>
                            @endif
                        </div>
                        {{ $errors->first('password', '<span class="help-block col-sm-8 col-sm-offset-4">:message</span>') }}
                    </div>

Any suggestions what I might be doing wrong?

Laravel Logout Functionality Causes User Model Save

Laravel's built-in logout functionality that is part of the Auth system (Auth::logout()), triggers a save on the user model, which inserts the remember_token.

I don't believe there is any way for me to intercept this save, and have to do forceSave instead, so I would propose one of two:

  1. Not to intercept the default save() function of Eloquent, but rather introduce a new validateAndSave() function to allow validation to be explicitly called. I think there are too many risks with intercepting framework methods that may change behavior in the future, or may change behavior for different database layers, i.e. using it with Laravel-MongoDB could prove problematic. (This is my preferred choice.)
  2. Add new pre-defined rulesets login and logout that will be used accordingly, and could also handle the password confirmation issue in the future.

inject(Unique)Identifier

I was failing to get my uniques to work over the weekend and after rummaging through the code I discovered that the documentation's suggested 'injectIdentifier' was not correct. The code utilises 'injectUniqueIdentifier'.

Had me stumped for a while that one :P

Confirmation should ignore empty fields

When I have a form, for example with 'password' and 'password_confirmation', but leave them empty (eg. for not wanting to change the password), the field should be ignored. (I'm on 0.10.x)
(If I wanted it to be required, I would have added the required rule ;))

Validator stopped working

Since this morning I can't seam to be able to perform validation. it worked fine on friday with 0.7.9, but now, even with that version it does not perform any kind of validation.

It's like the validator is not picking the save/create event

User.php

Class User extends \Eloquent implements UserInterface, RemindableInterface {

    use UserTrait, RemindableTrait, PresentableTrait, ValidatingTrait;

    /**
     * Database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = ['password', 'remember_token'];

    /**
     * Fillable fields
     *
     * @var array
     */
    protected $fillable = [
        'first_name', 'last_name', 'title',
        'email', 'password',
        'company_id', 'reports_to',
        'due_day', 'timezone'
    ];

    /**
     * Validation rules
     *
     * @var array
     */
    protected $rules = [
        'creating' => [
            'first_name' => 'required|min:3',
            'last_name' => 'required|min:3',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:6'
        ],

        'updating' => [
            'first_name' => 'required|min:3',
            'last_name' => 'required|min:3',
            'email' => 'required|email|unique:users,email',
            'password' => 'sometimes|min:6'
        ]
    ];

    /**
     * Whether the model should throw a ValidationException if it
     * fails validation. If not set, it will default to false.
     *
     * @var boolean
     */
    protected $throwValidationExceptions = true;
<?php

use Acme\Repositories\UserRepository;
use Watson\Validating\ValidationException;

class UsersController extends \BaseController {

    /**
     * @var Acme\Repositories\UserRepository
     */
    protected $repo;

    /**
     * Authenticated user
     *
     * @var Auth
     */
    protected $user;

    function __construct(UserRepository $repo)
    {
        $this->beforeFilter('guest', ['only' => ['create']]);
        $this->beforeFilter('auth', ['except' => ['create', 'register']]);

        $this->repo = $repo;
        $this->user = Auth::user();
    }

   /**
     * Register a new user
     * this will fire $mode->create($input)
     * @return Response
     */
    public function register()
    {
        try
        {
            $user = $this->repo->register(Input::all());

            Auth::login($user);

            return Redirect::intended('/')->withSuccess('!!!');
        }
        catch (ValidationException $e)
        {
            return Redirect::back()->withInput()->withErrors($e->getErrors());
        }
    }

}

Am I doing something wrong?

Use of 'validate' method interferes with Cartalyst/Sentry

Sentry implements a 'validate' method and so fails to work with this (frankly awesome) project. As a quick fix I renamed the method to 'validateModel' but I this obviously won't work in the future unless I fork and all that :)

Pass variable from controller to $rules

How would one pass a value from my controller to the model and $rules attribute like below?

protected $rules = [
    ....
    'username' => 'required|unique:users,username,NULL,id,tenant_id,'.$this->tenant_id
];

The following works in the controller, but replaces the entire rules set in the model (and is not as flexible)

$myModel->setRules([
    'username' => required|unique:users,username,NULL,id,tenant_id,'.$this->tenant_id
]);

Supports :placeholders for replace them on attribute value

Is it possible use placeholders for the substitution of the value of the attribute/field in the validation rule?
Example rule:

public static $validationRules = [
  'id' => 'unique:mytable,id,:id',
  'title' => 'unique:mytable,title,:id',
  'some_field' => 'custom_validation_fn:{{title}}',
];

Further, before the validation of the model the placeholders :id and {{title}} will be replaced by the values ​​of these fields.
What do you think about this? Thanks.

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.