Laravel: Too few arguments to function 0 passed and exactly 1 expected" - laravel

I know this has been asked before. ive seen the questions and answers but cant find something that I can get help from.
I am trying to pass simple data into my database. so far so good.
I believe my problem arises when I try to add the userID since it has to be pulled from Auth. so here is my controller code.
side node , userID is from a foreign table called users. and userID will be used as a foreign key. in the userstable its called "id"
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ShopController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('/shop/addShop');
}
protected function validator(array $data)
{
return Validator::make($data, [
'userid' => ['required', 'string', 'max:255'],
'shopname' => ['required', 'string', 'max:255'],
'address' => ['required', 'string', 'max:255'],
'postal' => ['required', 'string', 'max:255'],
'city' => ['required', 'string', 'max:255'],
'phone' => ['required', 'string', 'max:255'],
]);
}
/**
* Add Users shop after a validation check.
*
* #param array $data
* #return \App\
*/
protected function create(array $data)
{
$userId = Auth::id();
return User::create([
'userid'=> $data[$userId],
'shopname' => $data['shopname'],
'address' => $data['address'],
'postal' => $data['postal'],
'city' => $data['city'],
'phone' => $data['phone'],
]);
}
}
and right here you can see my route.
<?php
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::post('/addShop', 'ShopController#create')->name('addShop');
Route::get('/addShop', 'ShopController#index')->name('addShop');

Use Request
Your create function is expecting an array. However, Laravel is passing a POST request. Therefore, use the Request class instead. Your code should read:
namespace App\Http\Controllers;
use User;
use Illuminate\Http\Request;
protected function create(Request $data)
{
$userId = Auth::id();
return User::create([
'userid'=> $data[$userId],
'shopname' => $data['shopname'],
'address' => $data['address'],
'postal' => $data['postal'],
'city' => $data['city'],
'phone' => $data['phone'],
]);
}

I got this error on my project it was because this line of code
Auth::guard()->logoutOtherDevices(); I just comment it and my logout function worked correctly.

Related

Is there a built-in way to remove account enumeration from registration?

I have created a new site using Jetstream and Inertia. Currently the application will return a "The email has already been taken." message if a user tries to register with an existing email. Notwithstanding timing analysis, I would like to keep the existence of user accounts private. Is there a way to keep the unique constraint on email but display the same outward behavior if someone registers with an existing email? Ideally, I would like to not create a second user, but email the existing user suggesting they reset their password or ignore the email.
I agree with Unflux about not changing this, but if you need to you could modify CreateNewUser.php located at app\Actions\Fortify\CreateNewUser.php and change the validation message or modify the process.
The create() method which is responsible for creating the new user looks like:
public function create(array $input)
{
//define custom messages
$customValidationMessages = {
'email.unique' => 'New Message',
}
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], //email validation rules here
'password' => $this->passwordRules(),
], $customValidationMessages)->validate(); //add the variable containing the custom message(s) here
return User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
'api_token' => Str::random(60),
]);
}
If you need to send the user an email or customize this further I suggest you look into implementing an "After Validation Hook" which you can read about here: https://laravel.com/docs/8.x/validation#after-validation-hook
Here's what worked for me:
Create a new validation Exception in app/Exceptions/ExistingUserException.php
namespace App\Exceptions;
use Illuminate\Validation\ValidationException;
class ExistingUserException extends ValidationException
{
}
Break validation into 2 steps in app/Actions/Fortify/CreateNewUser.php, throwing the extended ValidationException if the form is otherwise good
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255'],
'password' => $this->passwordRules(),
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '',
])->validate();
$validator = Validator::make($input, [
'email' => ['unique:users'],
], ['email.unique'=>'']);
if ($validator->fails())
{
throw new ExistingUserException($validator);
}
Create a new middleware in app/Http/Middleware/CatchExistingUser.php
<?php
namespace App\Http\Middleware;
use App\Exceptions\ExistingUserException;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\URL;
class CatchExistingUser
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next, $redirectToRoute = null)
{
$response = $next($request);
if ($response->exception && $response->exception instanceof ExistingUserException)
{
return $request->expectsJson()
? abort(403, 'Your email address is not verified.')
: Redirect::guest(URL::route($redirectToRoute ?: 'verification.notice'));
}
return $response;
}
}
Inject the middleware into all fortify routes via config/fortify.php
'middleware' => [CatchExistingUser::class, 'web'],
Remove the auth middleware from the verification page by overwriting the route in routes/web.php
use Illuminate\Http\Request;
use Laravel\Fortify\Contracts\VerifyEmailViewResponse;
...
Route::get('/email/verify', function (Request $request) {
$user = $request->user();
if ($user && $user->hasVerifiedEmail())
{
return redirect()->intended(config('fortify.home'));
}
return app(VerifyEmailViewResponse::class);
})
->name('verification.notice');
The custom exception is not ideal but it seems cleaner than testing the validator stored in the ValidatorException and then removing one message if there's more than one error. I think this would be needed to allow the validation of other fields while not leaking email uniqueness.

