Laravel 4 : Authentication when having a many to many relationship - php

I have a users, roles and role_users table. In the roles table I have a user and admin value. Now I want to be able to edit users when the role of a user is admin. I don't know how to access the role_name == 'admin' in laravel.
When I use this it works :
#if(Auth::user()->user_username == 'Gilko')
But I want to be able to access this role_name == 'admin'
role_users migration
public function up()
{
Schema::create('role_users', function($table)
{
$table->increments('role_user_id');
$table->integer('role_id')->unsigned();
$table->integer('user_id')->unsigned();
});
Schema::table('role_users', function($table)
{
$table->foreign('role_id')
->references('role_id')->on('roles');
//->onDelete('cascade');
$table->foreign('user_id')
->references('user_id')->on('users');
//->onDelete('cascade');
});
}
User model :
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'users';
protected $primaryKey = 'user_id';
protected $hidden = ["password"];
public function getAuthIdentifier()
{
return $this->getKey();
}
public function getAuthPassword()
{
return $this->user_password;
}
public function getReminderEmail()
{
return $this->email;
}
public function user()
{
return $this->hasMany('Checklist', 'user_id', 'user_id');
}
public function roles(){
return $this->belongsToMany('Role', 'role_users', 'user_id', 'role_id');
}
public function getRememberToken()
{
//return $this->remember_token;
}
public function setRememberToken($value)
{
//$this->remember_token = $value;
}
public function getRememberTokenName()
{
//return 'remember_token';
}
}

You should be able to do something like this:
if (Auth::user()->roles()->where('name', 'admin')->first())
first will return null if there's no result.
You can also use firstOrFail: http://laravel.com/docs/eloquent
try (Auth::user()->roles()->where('name', 'admin')->firstOrFail()) {
// User has admin role
} catch (ModelNotFoundException $e) {
// User doesn't have admin role
}
Edit Just realized I had a brain fart. Corrected the code :-)

You can add a function which checks for this on your user model...
public function isAdmin()
{
return (bool)$this->roles()->where('name', 'admin')->count();
}
And then you can easily use it with...
#if(Auth::user()->isAdmin())

Related

How do I show user login history?

I am a beginner in Laravel. I use in my project Laravel 5.8.
I have this schema:
Schema::create('user_login_histories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->dateTime('date_time');
$table->ipAddress('ip');
$table->engine = "InnoDB";
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
});
and my Model:
class UserLoginHistory extends Model
{
protected $quarded = ['id'];
public $timestamps = false;
protected $fillable = ['user_id', 'date_time', 'ip'];
public function user()
{
return $this->belongsTo('App\User');
}
// Show User login history
public function scopeHistory()
{
//return $this->hasMany('App\UserLoginHistory');
return $this->hasMany('App\UserLoginHistory', 'user_id', 'id');
}
}
I want to show my user history by this function:
public function getLoginAdminHistory(int $idAdmin)
{
return UserLoginHistory::history()->orderBy('id', 'desc')->paginate(25);
}
but this is not working.
How can I fix this?
The way you are using scope here is wrong. It is not meant to be used like that and will not help you with this issue, so I am not gonna go into details with that.
I am going to assume that you want to store more than one UserLoginHistory per User, so what you need is a HasMany relationship on the User class.
So to make this work, you need something like:
in User.php
public function userLoginHistory(): HasMany
{
return $this->hasMany(UserLoginHistory::class);
}
Now you should be able to do:
$user->userLoginHistory, which will return a collection of UserLoginHistory for you.
public function getLoginAdminHistory(int $idAdmin)
{
$user = User::findOrFail($idAdmin);
return $user->userLoginHistory()->orderBy('id', 'desc')->paginate(25);
}

Laravel call to a member function addEagerConstraints() on boolean

