-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validating Unique Values on Update #6
Comments
we do it somewhat simplistically, but it works. First of all you have two options: 1 class per action i.e. UpdateUserForm and CreateUserForm, or something similar to what we did below, where the if you look at the
|
Thanks @carvefx your code works great :) |
If anybody finds a more elegant solution, I'd love to see it in action, I feel dirty about appending strings directly, seems so low-level :P |
Thanks! This helped me a lot. Glad to also see someone else was looking for this functionality. |
Is this really closed. Seems messy to me, and obviously is over riding methods which really should be able to cope with this.... @JeffreyWay is this something you could look at and maybe address is Laracasts (Which is excellent) Could the validator function accept a second param, array which has key (name of form element which has unique requirements) => $id. From here, the $rules could be editted??? |
Maybe a slight improvement.. <?php
namespace Teamleaf\Depots\Forms;
use Laracasts\Validation\FormValidator;
class DepotForm extends FormValidator
{
protected $rules = [];
/*
* Validation rules for the status form
* @var Array
*/
protected $create_rules = [
'title' => 'required|unique:depots',
'code' => 'required|unique:depots',
'address' => 'required'
];
protected $update_rules = [
'title' => 'required|unique:depots',
'code' => 'required|unique:depots',
'address' => 'required'
];
/**
* @param array $input
* @return mixed
*/
public function validateCreate(array $input)
{
$this->rules = $this->create_rules;
return $this->validate($input);
}
/**
* @param int $id
* @param array $input
* @return mixed
*/
public function validateUpdate(array $input, $id)
{
$this->update_rules['title'] .= ',title,'.$id;
$this->update_rules['code'] .= ',code,'.$id;
$this->rules = $this->update_rules;
return $this->validate($input);
}
} and public function update($id)
{
$inputs = Input::get();
$inputs['userId'] = Auth::id();
$inputs['id'] = $id;
$this->depotForm->validateUpdate($inputs, $id);
$depot = $this->execute(UpdateDepotCommand::class, $inputs);
Flash::message("Your depot has been updated!");
return Redirect::to('/depots');
} Realistically the passed |
Hey, guys - Firstly, I very quickly scanned this thread, so if I missed something, let me know. (Sorry, in a hurry.) I'm not sure if the package needs to provide a solution for this. You can add a helper method to your form object to set an excludes on the appropriate column. Something like: public function excludeUserId($id)
{
$this->rules['username'] = "required|unique:users,username,$id"
return $this;
} Then, you can do |
Hi, I extend your FormValidator class like this (maybe not the best way to do the replacement) public function setCurrent($id)
{
$this->currentId = $id;
return $this;
}
public function validate($formData)
{
$formData = $this->normalizeFormData($formData);
if( is_numeric($this->currentId))
{
$rules = $this->getValidationRules();
foreach($rules as $key => $value){
$rules[$key] = str_replace(':current', $this->currentId, $rules[$key]);
}
$this->rules = $rules;
} else
{
$this->rules = $this->getValidationRules();
}
$this->validation = $this->validator->make(
$formData,
$this->rules,
$this->getValidationMessages()
);
[...] Then you can use in your rules 'email' => 'required|email|unique:users,email,:current', and in your Controller: $this->updateUserForm->setCurrent($id)->validate($input); I hope you will include something like that in one update, also if its only with one id at the moment. Felix |
This project has the functionality and seems to work pretty neatly, albeit doing a few too many tasks in a single class: |
@JeffreyWay I think it would be good to implement something like this into the package. for example me personnaly, can't remember any project, where this unique thing would not be required... for now I just created something like this <?php namespace App\Forms;
use Laracasts\Validation\FormValidator;
class CarColorForm extends FormValidator {
protected $rules = [
'name' => 'required|unique:car_colors,name,{id}',
'hex' => 'required|unique:car_colors,hex,{id}',
];
public function validateUpdate($id, array $formData)
{
$search = [',{id}'];
$replace = [''];
if ($id)
{
$replace = [','.$id];
}
foreach ($this->rules as $k => $rules)
{
$this->rules[$k] = str_replace($search, $replace, $rules);
}
return parent::validate($formData);
}
} and I just call $this->$this->carColorForm->validateUpdate($id, $input); but probably funtionality like this out of the box would be perfect :) Thanks |
I think the If you define the validation rules in a method. You can do something like this. public function rules()
{
return [
'username' => 'required|unique:users,username,' . Auth::id()
];
} This is only a suggestion. But, this is a great package. |
@JeffreyWay how would you now do this with Laravel 5? Since the "YourCustomFormRequest" has no knowledge of the input data, how might you pass an $id to the Request? Particularly, when it's not something you can conveniently grab like @gravitano suggested above. What am I missing? |
I mean, this works: public function rules() { $id = Request::segment(2); return [ 'name' => 'required', 'slug' => 'required|unique:departments,slug,'.$id.'|alpha_dash' ]; } but to me that just seems hacky and probably not the best way of doing it. Other suggestions are greatly appreciated! |
It doesn't sound that hack to me! To avoid breaking stuff that's already setup (and I haven't got round to updating yet), I use the following in FormValidator:
Then I reference the request like @leothelocust
|
@leothelocust @TomCawthorn Laravel 5 has no need of this package as it is implementing its own validation using Form Requests which you can read more about over at Matt Staufers blog http://mattstauffer.co/blog/laravel-5.0-form-requests |
Also have my own solution to the multiple sets of rules for a single resource. You can check it out in my fork of the repo over at https://github.com/JacobBennett/Validation. The idea is essentially that you set nested rules in the rules array like so $rules = [
'store' => [
'user' => 'required',
'password' => 'required'
],
'update' => [
'password' => 'required'
]
]; Then before validating, you simply set a context on the validator like so $this->validator->setContext('update')->validate(); Easy solution, and tests are included. Has been working great for me. |
my extends of Laracasts\Validation\FormValidatornamespace Acme\Core;
use Laracasts\Validation\FormValidator as _FormValidator;
class FormValidator extends _FormValidator {
protected $rule = null;
public function getValidationRules() {
// si on passe en arg un array
if ( is_array( $this->rule ) ) {
// recupere toutes les values
$rule_val = current( array_values( $this->rule ) );
// print_r($rule_val);exit;
// si l'array contien qu'un seul élément et que les values sont un array
if ( count( $this->rule ) == 1 && is_array( $rule_val ) ) {
// récupere la premiere key de l'array
$rule_key = current( array_keys( $this->rule ) );
// si la premiere key de l'array est présent dans la class Acme/Forms/{$name}Form.php dans $this->rules ( add || edit || whatever || ... ).
if ( in_array( $rule_key, array_keys( $this->rules ) ) ) {
// on fusionne les 2 array
return array_merge( $this->rules[$rule_key], $rule_val );
}
//si 1er key pas présente on return les nouvelles rules passé en arg en enlevant le parents ( ex: edit => [ $rule1, $rule2, ... ] )
return $rule_val;
}
// si array plus que 1 éléments on return directement les rules
return $this->rule;
}
// si on passe en arg un string
if ( is_string( $this->rule ) ) {
// on return la bonne rules
return $this->rules[$this->rule];
}
// sinon rien de tout cela comportement par default
return $this->rules;
}
public function validate ( array $formData, $rule = null ) {
$this->rule = $rule;
// dd($this->rules);
return parent::validate( $formData );
}
} example of a FormValidatornamespace Acme\Forms;
use Acme\Core\FormValidator;
class UserForm extends FormValidator {
protected $rules = [
'add' => [
'login' => 'required|alpha_dash|unique:user,login,NULL,id,deleted_at,NULL',
'email' => 'required|email|unique:user,email,NULL,id,deleted_at,NULL',
'password' => 'required|confirmed'
]
];
} Using in a controller// ....
public function store( $id = null ) {
$user = User::firstOrNew(['id' => $id]);
if ( $id === null ) {
$this->userForm->validate(Input::all(), 'add');
// or merging with the existing one ( in Acme\Form\UserForm )
// if rule "add" doesn't existe juste apply the [ 'rule1', 'rule2' ]
$this->userForm->validate(Input::all(), [ 'add' => [ 'rule1', 'rule2' ] ]);
$user->password = Input::get( 'password' );
Flash::success("L'utilisateur a été ajouté avec succès !");
}
else {
$rules = [
'login' => 'required|alpha_dash|unique:user,login,'.$id.',id,deleted_at,NULL',
'email' => 'required|email|unique:user,email,'.$id.',id,deleted_at,NULL'
];
$this->userForm->validate( Input::all(), $rules );
Flash::success("L'utilisateur a été modifié avec succès !");
}
$user->login = htmlspecialchars(Input::get( 'login' ));
$user->email = htmlspecialchars(Input::get( 'email' ));
$user->firstname = htmlspecialchars(Input::get( 'firstname' ));
$user->lastname = htmlspecialchars(Input::get( 'lastname' ));
$user->save();
return Redirect::to( 'user' );
}
// .... |
For example, on updating user account information. In the docs it looks like you can add a id to a unique column to ignore validation like so:
'email' => 'unique:users,email_address,10'
Does this package support this functionality? If so how would one implement this?
Thanks!
The text was updated successfully, but these errors were encountered: