Laravel: Custom Auth with 2 tables - php

I am using Laravel 8, and I need to validate a user using data from 2 tables: users and customers. When user logs in, they will input 3 values: email, password and account. "Account" field comes from customer table.
So I need to do a join to access "account" field from "customers" table.
One option I see is:
public function validateCredentials(UserContract $user, array $credentials) {
$plain = $credentials['password'];
//Custom Query
return $this->hasher->check($plain, $user->getAuthPassword());
}
In section "Custom Query", I can do a query to get customer data using $user->customer_id and check if matches $credentials['account'], but not sure if it is the best way.
Thanks in advance for your help.

I end up building a Custom Provider, and override "retrieveByCredentials" method, that made the trick.
public function retrieveByCredentials(array $credentials)
{
if (empty($credentials) ||
(count($credentials) === 1 &&
Str::contains($this->firstCredentialKey($credentials), 'password'))) {
return;
}
$query = User::select(['customer.identifier', 'users.*'])->join('customer', 'customer_id', '=', 'customer.id');
foreach ($credentials as $key => $value) {
if (Str::contains($key, 'password')) {
continue;
}
if($key == 'account') {
$query->where('customer.identifier', '=', $credentials['account']);
} else {
$query->where($key, $value);
}
}
return $query->first();
}

Related

Laravel 5.6 Error on clicking the Patient list when creating a new doctor account

question 1.I have a thesis project about a certain clinic, I have a default users in my database, The default doctor doesn't have any problems or errors, but when i create a new doctor account, and when i click the patient list I get this error
Undefined variable: patient (View:C:\Users\patri\OneDrive\Desktop\Megason_noOTP\resources\views\patient-management\list.blade.php)
Please help TIA!!
enter code here
public function index(){
$user = User::where('id', Auth::user()->id)->with('usertype','usertype.permissions')->get();
$permissions = [];
foreach($user[0]->usertype->permissions as $permission)
{
array_push($permissions, $permission->name);
}
$patients = $this->getPatients();
$data = array(
'permissions' => $permissions,
'patients' => $patients
);
return view('patient-management.list')->with('data',$data);
}
public function getPatients(){
if(Auth::user()->type == 2){
return PatientDetail::where('doctor_id', Auth::user()->id)->with('doctor.doctorDetails','user')->get();
}else if(Auth::user()->type == 3){
return PatientDetail::where('user_id', Auth::user()->id)->with('doctor.doctorDetails','user')->get();
}
else{
return PatientDetail::with('doctor.doctorDetails','user')->get();
}
}

CakePHP 3 - ownership authorisation for associated tables