I'm getting the following error whenever i go on to a users page, its supposed to show if the authenticated user is already following the user that the profile is on.
Could this be a problem with the relationship setup, it hasMany
Stack trace
local.ERROR: Call to a member function addEagerConstraints() on
boolean {"userId":1,"email":"fakeemail#aol.com","exception":"[object]
(Symfony\Component\Debug\Exception\FatalThrowableError(code: 0):
Call to a member function addEagerConstraints() on boolean at
/Applications/MAMP/htdocs/elipost/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:522)"}
[]
UserController.php
public function getProfile($user)
{
$users = User::with([
'posts.likes' => function($query) {
$query->whereNull('deleted_at');
$query->where('user_id', auth()->user()->id);
},
'follow',
'follow.follower'
])->with(['followers' => function($query) {
$query->with('follow.followedByMe');
$query->where('user_id', auth()->user()->id);
}])->where('name','=', $user)->get();
$user = $users->map(function(User $myuser){
return ['followedByMe' => $myuser->followers->count() == 0];
});
if (!$user) {
return redirect('404');
}
return view ('profile')->with('user', $user);
}
MyFollow(model)
<?php
class MyFollow extends Model
{
use SoftDeletes, CanFollow, CanBeFollowed;
protected $fillable = [
'user_id',
'followable_id'
];
public $timestamps = false;
protected $table = 'followables';
public function follower()
{
return $this->belongsTo('App\User', 'followable_id');
}
public function followedByMe()
{
return $this->follower->getKey() === auth()->id();
}
}
MyFollow
use Overtrue\LaravelFollow\Traits\CanFollow;
use Overtrue\LaravelFollow\Traits\CanBeFollowed;
class MyFollow extends Model
{
use SoftDeletes, CanFollow, CanBeFollowed;
protected $fillable = [
'user_id',
'followable_id'
];
public $timestamps = false;
protected $table = 'followables';
public function follower()
{
return $this->belongsTo('App\User', 'followable_id');
}
public function followedByMe()
{
return $this->follower->getKey() === auth()->id();
}
}
Post
class Post extends Authenticatable
{
protected $fillable = [
'title',
'body',
'user_id',
'created_at',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany('App\Comment');
}
public function likes()
{
return $this->hasMany('App\Like');
}
public function likedByMe()
{
foreach($this->likes as $like) {
if ($like->user_id == auth()->id()){
return true;
}
}
return false;
}
}
Likes
<?php
namespace App;
use App\Post;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Like extends Model
{
use SoftDeletes;
protected $fillable = [
'user_id',
'post_id'
];
}
User(model)
class User extends Authenticatable
{
use Notifiable,CanFollow, CanBeFollowed;
/**
* 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',
];
public function posts()
{
return $this->hasMany(Post::class);
}
public function images()
{
return $this->hasMany(GalleryImage::class, 'user_id');
}
public function likes()
{
return $this->hasMany('App\Like');
}
public function follow()
{
return $this->hasMany('App\MyFollow');
}
public function comments()
{
return $this->hasMany('App\Comment');
}
}
As Jonas Staudenmeir stated, followedByMe isn't a relationship, it's a regular function and what it does is returning a boolean. I'm confused at why you've got a follow on your user model and trying to get information from the follow's follower? Just simplify, I see too much unneeded eager loading here.
Searching by indexed elements (id) > searching by name, any day of the week
Edit:
UserController
public function getProfile(Request $request, $id)
{
//$request->user() will get you the authenticated user
$user = User::with(['posts.likes','followers','follows','followers.follows'])
->findOrFail($request->user()->id);
//This returns the authenticated user's information posts, likes, followers, follows and who follows the followers
//If you wish to get someone else's information, you just switch
//the $request->user()->id to the $id if you're working with id's, if you're
//working with names, you need to replace findOrFail($id) with ->where('name',$name')->get() and this will give you
//a collection, not a single user as the findOrFail. You will need to add a ->first() to get the first user it finds in the collection it results of
//If you're planning on getting an attribute (is_following = true) to know if
//the authenticated user is following, you can use an accessor in the User model and write this after you've fetched the instance of the User
//$user->append('is_following');
return view ('profile')->with('user', $user);
}
User Model
//Accessor
//People who this user follows
public function getIsFollowingAttribute()
{
return MyFollow::where('followable_id',$this->attributes['id'])->where('user_id',Auth()->user()->id)->count() > 0 ? true : false;
}
//Relationships
//People who this user follows
public function follow()
{
return $this->hasMany('App\MyFollow','user_id','id');
}
//People who follows this user
public function followers()
{
return $this->hasMany('App\MyFollow','followable_id','id');
}
//Posts of this user
public function posts()
{
return $this->hasMany('App\Post','user_id','id');
}
//Likes of this user, not sure about this one tho, we're not using this for now but it could come in handy for you in the future
public function likes()
{
return $this->hasManyThrough('App\Likes','App\Post','user_id','user_id','id');
}
Post Model
//Who like this post
public function likes()
{
return $this->hasMany('App\Post','user_id','id');
}
MyFollow Model
//Relationships
//People who follow this user
public function followers()
{
return $this->hasMany('App\MyFollow','followable_id','user_id');
}
//Relationships
//People who this user follows
public function follow()
{
return $this->hasMany('App\MyFollow','user_id','followable_id');
}
With the help of #abr i found a simple fix, simple solution.
MyFollow.php(model)
public function followers()
{
return $this->hasMany('App\MyFollow','followable_id','user_id');
}
//Relationships
//People who this user follows
public function follow()
{
return $this->hasMany('App\MyFollow','user_id','followable_id');
}
User.php(model)
public function getIsFollowingAttribute()
{
return MyFollow::where('followable_id',$this->attributes['id'])->where('user_id',Auth()->user()->id)->count() > 0 ? true : false;
}
public function follow()
{
return $this->hasMany('App\MyFollow');
}
UserController.php
public function getProfile($user)
{
$users = User::with(['posts.likes' => function($query) {
$query->whereNull('deleted_at');
$query->where('user_id', auth()->user()->id);
}, 'followers','follow.followers'])
->with(['followers' => function($query) {
}])->where('name','=', $user)->get();
$user = $users->map(function(User $myuser){
$myuser['followedByMe'] = $myuser->getIsFollowingAttribute();
return $myuser;
});
if(!$user){
return redirect('404');
}
return view ('profile')->with('user', $user);
}
it works now. :)

3 models many-to-many sync in Laravel 5.4

I have 3 models with the relations many-to-many:
Module
public function permissionTypes()
{
return $this->belongsToMany(PermissionType::class, 'permissions')->withPivot('role_id');
}
public function roles()
{
return $this->belongsToMany(Role::class, 'permissions')->withPivot('permission_type_id');
}
Role
public function permissionTypes()
{
return $this->belongsToMany(PermissionType::class, 'permissions')->withPivot('module_id');
}
public function modules()
{
return $this->belongsToMany(Module::class, 'permissions')->withPivot('permission_type_id');
}
PermissionType
public function roles()
{
return $this->belongsToMany(Role::class, 'permissions')->withPivot('module_id');
}
public function modules()
{
return $this->belongsToMany(Module::class, 'permissions')->withPivot('role_id');
}
tables description:
modules
id
title
status
roles
id
title
permission_types
id
title
pivot table permissions
id
role_id
module_id
permission_type_id
My synchronization looks like:
//array of ids from request to synchronization
$permissions = $request['permissions'];
//role by id from request
$role = Role::findOrFail((int)$roleId);
//module by id from request
$module = Module::findOrFail((int)$moduleId);
//synchronization
$pivotData = array_fill(0, count($permissions), ['role_id' => $role->id]);
$syncData = array_combine($permissions, $pivotData);
$module->permissionTypes()->sync($syncData);
When trying to make the synchronization, have an error
QueryException in Connection.php line 647:
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'permissions' (SQL: select permissions.*, permissions.role_id as pivot_role_id, permissions.permission_id as pivot_permission_id from permissions inner join permissions on permissions.id = permissions.permission_id where permissions.role_id = 1)
Thanks
IMHO you are trying to design a triple many to many that does not exists in Laravel. The solution, usually is to give the pivot table (in your case permissions) a Model (Permission in below code) for defining hasManyThrough relations.
If I understood well your table structure I will design the following relationships:
Module
public function permissions()
{
return $this->hasMany(Permission::class);
}
public function roles()
{
return $this->hasManyThrough(Role::class, Permission::class);
}
public function permissionTypes()
{
return $this->hasManyThrough(PermissionType::class, Permission::class);
}
Role
public function permissions()
{
return $this->hasMany(Permission::class);
}
public function permissionTypes()
{
return $this->hasManyThrough(PermissionType::class, Permission::class);
}
public function modules()
{
return $this->hasManyThrough(Module::class, Permission::class);
}
PermissionType
public function permissions()
{
return $this->hasMany(Permission::class);
}
public function modules()
{
return $this->hasManyThrough(Module::class, Permission::class);
}
public function roles()
{
return $this->hasManyThrough(Role::class, Permission::class);
}
Permission
public function permissionType()
{
return $this->belongsTo(PermissionType::class);
}
public function role()
{
return $this->belongsTo(Role::class);
}
public function module()
{
return $this->belongsTo(Module::class);
}
Tell me if it could work for you.

Laravel: Getting data from my pivot table

I've just started using Laravel and I am really enjoying it. I am a little confused about how to access data at times and i'm not sure if I am going around this in the right way, Maybe somebody can help?
I want to simply output the Club Name and Opponent Club Name in a loop of Fixtures.
I have the following tables:
// a clubs table
Schema::create('clubs', function($table) {
$table->increments('id');
$table->string('name', 20);
$table->string('code', 40);
$table->string('location', 20);
$table->string('colour', 20);
$table->string('alias', 20);
$table->string('image', 200);
$table->timestamps();
});
// a fixtures table
Schema::create('fixtures', function($table) {
$table->increments('id');
$table->string('type', 20)->nullable();
$table->string('date', 20)->nullable();
$table->string('time', 20)->nullable();
$table->string('venue', 20)->nullable();
$table->string('address', 20)->nullable();
$table->boolean('reminders')->nullable();
$table->timestamps();
});
// a pivot table
Schema::create('clubs_fixtures', function($table) {
$table->increments('id');
$table->integer('club_id')->unsigned(); // this is meant to be used as a foreign key
$table->foreign('club_id')->references('id')->on('clubs')->onDelete('cascade')->onUpdate('cascade');
$table->integer('opponent_id')->unsigned(); // this is meant to be used as a foreign key
$table->foreign('opponent_id')->references('id')->on('clubs')->onDelete('cascade')->onUpdate('cascade');
$table->integer('fixture_id')->unsigned(); // this is meant to be used as a foreign key
$table->foreign('fixture_id')->references('id')->on('fixtures')->onDelete('cascade')->onUpdate('cascade');
$table->timestamps();
});
So a CLUB can have MANY FIXTURES and a FIXTURE can have MANY CLUBS.
My Club model is as follows:
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Club extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'clubs';
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->password;
}
public function getRememberToken() {
return $this->remember_token;
}
public function setRememberToken($value) {
$this->remember_token = $value;
}
public function getRememberTokenName() {
return 'remember_token';
}
public function getReminderEmail() {
return $this->email;
}
// set validation
public static $createUpdateRules = array(
'name'=>'required|min:2',
'location'=>'required|min:2',
'colour'=>'required|min:2',
'alias'=>'required|min:2'
);
// We can define a many-to-many relation using the belongsToMany method:
public function fixtures() {
return $this->belongsToMany('Fixture', 'clubs_fixtures')->withPivot('opponent_id');
}
}
My Fixture model is as follows:
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Fixture extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'fixtures';
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->password;
}
public function getRememberToken() {
return $this->remember_token;
}
public function setRememberToken($value) {
$this->remember_token = $value;
}
public function getRememberTokenName() {
return 'remember_token';
}
public function getReminderEmail() {
return $this->email;
}
// set validation
public static $createRules = array(
'type'=>'required|min:2',
'opponent'=>'required|min:1',
'date'=>'required|min:2',
'time'=>'required|min:2',
'venue'=>'required|min:2',
'address'=>'required|min:2',
'reminders'=>'required'
);
}
Then in my controller I use Elequent ORM to get the upcoming fixtures
public function getViewClub($id) {
$upcomingFixtures = Club::find($id)->fixtures()->where('date', '>=', new DateTime('today'))->get();
return View::make('club.view')->with('upcomingFixtures', $upcomingFixtures);
}
#foreach($upcomingFixtures as $upcomingFixture)
<p>
<a href="{{ URL::to('dashboard/'.$club->id.'/fixtures/upcoming/'.$upcomingFixture->id) }}">
<strong>{{ $club->name }} vs Team Name</strong>
</a>
</p>
#endforeach
I hope I make sense with all this. I've tried to separate out the data, trying to keep the clean modular and dry, but I've immediately hit a problem here.
Hopefully a Laravel guru can steer me in the right direction here?
Thanks
You're doing it wrong, first you don't need to implement UserInterface and RemindableInterface (but keep it in User model ), second you can add relation clubs() inside your Fixture model
class Fixture extends Eloquent {
protected $table = 'fixtures'; // you can also remove this line
// set validation
public static $createRules = array(
'type'=>'required|min:2',
//....
);
public function clubs() {
return $this->belongsToMany('Club','clubs_fixtures')
->withPivot('opponent_id');
}
}
Then in your controller
public function getViewClub($id) {
$upcomingFixtures = Fixture::with('clubs')
->where('date', '>=', new DateTime('today'))->get();
return View::make('club.view',compact('upcomingFixtures'));
}
#foreach($upcomingFixtures as $upcomingFixture)
<h1>{{ $upcomingFixture->type }}</h1>
#foreach($upcomingFixture->clubs as $club)
<p>
<a href="{{ URL::to('dashboard/'.$club->id.'/fixtures/upcoming/'.$upcomingFixture->id) }}">
<strong>{{ $club->name }} vs Team Name</strong>
</a>
</p>
<p> access to pivot table: {{ $club->pivot->opponent_id }}</p>
#endforeach
#endforeach

Laravel model object chaining

For some reason, I cannot chain model objects. I'm trying to eager load 'Location' for an 'Order' and would prefer the logic to be contained in the models themselves. But past one chain, it does not work.
class Order extends Eloquent {
protected $table = 'orders';
public function customer() {
return $this->belongsTo('Customer');
public function location() {
return $this->customer()->location(); // this does not work
}
}
class Customer extends Eloquent {
protected $table = 'customers';
public function user() {
return $this->belongsTo('User');
}
public function orders() {
return $this->hasMany('Order');
}
public function location() {
return $this->user()->location();
// return $this->user(); // WORKS!!
}
}
class User extends Eloquent {
protected $table = 'users';
public function locations() {
return $this->hasMany('Location');
}
public function location() {
return $this->locations()->first();
}
}
I eventually want to do this:
class ChefController extends BaseController {
public function get_orders() {
$chef = $this->get_user_chef(); // this already works
return $chef->orders()->with('location')->get(); // does not work
}
}
Try to reference relation (user table) by adding user_id as second argument, like this:
public function user() {
return $this->belongsTo('User',"user_id");
}
Maybe you called that id field different, but you know what I mean.

Categories