Laravel unique ruleset ignores the current user id - php

I'm working on updating a user in Laravel, where I made the following validation rule for updating a users email:
"email" => "required|email|unique:users,email,".$this->route("user")->id,
This is inside of my form request.
However, when I post, it still says that the email is already taken? Is this perhaps a bug in the latest version of Laravel?
Thanks!

No it is not a bug, you are using a null value for the id hence the reason why, change your rule to this:
"email" => "required|email|unique:users,email,".$this->user()->id,
Make sure that you have Request $request in your method, and also you have the auth middleware on your controller.

you set the ignore email column so you should pass email not id
"email" => "required|email|unique:users,email,".$this->route("user")->email,

First you have to add rules in user model
static function rules() {
return [
'email' => 'required|email'
];
}
In user controller
use Illuminate\Validation\Rule; // add this one
function add_update_user(Request $request,$user_id) {
$data = $request->all();
unset($data['_token']);
$rules = User::rules();
$rules['email'] = explode('|', $rules['email']);
if (isset($user_id)) // is old user, your get user_id in route
{
$rules['unique_code'][] = Rule::unique('databse_connection_name.users')->ignore($data['email'], 'email');
} else // is new user
{
$rules['email'][] = 'unique:databse_connection_name.users,email';
}
$validator = Validator::make($data, $rules);
...
...
}

Related

Verify if has only a specified parameter in request - Laravel

