laravel 5.4 - comparing user input to db value - php

I have utilized laravel's make:auth and was playing around with the registration part. I am trying to compare the user's input to the values that I already have in my database, if it exist then the user would proceed to the registration and if doesn't, it would take the user to another page. Now, after executing the function, it would directly take the user to another page. What seems to be the problem?
public function register(Request $request)
{
$name = $request->name;
$lastname = $request->lastname;
$check = DB::table('records')->where([
['firstname','=',$name],
['lastname','=',$lastname]
])->get();
if ($check===null) {
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
} else {
return redirect('/');
}
}

get() method returns an collection, so if there is no record $check would be similar to
$a = collect([]);
and
$a === null // returns false
$a->isEmpty(); // returns true
count($a); // returns 0
so you might want to use a different comparison in your if clause and this would be
if it exist then the user would proceed to the registration
if (!$check->isEmpty()) {
// proceed to registration
} else {
// redirect
}

Related

Cant test if a database boolean is true in Laravel

I am trying to query our database to see if users can log in based on whether the organisation they belong to have logins enabled.
LoginController.php
protected function redirectTo()
{
$user = Auth::user()->id;
$userOrg = UserOrganization::where('user_id', $user)->first();
$org = Organization::where('id', $userOrg->org_id)->first();
if ($org->allow_org_login == 0) {
return '/login';
} else {
if(Auth::user()->has_changed_temp_password == false)
{
DB::table('users')->where('id', $user)->update(['last_login' => Carbon::now()]);
DB::table('users')->where('id', $user)->increment('total_logins');
return '/user/password/change';
} else {
DB::table('users')->where('id', $user)->update(['last_login' => Carbon::now()]);
DB::table('users')->where('id', $user)->increment('total_logins');
return '/overview';
}
}
}
trying to log in as a user belonging to an organisation with allow_org_login = 0 should redirect to the '/login' page, but instead it either logs the user in or prompts for a password change for a new user.
What am I doing wrong?
Edit: Debug contents of $org (allow_org_login on the bottom line)
since there is many to many relation between user and organization.
i suppose this relation is defined in User & Organization as in documentation:
https://laravel.com/docs/7.x/eloquent-relationships#many-to-many
considering that:
user may have more than an organization, and if any of the organization allowed log_in the user should login to your system
$user = Auth::user();
$userOranization=$user->organizations()->get();
$allowUserToLogin=false;
if($userOranization->where('allow_org_login',1)->first()!=null)
$allowUserToLogin=true;
and then:
if ($allowUserToLogin == 0) {
return '/login';
} else { ....
for redirectTo() method it will only fire when we using POST method for login.
inside you redirectTo() method your check condition and then you return '/login';
which it will redirectTo login page. but this time you already login then on login it will check if user login then it redirectTo url that we config on LoginController and protected $redirectTo; it will not call redirectTo() method. cuz this time we use redirect using GET method not POST.
if you want to put validate on redirectTo() method you can try below code:
protected function redirectTo()
{
$user = Auth::user()->id;
$userOrg = UserOrganization::where('user_id', $user)->first();
$org = Organization::where('id', $userOrg->org_id)->first();
if ($org->allow_org_login == 0) {
Auth::logout(); // logout user before redirect
return '/login';
} else {
if(Auth::user()->has_changed_temp_password == false)
{
// depend on you choice need to logout or not
DB::table('users')->where('id', $user)->update(['last_login' => Carbon::now()]);
DB::table('users')->where('id', $user)->increment('total_logins');
return '/user/password/change';
} else {
// depend on you choice need to logout or not
DB::table('users')->where('id', $user)->update(['last_login' => Carbon::now()]);
DB::table('users')->where('id', $user)->increment('total_logins');
return '/overview';
}
}
}
but for my option i will create new middleware for handle this.

Check users role Laravel

After a user enters his credential and tries to login and after the user is found, we have a siterole table that will be checked, if the role that the user selected is found in the database "where userID=request and roleType = request" then the login is successful otherwise it fails due to choosing the wrong user role.
The code is simple:
$findrole = $request->role;
$user_id = Auth::user()->id;
$userrole = DB::table('siterole')->where('role_id' ,'=',$findrole)->where('user_id' ,'=', $user_id)->get();
if(!empty($userrole)) {
make it login
}
else{
redirect it with a fail login
}
By failed login I mean no session should be set, where I tried this code was in
vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php
BUT when the "role_id" is not found for that "user_Id", the user is logged in and redirected to the wrong page!
Edit the function Im putting my code in is this :
public function login(Request $request)
{
$this->validateLogin($request);
$throttles = $this->isUsingThrottlesLoginsTrait();
if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
$credentials = $this->getCredentials($request);
if (Auth::guard($this->getGuard())->attempt($credentials, $request->has('remember'))) {
//MYCODE GOES BETWEEN THESE LINES
if its not empty return the below code
return $this->handleUserWasAuthenticated($request, $throttles);
}
if ($throttles && ! $lockedOut) {
$this->incrementLoginAttempts($request);
}
//if its empty return to this section
return $this->sendFailedLoginResponse($request);
}
Auth::user()->id returns the user id only when you are authenticated. In line 2 of your example code, when you are creating the $user_id variable you are not authenticated yet so it will always be null. You'll need to get the user_id another way.
Found the solution, so where i was putting my condition is where laravel already returned a login = true, so i cant do anything.
that attemp() is actually attempting the login which is located in :
vendor\laravel\framework\src\Illuminate\Auth\SessionGuard.php
now in attemp function we dont have access to our request but we can pass the User type i call it (role) in function getCredentials which is located in :
vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php
Step 1:
protected function getCredentials(Request $request)
{
//sending role as credential too
// my input name was role
return $request->only($this->loginUsername(), 'password','role');
}
Now since we passed it in attemp() , its the 2nd array of our credentials BUT we have to unset it from the main credentials because laravel will create a where clause for each key in array :
Step 2
public function attempt(array $credentials = [], $remember = false, $login = true)
{
//get the user roll to check if the user has the same role
//else kill him #Stormspirit
$user_role = $credentials['role'];
//as laravel make the where clause for every field we unset it from the array
unset($credentials['role']);
$this->fireAttemptEvent($credentials, $remember, $login);
$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
// If an implementation of UserInterface was returned, we'll ask the provider
// to validate the user against the given credentials, and if they are in
// fact valid we'll log the users into the application and return true.
if ($this->hasValidCredentials($user, $credentials)) {
//user credential was valid check the role part
$userrole_finder = DB::table('siterole')->where('role_type',$user_role)->where('user_id',$user->id)->get();
if($userrole_finder==[]) {
$login = false;
return false;
}
if ($login) {
$this->login($user, $remember);
}
return true;
}
All set! dont forget to add use DB; check your user role table and if it was empty make the login false and return false that would do the rest and u will see laravel's invalid credential error.
You can implement this for user type I just called it role.you can also put the user type in a session in handleUserWasAuthenticated function in AuthenticatesUsers.php , exact location described above
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
session(['user_role' => $request->role]);
if ($throttles) {
$this->clearLoginAttempts($request);
}
if (method_exists($this, 'authenticated')) {
return $this->authenticated($request, Auth::guard($this->getGuard())->user());
}
return redirect()->intended($this->redirectPath());
}

Check if laravel model got saved or query got executed

I've seen alot of people using this way to check if a laravel model got saved. So now I wonder if it is a safe way.
And also can I check if the queries bellow got executed like this
Check if model got saved
Eg:
$myModel = new User();
$myModel->firstname = Input::get('firstname');
$myModel->lastname = Input::get('lastname');
$myModel->save();
//Check if user got saved
if ( ! $myModel->save())
{
App::abort(500, 'Error');
}
//User got saved show OK message
return Response::json(array('success' => true, 'user_added' => 1), 200);
Is the above a safe way to check whenever my model got saved or not?
Check if query returned a result
Eg:
$UserProduct = Product::where('seller_id', '=', $userId)->first();
if (! $UserProduct)
{
App::abort(401); //Error
}
Does above return an error if no product where found?
Check if query got executed
Eg:
$newUser = User::create([
'username' => Input::get('username'),
'email' => Input::get('email')
]);
//Check if user was created
if ( ! $newUser)
{
App::abort(500, 'Some Error');
}
//User was created show OK message
return Response::json(array('success' => true, 'user_created' => 1), 200);
Does above check if a user was created?
Check if model got saved
save() will return a boolean, saved or not saved. So you can either do:
$saved = $myModel->save();
if(!$saved){
App::abort(500, 'Error');
}
Or directly save in the if:
if(!$myModel->save()){
App::abort(500, 'Error');
}
Note that it doesn't make sense to call save() two times in a row like in your example. And by the way, many errors or problems that would keep the model from being saved will throw an exception anyways...
Check if query returned a result
first() will return null when no record is found so your check works find. However as alternative you could also use firstOrFail() which will automatically throw a ModelNotFoundException when nothing is found:
$UserProduct = Product::where('seller_id', '=', $userId)->firstOrFail();
(The same is true for find() and findOrFail())
Check if query got executed
Unfortunately with create it's not that easy. Here's the source:
public static function create(array $attributes)
{
$model = new static($attributes);
$model->save();
return $model;
}
As you can see it will create a new instance of the model with the $attributes and then call save(). Now if save() where to return true you wouldn't know because you'd get a model instance anyways. What you could do for example is check for the models id (since that's only available after the record is saved and the newly created id is returned)
if(!$newUser->id){
App::abort(500, 'Some Error');
}
You can also check the public attribute $exists on your model.
if ($myModel->exists) {
// Model exists in the database
}
I would do such move to when I use Model::create method :
$activity = Activity::create($data);
if ($activity->exists) {
// success
} else {
// failure
}
As for the Save method it's easier because $model->save() returns Bool :
$category = new Category();
$category->category_name = $request->category_name;
$is_saved = $category->save();
if ($is_saved) {
// success
} else {
// failure
}
/**
* Store a newly created country in storage.
*
* #url /country
* #method POST
* #param Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function store(Request $request)
{
# Filer & only get specific parameters.
$request = $request->only('code', 'name', 'status');
# Assign login user(Auth Control).
$request['created_by'] = Auth::user()->id;
# Insert data into `countries` table.
$country = Country::create($request);
if(!$country)
throw new Exception('Error in saving data.');
}

Laravel Checking If a Record Exists

I am new to Laravel. How do I find if a record exists?
$user = User::where('email', '=', Input::get('email'));
What can I do here to see if $user has a record?
It depends if you want to work with the user afterwards or only check if one exists.
If you want to use the user object if it exists:
$user = User::where('email', '=', Input::get('email'))->first();
if ($user === null) {
// user doesn't exist
}
And if you only want to check
if (User::where('email', '=', Input::get('email'))->count() > 0) {
// user found
}
Or even nicer
if (User::where('email', '=', Input::get('email'))->exists()) {
// user found
}
if (User::where('email', Input::get('email'))->exists()) {
// exists
}
In laravel eloquent, has default exists() method, refer followed example.
if (User::where('id', $user_id )->exists()) {
// your code...
}
One of the best solution is to use the firstOrNew or firstOrCreate method. The documentation has more details on both.
if($user->isEmpty()){
// has no records
}
Eloquent uses collections.
See the following link: https://laravel.com/docs/5.4/eloquent-collections
Laravel 5.6.26v
to find the existing record through primary key ( email or id )
$user = DB::table('users')->where('email',$email)->first();
then
if(!$user){
//user is not found
}
if($user){
// user found
}
include " use DB " and table name user become plural using the above query like user to users
if (User::where('email', 'user#email.com')->first()) {
// It exists
} else {
// It does not exist
}
Use first(), not count() if you only need to check for existence.
first() is faster because it checks for a single match whereas count() counts all matches.
It is a bit late but it might help someone who is trying to use User::find()->exists() for record existence as Laravel shows different behavior for find() and where() methods. Considering email as your primary key let's examine the situation.
$result = User::find($email)->exists();
If a user record with that email exists then it will return true. However the confusing thing is that if no user with that email exists then it will throw an error. i.e
Call to a member function exists() on null.
But the case is different for where() thing.
$result = User::where("email", $email)->exists();
The above clause will give true if record exists and false if record doesn't exists. So always try to use where() for record existence and not find() to avoid NULL error.
This will check if requested email exist in the user table:
if (User::where('email', $request->email)->exists()) {
//email exists in user table
}
In your Controller
$this->validate($request, [
'email' => 'required|unique:user|email',
]);
In your View - Display Already Exist Message
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Checking for null within if statement prevents Laravel from returning 404 immediately after the query is over.
if ( User::find( $userId ) === null ) {
return "user does not exist";
}
else {
$user = User::find( $userId );
return $user;
}
It seems like it runs double query if the user is found, but I can't seem to find any other reliable solution.
if ($u = User::where('email', '=', $value)->first())
{
// do something with $u
return 'exists';
} else {
return 'nope';
}
would work with try/catch
->get() would still return an empty array
$email = User::find($request->email);
If($email->count()>0)
<h1>Email exist, please make new email address</h1>
endif
Simple, comfortable and understandable with Validator
class CustomerController extends Controller
{
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:customers',
'phone' => 'required|string|max:255|unique:customers',
'password' => 'required|string|min:6|confirmed',
]);
if ($validator->fails()) {
return response(['errors' => $validator->errors()->all()], 422);
}
I solved this, using empty() function:
$user = User::where('email', Input::get('email'))->get()->first();
//for example:
if (!empty($user))
User::destroy($user->id);
you have seen plenty of solution, but magical checking syntax can be like,
$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();
it will automatically raise an exception with response 404, when not found any related models Sometimes you may wish to throw an exception if a model is not found. This is particularly useful in routes or controllers. The fingernail and firstOrFail methods will retrieve the first result of the query; however, if no result is found, an Illuminate\Database\Eloquent\ModelNotFoundException will be thrown.
Ref: https://laravel.com/docs/5.8/eloquent#retrieving-single-models
$user = User::where('email', request('email'))->first();
return (count($user) > 0 ? 'Email Exist' : 'Email Not Exist');
This will check if particular email address exist in the table:
if (isset(User::where('email', Input::get('email'))->value('email')))
{
// Input::get('email') exist in the table
}
Shortest working options:
// if you need to do something with the user
if ($user = User::whereEmail(Input::get('email'))->first()) {
// ...
}
// otherwise
$userExists = User::whereEmail(Input::get('email'))->exists();
$user = User::where('email', '=', Input::get('email'))->first();
if ($user === null) {
// user doesn't exist
}
can be written as
if (User::where('email', '=', Input::get('email'))->first() === null) {
// user doesn't exist
}
This will return true or false without assigning a temporary variable if that is all you are using $user for in the original statement.
I think below way is the simplest way to achieving same :
$user = User::where('email', '=', $request->input('email'))->first();
if ($user) {
// user exist!
}else{
// user does not exist
}
Created below method (for myself) to check if the given record id exists on Db table or not.
private function isModelRecordExist($model, $recordId)
{
if (!$recordId) return false;
$count = $model->where(['id' => $recordId])->count();
return $count ? true : false;
}
// To Test
$recordId = 5;
$status = $this->isModelRecordExist( (new MyTestModel()), $recordId);
Home It helps!
The Easiest Way to do
public function update(Request $request, $id)
{
$coupon = Coupon::where('name','=',$request->name)->first();
if($coupon->id != $id){
$validatedData = $request->validate([
'discount' => 'required',
'name' => 'required|unique:coupons|max:255',
]);
}
$requestData = $request->all();
$coupon = Coupon::findOrFail($id);
$coupon->update($requestData);
return redirect('admin/coupons')->with('flash_message', 'Coupon updated!');
}
Laravel 6 or on the top: Write the table name, then give where clause condition for instance where('id', $request->id)
public function store(Request $request)
{
$target = DB:: table('categories')
->where('title', $request->name)
->get()->first();
if ($target === null) { // do what ever you need to do
$cat = new Category();
$cat->title = $request->input('name');
$cat->parent_id = $request->input('parent_id');
$cat->user_id=auth()->user()->id;
$cat->save();
return redirect(route('cats.app'))->with('success', 'App created successfully.');
}else{ // match found
return redirect(route('cats.app'))->with('error', 'App already exists.');
}
}
If you want to insert a record in the database if a record with the same email not exists then you can do as follows:
$user = User::updateOrCreate(
['email' => Input::get('email')],
['first_name' => 'Test', 'last_name' => 'Test']
);
The updateOrCreate method's first argument lists the column(s) that uniquely identify records within the associated table while the second argument consists of the values to insert or update.
You can check out the docs here: Laravel upserts doc
You can use laravel validation if you want to insert a unique record:
$validated = $request->validate([
'title' => 'required|unique:usersTable,emailAddress|max:255',
]);
But also you can use these ways:
1:
if (User::where('email', $request->email)->exists())
{
// object exists
} else {
// object not found
}
2:
$user = User::where('email', $request->email)->first();
if ($user)
{
// object exists
} else {
// object not found
}
3:
$user = User::where('email', $request->email)->first();
if ($user->isNotEmpty())
{
// object exists
} else {
// object not found
}
4:
$user = User::where('email', $request->email)->firstOrCreate([
'email' => 'email'
],$request->all());
$userCnt = User::where("id",1)->count();
if( $userCnt ==0 ){
//////////record not exists
}else{
//////////record exists
}
Note :: Where condition according your requirements.
Simply use this one to get true or false
$user = User::where('email', '=', Input::get('email'))->exists();
if you want $user with result you can use this one,
$user = User::where('email', '=', Input::get('email'))->get();
and check result like this,
if(count($user)>0){}
Other wise you can use like this one,
$user = User::where('email', '=', Input::get('email'));
if($user->exists()){
$user = $user->get();
}
The efficient way to check if the record exists you must use is_null method to check against the query.
The code below might be helpful:
$user = User::where('email', '=', Input::get('email'));
if(is_null($user)){
//user does not exist...
}else{
//user exists...
}
It's simple to get to know if there are any records or not
$user = User::where('email', '=', Input::get('email'))->get();
if(count($user) > 0)
{
echo "There is data";
}
else
echo "No data";

Passing Data to view in a Redirect request to prevent double submission

I am trying to prevent double submission through the back button in a simple voting application
I was doing this before. After voting it returns this view
return View::make('votes.votesresults')->with('candidates',$candidates)->with('count',$count);
This passes two variables to votesresult view but unfortunately if someone clicks the back button they can resubmit their votes. I looked around and came across the PRG pattern. Am supposed to use a redirect to prevent this. So i tried this
return Redirect::route('votes.votesresults')->with('candidates',$candidates)->with('count',$count);
Here are my controllers
public function votesuccess()
{
$rules = array(
'name' => 'required'
);
$validator = Validator::make(Input::all(),$rules);
if ($validator->fails()) {
return Redirect::to('votes/index')
->withErrors($validator)
->withInput(Input::except('password'));
} else {
// store
$vote = new Vote;
$candidates = Candidate::all();
$candidate_id =Input::get('name');
$candidate = Candidate::find($candidate_id);
$vote = $candidate->votes()->save($vote);
//$count = DB::table('votes')->where('candidate_id','=','$candidate_id')->count();
$count = DB::table('votes')->count();
// redirect
Session::flash('message', 'Successfully Cast your vote!');
//return View::make('votes.voteresults')->with('candidates', $candidates)->with('count',$count);
return Redirect::route('voteresults')->with('candidates', $candidates)->with('count',$count);
}
}
public function voteresult()
{
$candidates = Candidate::all();
return View::make('votes.voteresults');
}
My routes are like this
Route::post('votesuccess', array('as' => 'votesuccess', 'uses'=>'VoteController#votesuccess'));
Route::get('voteresults', array('as' => 'voteresults', 'uses'=>'VoteController#voteresult'));
This does not work because it returns undefined variable: candidates. My results view requires these variables. So how do I implement the PRG pattern correctly such that I prevent double submission while being able to pass data to my view
You are redirecting to the route named voteresults, which is handled by the voteresult function and not the votesuccess function.
In your votesuccess function, you should load the view and include the candidates variable in that view. You can access the candidates variable stored in the session by using Session::get('candidates').
It would help to see you voter results view to see what's going on there, and where/how you've put in logic to avoid duplicate submission. Are you concerned about accidental re-submissions, or just multiple submissions from the same user? If the latter, then you would need to build in some logic that limits a user to only 1 vote. You could do this by check if the user has a related vote.
if ( ! $candidate->votes() ) {
// no votes exist, proceed with storing vote
}
Below is you controller refactored a bit:
public function votesuccess()
{
$rules = array(
'name' => 'required'
);
$validator = Validator::make(Input::all(),$rules);
if ($validator->fails()) {
return Redirect::back('votes/index')
->withErrors($validator)
->withInput(Input::except('password'));
} else {
// store
$candidate = Candidate::find(Input::get('name'));
$vote = $candidate->votes()->save(new Vote);
// redirect
Session::flash('message', 'Successfully Cast your vote!');
return Redirect::route('voteresults');
}
}
public function voteresult()
{
$candidates = Candidate::all();
$count = DB::table('votes')->count();
return View::make('votes.voteresults', compact('candidates', 'count'));
}

Categories