I have the following tables:
User: [id,username,password]
Producer: [id,user_id,...]
Admin: [id,user_id,...]
I've configured Authentication through User table.
So, if I get logged in when I execute Auth::user() I only can access to the user's fields. However, I would need be able to get producer's fields. I have to say that, a user can be Producer or Admin but not both.
Do you know good documentation or something to do it? Thanks a lot.
You class should hasMany relation to it
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
public function producers()
{
return $this->hasMany('Producer');
}
}
$user = Auth::user();
print_r($user->producers);
Related
I'm building a Laravel 8 API and want to automatically join user_settings onto a user whenever the User model is queried.
My thinking is that I can achieve this with the belongsTo relationship since user_settings "belongs" to a user.
However, when I attach this to my UserSetting model and query a user I'm not seeing any user settings attached to my User despite having data in the user_settings table.
Where am I going wrong?
Model: User
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class UserSetting extends Model
{
use HasFactory, SoftDeletes;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'user_settings';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_id',
'theme',
'refreshButtonPlacement',
'animationSpeed',
'fetchTimeout'
];
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo(UserSetting::class);
}
}
Model: User
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use HasFactory, Notifiable, SoftDeletes;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name',
'last_name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password'
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
'last_login_at' => 'datetime'
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
I also tried using a One To One relationship and defined a settings method on my User model but in Tinker when I ran User::findOrFail(1)->settings; I had nothing either.
Relationship setup:
class User extends Model
{
//some custom stuff
/**
* Get the phone associated with the user.
*/
public function user_setting()
{
return $this->hasOne(UserSetting::class);
}
}
class UserSetting extends Model
{
//some custom things
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
Afterwards you can use eager laoding by default, in your case you will have to add $with = ['user_setting'] to your User class.
You could also use the ->with() method, for that you will have to use either:
User::with('user_setting')->find(Auth::id());
//or
Auth::user()->with('organisation')->first()
Laravel doesn't load the relationship values in every call because of the obvious overhead. So you will either define the relationship to be loaded by default or you will have to work with the ->with() method for eager loading the relationship.
Add this method to your User model
And you can access the user settings through a dynamic attribute $user-> user_setting
on each User model instance
For more informations
https://laravel.com/docs/8.x/eloquent-relationships#one-to-one
public function user_setting(){
return $this->hasOne(UserSetting::class);
}
I am currently writing an application that is using Laravel 5.3 on the backend, and I'm looking for a way to overwrite the default password reset behaviour.
The class that I need to change is "ResetPassword" located here:
/Illuminate/Auth/Notifications/ResetPassword.php
Reason for the change is, that the reset url generated in this file is not correct for my front-end - as it uses url(), which puts the API url rather then the front-end url in the reset email.
You can override CanResetPassword's sendPasswordResetNotification() method in your User.php
use Illuminate\Notifications\Notifiable;
use App\Notifications\CustomResetPasswordNotification;
public function sendPasswordResetNotification($token)
{
$this->notify(new CustomResetPasswordNotification($token));
}
and create CustomResetPasswordNotification.php according your requirements.
Check Password Reset Emails section here for more details
I found a quick and easy way to overwrite the password reset process by overwriting the User class located here:
/Illuminate/Foundation/Auth/User.php
Basically, I created my own version like this:
<?php
namespace App\Traits\Auth;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use App\Traits\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements
AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
}
I saved it to /App/Traits/Auth and now use it in my User model.
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use App\Traits\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
Once finished, you can create your own version of the "CanResetPassword" trait and replace the Notification class and make necesarry adjustments.
Here is an example replacement for the "CanResetPassword" trait:
namespace App\Traits\Auth\Passwords;
use App\Notifications\CustomResetPassword as ResetPasswordNotification;
trait CanResetPassword
{
/**
* Get the e-mail address where password reset links are sent.
*
* #return string
*/
public function getEmailForPasswordReset()
{
return $this->email;
}
/**
* Send the password reset notification.
*
* #param string $token
* #return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
}
I have the following relationship models setup:
User
Users can have many job titles
Users can have many employee types
<?php
namespace App\Models\User;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'user';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['first_name', 'last_name', 'email', 'status', 'activation_code'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token', 'activation_code'];
/**
* The roles that belong to the user.
*
* #return Object
*/
public function roles()
{
return $this->belongsToMany('App\Models\User\Role')->withTimestamps();
}
/**
* The employee types that belong to the user.
*
* #return Object
*/
public function employeeTypes()
{
return $this->belongsToMany('App\Models\User\EmployeeType')->withTimestamps();
}
/**
* The job itles that belong to the user.
*
* #return Object
*/
public function jobTitles()
{
return $this->belongsToMany('App\Models\User\JobTitle')->withTimestamps();
}
}
Now, I want to be able to select the a list of users and all their job titles and employee types.
I have tried something like this with no such luck! Please could someone advise how this is possible?
$this->user->whereIn('id', $ids)->jobTitles()->get();
The above code gives the error:
Call to undefined method Illuminate\Database\Query\Builder::jobTitles()
Use eager loading:
$this->user->whereIn('id', $ids)->with('jobTitles', 'employeeTypes')->get();
You can only call relationships directly from a model, that's why your attempt failed (whereIn() returns Builder).
Eager/nested loading is very efficient way to fetch data before looping through multiple models and their relations (otherwise you may end up having A LOT of db queries) ;)
I am using Laravel 5 to build a user based application. Some models have a manyToMany relationship in my app and therefore I am using pivot tables.
When I delete a user from the system, I use this simple function:
/**
* Delete user.
*
* #param $id
* #return mixed
*/
public function deleteUser($id)
{
return $this->user->whereId($id)->delete();
}
However, when the user is deleted, the rows in the pivot tables (for example role_user) do not get deleted.
I have read on the laravel site that I can use model events to "clear up" my pivot tables, but i'm really unsure how I would implement that.
Can anyone point me in the right direction?
Edit
Below is my current model setup:
namespace App\Models\User;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use App\Scopes\MultiTenantTrait;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, CanResetPassword, MultiTenantTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'user';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['cust_id', 'first_name', 'last_name', 'email', 'status', 'activation_code'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* Boot the model.
*
*/
public static function boot()
{
parent::boot();
static::deleting(function($user)
{
$user->roles()->delete();
$user->supervisors()->delete();
$user->types()->delete();
$user->rates()->delete();
$user->miscs()->delete();
});
}
...
You can add a boot method to your models, like the following:
public static function boot() {
parent::boot();
// This is a deleting event on the model
static::deleting(function($model) {
$model->... //Here your model is still available
// You could add something like this
DB::table('role_user')->where('user_id', $model->id)->delete();
})
}
But you can also extend the delete method in your models:
public function delete() {
DB::table('role_user')->where('user_id', $this->id)->delete();
parent::delete();
}
I'm reading Laravel 5 documentation and have some problem with understanding route model binding.
I use example code from here
So, I added line to RouteServiceProvider.php:
public function boot(Router $router)
{
parent::boot($router);
$router->model('user', 'App\User');
}
I added route:
Route::get('/profile/{user}', function(App\User $user)
{
die(var_dump($user));
});
Default Laravel user model is used.
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
}
And I have MySQL table 'users'. When I go to URL http://blog.app/profile/1, I expect to see data for user with ID 1, but I don't understand how to get actual model values. Instead I see:
Is there any special methods for getting model values? Or did I miss something?
I have the same problem here. You just get an empty instance of App\User, since you declared that in your Route::get(). The model is never loaded.
Another way to bind model to the parameter:
Route::bind('user', function($value)
{
return App\User::find($value);
});
The Closure you pass to the bind method will receive the value of the URI segment, and should return an instance of the class you want to be injected into the route.
I have had the same problem.
Look for the "$namespace" var in the "RouteServiceProvider" and try to set it blank :
protected $namespace = '';