In the CakePHP 3 Blog Tutorial, users are conditionally authorized to use actions like edit and delete based on ownership with the following code:
public function isAuthorized($user)
{
// All registered users can add articles
if ($this->request->getParam('action') === 'add') {
return true;
}
// The owner of an article can edit and delete it
if (in_array($this->request->getParam('action'), ['edit', 'delete'])) {
$articleId = (int)$this->request->getParam('pass.0');
if ($this->Articles->isOwnedBy($articleId, $user['id'])) {
return true;
}
}
return parent::isAuthorized($user);
}
public function isOwnedBy($articleId, $userId)
{
return $this->exists(['id' => $articleId, 'user_id' => $userId]);
}
I've been attempting to implement something similar for my own tables. For example, I have a Payments table, which is linked to Users through several different tables as follows:
Users->Customers->Bookings->Payments.
Foreign keys for each:
user_id in Customers table = Users->id (User hasOne Customer)
customer_id in Bookings table = Customers->id (Customer hasMany Bookings)
booking_id in Payments table = Bookings->id(Booking hasMany Payments)
My AppController's initialize function:
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth',[
'authorize' => 'Controller',
]);
$this->Auth->allow(['display']); //primarily for PagesController, all other actions across the various controllers deny access by default
}
In my PaymentsController, I have the following
public function initialize()
{
parent::initialize();
}
public function isAuthorized($user)
{
if (in_array($this->request->action,['view', 'edit', 'index', 'add']
return (bool)($user['role_id'] === 1); //admin functions
}
if (in_array($this->request->action,['cart'])) {
return (bool)($user['role_id'] === 2) //customer function
}
if (in_array($this->request->action, ['cart'])) {
$bookingId = (int)$this->request->getParam('pass.0');
if ($this->Payments->isOwnedBy($bookingId, $user['id'])) {
return true;
}
}
return parent::isAuthorized($user);
}
public function isOwnedBy($bookingId, $userId)
{
return $this->exists(['id' => $bookingId, 'user_id' => $userId]);
}
I'm unsure as to how to link through the different tables to determine ownership.
Currently if a customer who is paying for Booking #123 could just change the URL so they are paying for Booking #111, provided that Booking exists in the database.
Additionally, the Booking ID is passed to the Cart function (since customers are paying for a specific booking). For example: If customer is paying for Booking #123, then the URL = localhost/project/payments/cart/123. Upon submitting their cart, a new Payment entry is created.
Also, regarding the getParam and isOwnedBy methods, hovering over them in my editor shows this:
Method 'getParam' not found in \Cake\Network\Request
Method 'isOwnedBy' not found in App\Model\Table\PaymentsTable
However, I've gone through the entire BlogTutorial and can't find anywhere else that getParam or isOwnedBy is used or set up in the Model.
In the IsAuthorized function in PaymentsController:
if (in_array($this->request->action, ['cart'])) {
$id = $this->request->getParam('pass'); //use $this->request->param('pass') for CakePHP 3.3.x and below.
$booking = $this->Payments->Bookings->get($id,[
'contain' => ['Artists']
]);
if ($booking->artist->user_id == $user['id']) {
return true;
}
}

How to delete an item from array in Laravel Session?

I'm creating a cart system, this is my code to input some itens into the user Session:
public function jsonResponse($data){
return response()->json([
'success' => true,
'users' => $data
]);
}
public function post(Request $request ,User $user)
{
$request->session()->push('users', $user);
return $this->jsonResponse($request->session()->get('users'));
}
How can I delete an unique item from the users array?
Alternative 01
It's able to remove the item from the users array with the following code:
public function delete(Request $request, User $user)
{
$users = $request->session()->get('users');
foreach ($users as $key => $val) {
if($user->id == $users[$key]->id){
$array = $request->session()->pull('users', []);
unset($array[$key]);
$request->session()->put('users', $array);
return $this->jsonResponse($request->session()->get('users'));
}
}
return $this->jsonResponse($request->session()->get('users'));
}
But I was searching for a clean way... Without remove the array and put it back to the Session...
Solution 01
The following alternative has been found for a cleaner code:
public function delete(Request $request, User $user)
{
$users = $request->session()->get('users');
foreach ($users as $key => $val) {
if($user->id == $users[$key]->id){
$request->session()->forget('users.'.$key);
return $this->jsonResponse($request->session()->get('users'));
}
}
return $this->jsonResponse($request->session()->get('users'));
}
Thanks to Kyslik for remind the dot notation...
You can use forget() or pull() methods for that.
$request->session()->forget('key');
The forget method will remove a piece of data from the session
$request->session()->pull('key', 'default');
The pull method will retrieve and delete an item from the session in a single statement

cakephp 3 build rules that allows checks if data is unique and allows empty

I want to allow users to leave the email and phone blank on the register function. I also want any added emails or phones no. to be unique.
However the isUnique function in the build rules is stopping this because it sees that the blank field already exists.
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['username']));
$rules->add($rules->isUnique(['email']));
$rules->add($rules->isUnique(['phone']));
return $rules;
}
How can I remedy this?
I have already tried the ->allowEmpty in the validation but it doesn't work.
There is nothing about this in the documents. As specific as this.
To improve on divinemaniac answer you should do this in the User Entity
//Entity/User.php
protected function _setPhone($value)
{
if($value == '') {
$value = null;
}
return $value;
}
If you still haven't found a solutions to this, I have one.
I ran into the same problem today and what I found out was that empty fields have a value of '' which does not equal null.
So, what you have to do is, in the add() and edit() function, or whichever function you are using to write the phone to the database, you must check if the phone field is equal to ''. If it does, then just assign null to it.
For example:
public function add()
{
//todo: check for conflicting email and phone
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
//LOOK AT THESE TWO LINES
if($user->phone == '') {
$user->phone = null;
}
if ($this->Users->save($user)) {
$this->Flash->success(__('The user has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$roles = $this->Users->Roles->find('list', ['limit' => 200]);
$this->set(compact('user', 'roles'));
$this->set('_serialize', ['user']);
}

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";

Categories