Why this protected function create(Array $data) and not this protected function create(Request $data)?

I created a registration form with the use of laravel ui scaffolding.
What I did:
• Added some field besides the default ones
• Using the auth controller specifically RegisterController and change a part of the create function from this
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
Into this:
protected function create(array $data)
{
return User::create([
'user_email' => $data['email'],
'user_Type' => $data['user_Type'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'contact_number' => $data['contact_number'],
]);
}
But the result after submitting the form with a post method is this:
ArgumentCountError
Too few arguments to function App\Http\Controllers\Auth\RegisterController::create(), 0 passed in /Users/idan/Documents/SweetSurrender/vendor/laravel/framework/src/Illuminate/Routing/Controller.php on line 54 and exactly 1 expected
Web.php
Route::get('/register', function() {
return view('auth.register');
})->name('register');
Route::post('/register', [RegisterController::class, 'create']);
RegisterController.php
<?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
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
public function index() {
return view('auth.register');
}
protected function validator(array $data)
{
return Validator::make($data, [
'username' => ['required', 'string', 'max:16'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'contact_number' => ['required', 'string', 'min:12', 'unique:users'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\Models\User
*/
protected function create(array $data)
{
return User::create([
'user_email' => $data['email'],
'user_Type' => $data['user_Type'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'contact_number' => $data['contact_number'],
]);
}
}
I also tried using this in RegisterController.php
protected function create(Request $data)
{
return User::create([
'user_email' => $data->input('email'),
'user_Type' => $data->input('user_Type'),
'username' => $data->input('username'),
'password' => Hash::make($data->input('password')),
'contact_number' => $data->input('contact_number'),
]);
}
but it results to an error:
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1364 Field 'user_email' doesn't have a default value (SQL: insert into users (password, updated_at, created_at) values ($2y$10$vr7UasRBCzx2URQxLSWneuvr4Hl1at.q7qDk8UK0Wc/INjeHeYH7y, 2020-12-22 07:15:41, 2020-12-22 07:15:41))
I solved this problem by using the same code:
protected function create(array $data)
{
return User::create([
'user_email' => $data['email'],
'user_Type' => $data['user_Type'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'contact_number' => $data['contact_number'],
]);
}
and In the User model I included this:
protected $fillable = [
'username',
'user_email',
'password',
'contact_number',
];

Laravel 7 redirect issues

I'm trying to redirect with a message to a view ( notification ) after the form is successfully validated / stored and emailed.
Everything Works as expected but unable to redirect after the email is sent.
Tried redirecting after form validation and it works. But if i call the store() and try to redirect after save() it does not redirect.
I though maybe something was wrong with my store() function so i created an empty function test() and tried redirecting if like this
public function test($request){
Session::flash('message', 'alert-danger');
return Redirect::to('/notifications');
}
public function test(){
Session::flash('message', 'alert-danger');
return Redirect::to('/notifications');
}
It still does not work.
but if redirect from validator() it works fine.
I don't know what is wrong. Please help.
<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use App\Mail\RegistrationMail;
use Illuminate\Support\Facades\Mail;
use App\Register;
use Illuminate\Support\Facades\URL;
use Session;
use Illuminate\Support\Facades\Redirect;
class RegisterController extends Controller
{
protected function store(Request $request){
$length = 16;
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$code = substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
$user = new Register();
$user->fname = request('fname');
$user->mname = request('mname');
$user->lname = request('lname');
$user->email = request('email');
$user->kathum_tui = $code;
$user->created = \Carbon::now();
$vfname = request('fname');
$vlname = request('lname');
$vemail = request('email');
$url = URL::temporarySignedRoute('verify', now()->addMinutes(1500), ['fname' => $vfname ,'lname'=> $vlname , 'email'=> $vemail]);
$user->save();
Mail::to($user['email'])->send(new RegistrationMail($user,$url));
Session::flash('message', 'alert-danger');
return Redirect::to('/notifications');
}
protected function validator(Request $request)
{
$validator = Validator::make($request->all(),[
'email' => ['required', 'string', 'email', 'max:255', 'unique:registers'],
]);
if ($validator->fails()) {
$request->validate( [
'fname' => ['required', 'string', 'max:255'],
'mname' => ['nullable','string', 'max:255'],
'lname' => ['required', 'string', 'max:255'],
],
[
'fname.required' => 'First Name Cannot be empty!',
'lname.required' => 'Last Name Cannot be empty!',
'email.unique' => 'You have not completed the Registration. Please check your email to complete the Registration.',
]
);
}else{
$request->validate( [
'fname' => ['required', 'string', 'max:255'],
'mname' => ['nullable','string', 'max:255'],
'lname' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:registers'],
],
[
'fname.required' => 'First Name Cannot be empty!',
'lname.required' => 'Last Name Cannot be empty!',
'email.unique' => 'An account already Exist with this email. Forgot Password',
]
);
$this->store($request);
}
}
}
You should return your store method call in the validator function like as following:
return $this->store($request);

Laravel 5.8 register redirect

I'm using Laravel 5.8, still new to PHP and Laravel. When I register, it returns the user in JSON format which is normal from the Register Users.php register function. However, I have a redirectTo() function which should take care of the redirect and redirect the user to some pages a specified, but it's not working. I've tried overriding the redirectPath() function as well which isn't working.
The redirect works perfectly for the login controller.
Any solution or pointers would be appreciated. See RegisterController below.
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
use Auth;
class RegisterController extends Controller
{
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
//public $redirectTo = '/home';
protected function redirectPath()
{
$role = Auth::user()->role;
if ($role === 'candidate') {
return '/candidate_dashboard';
} elseif ($role === 'employer') {
return '/employer_dashboard';
} elseif ($role === 'contractor') {
return '/contractor_dashboard';
}
}
public function __construct()
{
$this->middleware('guest');
}
protected function validator(array $data)
{
try {
return Validator::make($data, [
'first_name' => ['required', 'string', 'max:255'],
'last_name' => ['required', 'string', 'max:255'],
'role' => ['required', 'string', 'max:50'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
} catch (Illuminate\Database\QueryException $th) {
return back()->withError($th->getMessage())->withInput();
}
}
protected function create(Request $data)
{
try {
return User::create([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'role' => $data['role'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
} catch (Illuminate\Database\QueryException $th) {
return back()->withError($th->getMessage())->withInput();
}
}
}

Method App\Http\Controllers\Auth\RegisterController::validator does not exist

I am trying to do registration of multi-user in my registration controller and used the following code and checked. But it shows me error:
Method App\Http\Controllers\Auth\RegisterController::validator does not exist.
<?php
namespace App\Http\Controllers\Auth;
use App\Admin;
use App\Manager;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
class RegisterController extends Controller
{
use RegistersUsers;
public function __construct()
{
$this->middleware('guest');
$this->middleware('guest:admin');
$this->middleware('guest:manager');
}
protected function createAdmin(Request $request)
{
$this->validator($request->all())->validate();
$admin = Admin::create([
'name' => $request['name'],
'email' => $request['email'],
'password' => Hash::make($request['password']),
]);
return redirect()->intended('login/admin');
}
protected function createManager(Request $request)
{
$this->validator($request->all())->validate();
$manager = Manager::create([
'name' => $request['name'],
'email' => $request['email'],
'password' => Hash::make($request['password']),
]);
return redirect()->intended('login/manager');
}
}
Try to add validator() function like follow:
protected function validator(array $data, $table)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:'.$table],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
then you can make validation like so:
$this->validator($request->all(), 'table_name')->validate();
change table_name with corresponding name.

Resources