Laravel- Creating new user only if there is data in another table - php

I have two tables the first one is the user table which have these property id, username, email,remember_token, createdat, updateat another table is called received_pay having id, email, token my task is to check if the email, and token entered by the user must match the ones in received_pay otherwise new user is not created, thanks for your time in advanced,
I'm trying to create new user on a condition that if there is data in another table then new user is created otherwise not I have put my code inside if else statement and is throwing errors.
my function for creating new user is listed below:
protected function create(array $data)
{
/*$exists = \DB::table('received_pay')->where('email', $data['email'])->first(); */
$exists=\DB::table('received_pay')->where('email', '=', $data['email'])->where('token', $data['token'])->exists();
if ($exists === null)
{
// user doesn't exist
return User::create([
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'token' => $data['token'],
]);
}
else
{
return null;
}
}

I think that the best approach in Laravel is create a middleware to protect this url. If you already have this create user feature working is better don't modify it.
So the first step would be create a middleware (https://laravel.com/docs/5.5/middleware) to add your safeguard, something like this:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckPayment
{
public function handle($request, Closure $next)
{
$payment = \DB::table('received_pay')->where('email', $request->email)->where('token', $request->token]);
if (!$payment->count()) {
return redirect('no-payment');
}
return $next($request);
}
}
Then you would need to create a route to handle this invalid creation users (this no-payment url).
And finally you can protect your create-user url in route, by adding your middleware in your kernel.php file...
protected $routeMiddleware = [
...
'payment' => \App\Http\Middleware\CheckPayment::class,
];
and in your web.php route file:
Route::post('user', 'UserController#create')->middleware('payment');
In this way your code will look cleaner, tidier, and closer to the way Laravel works.
I hope it would work fine for you.

If you wish to do it with if statement then do it like below
protected function create(array $data)
{
/*$exists = \DB::table('received_pay')->where('email', $data['email'])->first(); */
$exists=\DB::table('received_pay')->where('email', '=', $data['email'])->where('token', $data['token']);
if (!$exists->count())
{
// user doesn't exist
return User::create([
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'token' => $data['token'],
]);
}
else
{
return null;
}
}
the count() in the if is to make the statement evaluate true if the data exists and false otherwise and create the new user.
I think that solves your problem.

Related

Check if record exists while registering user

