I'm working with Laravel 8 to develop my project, and I have made a Resource Controller under the Admin directory, which goes like this:
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
public function update(Request $request, User $user)
{
$data = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email',
'max:255', Rule::unique('users')->ignore($user->id)],
]);
if (!is_null($request->password)) {
$request->validate([
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
$data['password'] = $request->password;
}
$user->update($data);
if ($request->has('verify')) {
$user->markEmailAsVerified();
}
return redirect(route('admin.users.index'));
}
As you can see, I put the method update because it holds some form of validation. But whenever I try to update the data within the form of the Blade file, I get this error:
Error
Class 'App\Http\Controllers\Admin\Rule' not found
I even tried adding use Illuminate\Support\Facades\Validator; but still receives the error. How can I fix this error?
call this in your file
use Illuminate\Contracts\Validation\Rule;
Related
I created a trait to use with a controller. The controller should start the trait function, which validates its input and then does a thing.
Inside the FooController.php:
[..]
$do_stuff = $this->create_stuff($input);
The trait:
<?php
namespace App\Traits;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
[..]
use Illuminate\Support\Facades\Validator;
trait Foo
{
public function create_stuff(Request $input)
{
// validation part
$validatedData = $input->validate([
'Value' => 'required|numeric',
]);
// end of validation part
[..]
Everything works fine without the validation part but as soon as I add it I get the error:
Argument 1 passed to App\\Http\\Controllers\\FooController::create_stuff() must be an instance of Illuminate\\Http\\Request, instance of stdClass given,[..]
I understand the $input is a 'normal' (?) PHP object and it seems the validation only works with 'request' objects, so how can I make this work?
First of all please don't create a trait for validation create a request for validation using PHP artisan
PHP artisan make:request Your_request_name
and inside your request add your validations like this
public function rules()
{
return [
'sponsor_name' => ['required', 'string'],
'sponsor_type' => ['required', 'string'],
'mobile' => ['required', 'string'],
'email' => ['required', 'string'],
'nationality' => ['required', 'string'],
'sponsor_issued_from' => ['required', 'string'],
'sponsor_issued_date' => ['required', 'date'],
'sponsor_address' => ['required', 'string'],
];
}
public function authorize()
{
return true;
}
then inside your request add your validations
after that just call your request in your controller function
for example
public function (Your_request_name $request)
{
...
}
Before you mark this question as a duplicate of this question, first understand that this question is based on Laravel 8 while the former is on Laravel 5.4 which handle the auth differently.
I would like to add a named error bag on laravel validation during registration. I am using the default laravel auth
php artisan ui bootstrap --auth
Below is the class that handles registration.
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
use RegistersUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest');
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
Registration is handled by register method in the above class. Laravel has hidden this method and imports it to the above class using the use RegistersUsers; declaration.
To add a named error bag as explained here, I need to access this hidden register method. How do I do it.
I know that one way of doing this is by writing my own register method, but is there an alternative?
I need to add a named error bag because my login and register forms are in the same page.
You should pass the validator to named error bag, so it can be achieved by overriding register method from RegisterUsers trait:
public function register(Request $request)
{
$validator = $this->validator($request->all());
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
return redirect('register')->withErrors($validator, 'login');
}
Or you can validate it with an error name bag
public function register(Request $request)
{
$validator = $this->validator($request->all())->validateWithBag('login');
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
return redirect('register');
}
I'm trying to block users from using certain names like 'admin' or 'operator'.
I've tried fiddling with both Controllers/Auth/RegisterController and Controller/RegisterController but failed.
What I've tried was something like this:
in Controllers/Auth/RegisterController,
if ($data['name'] === 'admin' || $data['name'] === 'operator') {
return redirect()->back()->withErrors(['Invalid username']);
}
else {
session()->flash('message', 'Welcome!');
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
The code above gave me this error:
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must be an
instance of Illuminate\Contracts\Auth\Authenticatable, string given,
called in /var/www/vendor/laravel/ui/auth-backend/RegistersUsers.php
on line 36
I've also searched whether validators can block specific words but failed.
I know I can work this around by using JS, but I think Laravel would have some function like this.
Go to RegisterController.php.
There will be a validator(array $data) function that validates your registration input.
Add not_in validation check for the name field.
Something like this:
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255', 'not_in:admin,operator'],
'pan' => ['required', 'string', 'min:10', 'max:10', 'unique:users,username'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
Hopefully, this helps.
You can try to validate if requested name is not in the list of predefined blocked names:
use Illuminate\Validation\Rule;
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['admin', 'superuser']),//etc..
],
]);
Hope it helps.
Here's what I did in Laravel 9 with the Breeze scaffolding.
I created a separate "Services" trait with the reserved usernames, so that I can easily implement and extend it.
Create a Services folder at app/Services
Create a trait Reserved at app/Services/Reserved.php
Reserved.php
<?php
namespace App\Services;
trait Reserved
{
public static function usernames()
{
return ['admin', 'operator', 'someBadWord'];
}
}
Next open app/Http/Controllers/Auth/RegisteredUserController.php and import the trait, then add it.
Now just add it to your validation rules using the notIn rule.
Rule::notIn(Reserved::usernames())
RegisteredUserController.php
use Illuminate\Validation\Rule;
use App\Services\Reserved;
class RegisteredUserController extends Controller
{
use Reserved;
...
public function store(Request $request)
{
$request->validate([
'username' => ['required', 'string', 'max:16', 'unique:users', Rule::notIn(Reserved::usernames())],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
...
}
}
Create RegisterControllerRequest using the following command:
php artisan make:request RegisterControllerRequest
find out your recent created file in app/Http/Requests, then update rules() to be:
public function rules()
{
return [
'name' => 'required|notIn:admin,operator',
];
}
Then update your controller to use the new validation:
After name space add:
use App\Http\Requests\RegisterControllerRequest;
And finally inject the validation as a parameter in your register method:
public function register (RegisterControllerRequest $request)
For more information check documentation: https://laravel.com/docs/7.x/validation#form-request-validation
Modify my registration blade. I added 2 additional functions that trigger the registration of the user. The data I needed are being saved to the appropriate tables but I am having this error,
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must
implement interface Illuminate\Contracts\Auth\Authenticatable, boolean
given, called in
E:\wamp64\www\aftscredit-appzcoder\vendor\laravel\framework\src\Illuminate\Foundation\Auth\RegistersUsers.php
on line 35
Here's my Registration controller
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Referral;
use App\CollectorMember;
use App\HasRoles;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
class RegisterController extends Controller
{
use RegistersUsers;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware('guest');
}
public function index(Request $request)
{
$referral = '';
$keyword = $request->get('search');
$referral = Referral::where([
['code', $keyword],
['status', 0]
])->first();
if (is_null($keyword))
return view ( 'Auth.register');
elseif ($referral)
return view ( 'Auth.register', compact('referral', $referral))
->withDetails ( $referral )
->withQuery ( $keyword );
else
return view ( 'Auth.register')->withMessage ( 'The code you provided is not EXISTING or not AVAILABLE.' );
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$user_id = $user->id;
Referral::find($data['referral_id'])->update ([
'status' => 1,
'date_used' => $data['referral_date_used']
]);
return CollectorMember::create ([
'collector_id' => $data['referral_generate_by'],
'borrower_id' => $user_id,
'referral_id' => $data['referral_id'],
]);
}
}
What's causing this? thanks in advance!
Try opening the RegistersUsers trait and look at line 35. A user is not being created.
The original Laravel controller code to create a user is as follows:
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
Note how the DocBlock indicates an instance of User must be returned. This is key because the the actual code that completes the registration, within the trait, assumes a a valid User model instance.
It's sometimes helpful to step through the code and understand what Laravel is doing for you, behind the scenes.
In Laravel (5.8) controller, i try to make update() function for my User model.
I validate data with using my own class UpdateRequest. When i put variable $user in this class, i have error Undefined variable: user.
<?php
namespace App\Http\Requests\Users;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class UpdateRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required|string|alpha_dash|max:255|min:6',
'email' => ['required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore($user->id)],
];
}
}
public function update(User $user, UpdateRequest $request)
{
$user->update($request->only(['name', 'email']));
return redirect()->route('users.index');
}
But if I use validate function in controller update() method, all works fine.
public function update(User $user, Request $request)
{
$this->validate($request, [
'name' => 'required|string|alpha_dash|max:255|min:6',
'email' => 'required|string|email|max:255|unique:users,id,' . $user->id,
]);
$user->update($request->only(['name', 'email']));
return redirect()->route('users.index');
}
In your custom request class, you don't have the $user initialized and you try to use it, while in the controller method the $user is passed as a parameter.
Note $this->user in the Request returns the currently authenticated user, so make sure that you always want to use his ID, instead of an ID of the passed in user, hence the reason I am using request('user') to get the user id from the URL.
So try this instead:
public function rules()
{
return [
'name' => 'required|string|alpha_dash|max:255|min:6',
'email' => ['required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore(request('user'))],
];
}
You need to change $user->id to $this->user->id and it should work properly. Check below:
return [
'name' => 'required|string|alpha_dash|max:255|min:6',
'email' => ['required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore($this->user->id)],
];
Hope it helps you!!
User class instance is missing in UpdateRequest class constructor or you can try with $this->user->id. It may help you.