Is it possible to check in laravel, if only a specific field is filled in a request?
Like this: if($request->filledOnly('email)){}
If possible how to do that?
You can use the has() method, and you can call it like this:
if($request->has('email'))){
//do one thing
} else {
//do another
}
Edit:
If you want to check for a situation in which only one input is set, you can do something like this:
Assuming your other inputs are name, phone, address, you can check if any of them are set by calling hasAny on your $request:
if (!$request->hasAny['name', 'phone', 'address'])
{
//now we know none of them are set
//check if email is set:
if ($request->has('email')
{
}
}
You can also use Validator rules in that.
$all = $request->all();
$rules = [
'email' => 'bail|required|email'
];
$validator = Validator::make($all, $rules);
You can try to do this:
if(count($request->except('email')) === 0)
{
// your code here
}

Laravel - limit FormRequest to certain parameters

In a form request class I use a method like this to validate input data.
class SignupRequest extends FormRequest
{
...
public function rules()
{
return [
'user.email' => 'required_with:user|email',
'user.domain_name' => 'required_with:user|string',
'user.password' => 'required_with:user|string|min:8',
'user.username' => 'required_with:user',
];
}
...
}
Later in a controller I use something like this
$data = $request->get('user', []);
return $this->response($this->userService->create($data, false), 201);
I want somehow to write to my SignupRequest which fields it should allow to be passed. So when later I get $data = $request->get('user', []); I'm sure there are only allowed fields in it.
Is this possible inside the FormRequest?
P.S. I'm aware of $request->only(['field1', 'field2', 'field3']) way, but if I want to limit the fields in SignupRequest extends FormRequest. Because if I use $request->only([...]) in my code several times, I would have to change it several times later. I want to keep it in one place.
You wouldn't need to do this with the request.
One option would be to do something like:
$user = $request->input('user', []);
$data = array_only($user, ['email', 'domain_name', 'password', 'username']);
Or you could even inline it:
$data = array_only($request->input('user', []), ['email', 'domain_name', 'password', 'username']);
Hope this helps!
FormRequest is meant to validate your request data, not control them. You could always extract the inputs you need by doing so.
$data = $request->only(['user.name', 'user.password']);
Edit : Based on your comment, you can do something like this. This allows you to store all the field names within a single request to keep them organised and easier to update.
Add this to your SignupRequest
public function loginData()
{
return array_only($this->input('user', []), ['username', 'password']);
}
Use it in the controller like so
$request->loginData();
return $this->response($this->userService->create($request->loginData(), false), 201);

Laravel 5 make a custom register function

Laravel 5 has it's default register function which is in
public function postRegister(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
Auth::login($this->create($request->all()));
return redirect($this->redirectPath());
}
I know that I can copy this code and paste it in my AuthController but there's a change that I need to make which I don't know where to start and find. What I want is change the code for the insertion of data in my users table. I want to change this because I add another column in my users table which is company_name and I have a table which is named companies so basically when the user enter a company_name for registration it will check the companies table if it is existing then return error message if it is. So think there is something like:
$rules = array(
'company_name' => 'unqiue:companies',
);
But i don't know where to put this thing in my registration code. Thanks
You can use a custom validation, in this case. Make sure, you a are calling $this->validate(), and not $this->validator. This validate will automatically redirect back with errors if it fails, so you can skip the check statement.
public function postRegister(Request $request)
{
$this->validate($request->all(), [
'company_name' => 'unique:companies',
// And the other rules, like email unqiue, etc..
]);
Auth::login($this->create($request->all()));
return redirect($this->redirectPath());
}

Laravel 4 Form Validation should be unique on update form, but not if current

I am trying to validate an update user profile form, whereby the validation should check that the email doesn't exist already, but disregard if the users existing email remains.
However, this continues to return validation error message 'This email has already been taken'.
I'm really unsure where I'm going wrong. Otherwise, the update form works and updates perfectly.
HTML
{{ Form::text('email', Input::old('email', $user->email), array('id' => 'email', 'placeholder' => 'email', 'class' => 'form-control')) }}
Route
Route::post('users/edit/{user}', array('before' => 'admin', 'uses' => 'UserController#update'));
User Model
'email' => 'unique:users,email,{{{ $id }}}'
Your rule is written correctly in order to ignore a specific id, however, you'll need to update the value of {{{ $id }}} in your unique rule before attempting the validation.
I'm not necessarily a big fan of this method, but assuming your rules are a static attribute on the User object, you can create a static method that will hydrate and return the rules with the correct values.
class User extends Eloquent {
public static $rules = array(
'email' => 'unique:users,email,%1$s'
);
public static function getRules($id = 'NULL') {
$rules = self::$rules;
$rules['email'] = sprintf($rules['email'], $id);
return $rules;
}
}
You can accomplish this with the sometimes function of the validator
Something like:
$validator->sometimes('email', 'unique:users,email', function ($input) {
return $input->email == Input::get('email');
});
See http://laravel.com/docs/4.2/validation#conditionally-adding-rules for more info

Laravel validation service with unique fields

I'm using a validation service to validate user submitted form input (something along the lines of: http://laravel.io/bin/vrk).
Using this approach (validation service classes) to validate user submitted form data against a set of rules, how can I validate user submitted data when rules have a unique rule. For example, if a user has the username of John then when I try to update the model validation fails (because John exists as a username, even though it belongs to the current model).
To solve this in Laravel I can do something like 'username' => 'required|alpha_dash|unique:users,username'.$id. How should I modify my current code, in the link, to best accommodate this? Should I have separate validator classes depending on the scenario (for example, UserCreateValidator, UserUpdateValidator, etc). Or should I do something like create separate validation rules in UserValidator class and pass which rule I want as an argument to either the constructor or the passes() method when calling UserValidator?
I think you could do something like this
First update UserValidator rules like this.
class UserValidator extends Validator {
// Override parent class $rules
protected $rules = [
'default' => [
'username' => 'required|alpha_dash|unique:users',
'password' => 'required|between:6,16|confirmed',
'password_confirmation' => 'required|between:6,16'
],
'update' => [
'username' => null,
]
];
}
Then modify Validator's passes method like this
public function passes($rule = null) {
$rules = $this->rules['default'];
if ($rule && isset($this->rules[$rule])) {
$rules = array_merge($rules, $this->rules[$rule]);
}
$validator = \Validator::make($input, $rules);
if ($validator->fails()) {
$this->validator = $validator;
return false;
}
return true;
}
Then in your controller's PUT method, this will merge update rules to default rules
$rule = 'update';
// user has changed his username
if ($input['username'] !== $old_username) {
$rule = 'create'; // validate uniqueness
}
else {
unset($input['username']); // remove it, we don't validate it anymore since it's the same
}
$validator->passes($rule); // override 'default' rules with 'update' rules
You don't have to change your controller's POST method, it'll stay the same
$validator->passes(); // use 'default' rules
If I'm understanding right, you have issues updateng data because of primary key constraints on your model. What you need to do is to create 2 sets of rules, one for insert, and one for update.
Asuming you have a set of rules like this:
protected $rules = [
'id' => 'required|unique:users'
]
You should implement something like this:
protected $rules = [
'id' => 'required|unique|unique:users,id,' . $this->id
];
This should tell laravel to ignore the duplicate id in the table users for the specified id, in this case, the id for the current object.
You can read more about this on laravel's documentation at http://laravel.com/docs/validation
unique:table,column,except,idColumn
The field under validation must be unique on a given database table.
If the column option is not specified, the field name will be used.
Well, what are you doing on post?
Because this is what you should be doing:
$user = User::find($userId);
$user->username = $input['username'];
$user->email = $input['email'];
$user->save();
To update a record.
Or
$input = array('username' => 'w0rldart', 'email' => 'hahafu#dumbledore.com');
// Retrieve the user by the attributes, or create it if it doesn't exist,
// based on the data above, which can come from an Input::all();
$user = User::firstOrCreate($input);
... many possibilities. But you could also do:
$input = array_forget($input, 'username');
To comply with your case, by removing the username index from the input array.
This is all I call tell you, based on the information you gave us. If you want more, post the controller's put method.
Update:
Here's my version of your PUT method: http://laravel.io/bin/OaX
I really think that try catch syntax is useless, since it's obvious that a User model will always be there. But I still don't know what you're trying to update. Even though I can't test it right now, I don't think that updating should be giving that problem, and if it does, retrieve user by username/id then unset the username index in your input array, and update it according to your specifications.
A little modification in UserValidator class
class UserValidator extends Validator {
// Override parent class $rules
protected $rules = [
'username' => 'required|alpha_dash|unique:users',
'password' => 'required|between:6,16|confirmed',
'password_confirmation' => 'required|between:6,16'
];
// ADD THIS
public function __construct(Array $rules = array())
{
parent::__construct();
if(count($rules)){
foreach($rules as $k => $v) $this->rules[$k] = $v;
}
}
}
In your controller putUpdate method
$user = User::whereUsername($username)->firstOrFail();
$rules = ['username' => 'required|alpha_dash|unique:users,username,'. $user->id];
// Pass the rule to update the rule for username in this method
$validator = \Services\Validators\UserValidator(Input::all(), $rules);
Check the manual here.

Categories