In my Register controller - I have the following method to check if a record exists in another table before creating a user:
public function getCompanyDetails($id)
{
$details = Company::where('company_id', $id)->first();
return $details;
}
protected function create(array $data)
{
$company_id = $data['com_id'];
$company_details = $this->getCompanyDetails($company_id);
if ($company_details == null) {
return redirect()
->back()
->with('warning', 'We could not find the company');
} else {
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
However when the company record is not found. I'm getting the following error message:
Cannot use object of type Illuminate\Http\RedirectResponse as an array
I believe it's expecting a return of type user. But how can I redirect back to the registration page if the company is not found?
Thanks in Advance
Try the method withErrors():
Redirect::back()->withErrors(['warning', 'We could not find the company']);
I however recommend you to use the validation rule Exists instead of having more queries and manually return a message. You can do it like so:
$request->validate([
'company_id' => 'required|integer|exists:App\Company,id',
]);
Then you won't need the extra logic and the other method.
Source: https://laravel.com/docs/7.x/validation#rule-exists

How can I login the user manually in Laravel?

Here is my code:
public function register_and_login(Request $request)
{
$this->validator_short($request->all())->validate();
$user = User::where('cell_phone', $request->cell_phone)->first();
// already registered
if ( is_null($user) ) {
$user_id = User::create([
'name' => $request->name,
'cell_phone' => $request->cell_phone,
'password' => bcrypt($request->password),
]);
} else {
$user_id = $user->id;
}
$this->guard()->login($user_id);
dd('user is logged in now');
}
My code works when the user isn't registered so far and we create it. But when he has registered already, my code throws this error:
How can I fix it?
Make sure the User model extends Authenticatable:
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
Also, use auth() helper or Auth:: facade:
$user = User::create(['name' => $request->name,
'cell_phone' => $request->cell_phone,
'password' => bcrypt($request->password)
]);
auth()->login($user);
https://laravel.com/docs/5.5/authentication#other-authentication-methods
Change your else part to -
else {
$user_id = $user;
}
The login function is not asking you for an integer id, it's asking for an Authenticable. In any default Laravel application, that's usually the User Model.
The problem lies in your else statement. You don't need to set $user_id to the id of the user you loaded when checking the cell number. You just need to use the user you loaded. Based on your logic, you don't even need the else statement.
A possible separate issue with your logic,is that you're checking to see if the cell number exists, and if it does, logging in that user, not the user that your doing the check for. This may be desired behaviour, but it doesn't seem like.
public function register_and_login(Request $request)
{
$this->validator_short($request->all())->validate();
$user = User::where('cell_phone', $request->cell_phone)->first();
// already registered
if ( is_null($user) ) {
$user = User::create([
'name' => $request->name,
'cell_phone' => $request->cell_phone,
'password' => bcrypt($request->password),
]);
}
$this->guard()->login($user);
}

How to save multiple related models at the same time

In my RegistrationController#store, I am doing the following:
Create a user (User: hasMany() Points, hasOne() Profile, belongsToMany() Role)
Attach a role (Role: belongsToMany() User)
Create a profile (Profile: belongsTo() User)
Set initial score to 0 (Points: belongsTo() User)
I realized if one of these steps fails, for example if due to slow connectivity the profile is somehow not created, my app will break. Here is my store method:
public function store(){
$profile = new Profile();
$points = new Points();
$this->validate(request(),[
'name' => 'required',
'username' => 'required|unique:users',
'email' => 'required|email|unique:users',
'password' => 'required|confirmed',
'role_id' => 'required|between:1,2'
]);
$user = User::create([
'name' => request('name'),
'username' => request('username'),
'email' => request('email'),
'password' => bcrypt(request('password'))
]);
$role_student = Role::where('title', 'Student')->first();
$role_parent = Role::where('title', 'Parent')->first();
if(request()->input('role_id') == 1){
$user->roles()->attach($role_student);
} else if(request()->input('role_id') == 2){
$user->roles()->attach($role_parent);
}
$profile->user_id = $user->id;
$profile->date_of_birth = Carbon::createFromDate(request('year'),request('month'),request('day'));
$profile->institution = request('institution');
$profile->class = request('class');
$profile->division = request('division');
$profile->photo = 'propic/default.png';
$profile->bio = 'I am a Member!';
$profile->social_link = 'http://facebook.com/zuck';
$profile->save();
auth()->login($user);
\Mail::to($user)->send(new Welcome($user));
$points->updateOrCreateAndIncrement(0);
return redirect()->home();
}
It is worth mentioning that, all of the data is coming from a registration form. How can I execute all these steps at a time (or, in one statement) so that if the statement executes successfully, I will have a perfectly synchronized registration, otherwise, no data will be persisted to the database?
Use transactions.
Before the first DB operation, in your case: User::create, use this:
DB::beginTransaction();
From now on, put all of your db operations in try/catch braces and if any exception happens, use:
DB::rollBack();
And at the end of the function, before return statement, put this:
DB::commit();
If you can have all your operations in the same place, it's easier to do this:
DB::transaction(function () {
//all your db opertaions
}, 2);

Laravel creating a new user from within a controller

How can I invoke the create method to register a user from within a controller.
A user will already be logged in when register the new user.
When doing:
User::create([
...
]);
The password is not hashed, so the register procedure must be done with another method call. In the postRegister method used by the default register process, there is this line
Auth::login($this->create($request->all()));
So how can I invoke
$this->create($request->all())
From with my custom controller and what parameters does it require.
Any ideas
An thanks in advance for any feedback.
/**
* Invites a new user to the current users company.
* #param Request $request
* #return mixed
*/
public function employeeInvite(Request $request) {
$this->validate($request, [
'email' => 'required|email',
]);
// TODO: Check user is authorized to send invites
$user = $this->users->getUserByEmail($request->email); // get user
if($this->userExists($user)
&& $request->user()->email != $request->email
&& $this->userHasInvite($user->id, $request->user()->company_id) == false)
{
// send invite
if($this->sendInvite($request->user()->company_id, $user->id)) {
// if worked, create succses method to send back to the user
}
} else
{
// create user
$userData = [
'email' => $request->email,
'password' => $this->random_password(6),
];
$newUser = User::create($userData);
// send invite
$this->sendInvite($request->user()->company_id, $userData->id);
}
return redirect('members/company');
} // end function employeeInvite
The User::create() method doesn't hash passwords by itself, so you will have to do it yourself.
Laravel's hashing function is bcrypt(), so your $userData array should look like this:
$userData = [
'email' => $request->email,
'password' => bcrypt($this->random_password(6)),
];

How to assign default user role in entrust?

I just want to assign a role to newly registered user. How I can achieve this in Laravel 5 with Entrust? I am using Entrust for roles and permissions.
Last time I tried to fire event after user registration in a file in vendor folder. Is there any way to fire an event for role assignment without modifying anything inside vendor folder?
If yes then where should I fire event? I don't want to modify anything inside my vendor folder like firing event in postRegister() in AuthenticatesAndRegistersUsers.php because new updates will overwrite my code.
Code on this link looks good but I don't know entrust has registration event or not.
http://laravel.io/forum/07-02-2014-entrust-assign-role-on-user-signup
Here is my code in routes.php:
// this event is firing on user login and i am getting user object
Event::listen('auth.login', function($user) {
var_dump($user);
die(__LINE__);
});
// this event is not firing on user registration
Event::listen('auth.register', function($user) {
var_dump($user);
die(__LINE__);
// $donor_role = DB::table('app_roles')->where('name', '=', 'donor')->pluck('id');
// $user->roles()->attach($donor_role);
// return false;
});
Please help me out.
App\Service\Registrar.php
This is my way:
public function create(array $data)
{
$create = User::create([
'username' => $data['username'],
'email' => $data['email'],
'password' => $data['password'],
]);
$user = User::find($create->id);
$role = Role::where('name', '=', 'user')->firstOrFail();
$user->roles()->attach($role->id);
return $create;
}
I figured it out all by myself. Here is how I achieved:
I copied postRegister() function from /vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesAndRegistersUsers.php and overridden in /app/Http/Controllers/Auth/AuthController.php with some modification.
Here is the modified function in AuthController.php:
public function postRegister(Request $request) {
$validator = $this->registrar->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
$this->auth->login($this->registrar->create($request->all()));
// little modification :-)
\Event::fire('auth.assign_default_role', $this->auth->user());
return redirect($this->redirectPath());
}
And here is the event listener in routes.php:
Event::listen('auth.assign_default_role', function($user) {
$donor_role = DB::table('app_roles')->where('name', '=', 'donor')- >pluck('id');
$user->roles()->attach($donor_role);
return false;
});
You can fire the register event from your controller where the actual signup is being handled.
Event::fire('auth.register', array($user));
In Laravel 5.7+ you can go to the RegisterController and modify the create function:
protected function create(array $data) {
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$default_role = Role::where('name', 'DEFAULT_ROLE_NAME')->first();
$user->attachRole($default_role);
return $user;
}
Don't forget to use App\Models\Role; in the beginning.

Categories