Laravel : How to get all users who have a certain role? - php

I have three roles: 1. Admin 2. Client 3. Store
I have three tables: 1. users 2. roles 3.role_user
How can I get all users who have the role Client?
I tried this
$clients = User::roles()->where('App\Models\Role',Role::CLIENT)->get();
I'm getting following error.
Non-static method App\Models\User::roles() should not be called
statically
Role Model
class Role extends Model
{
public const ADMIN = 'Admin';
public const CLIENT = 'Client';
public const STORE = 'Store';
public function users()
{
return $this->belongsToMany('App\Models\User')->using('App\Models\UserRole');
}
}
User Model
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name',
'first_name',
'last_name',
'email',
'password',
'activated',
'token',
'signup_ip_address',
'signup_confirmation_ip_address',
'signup_sm_ip_address',
'admin_ip_address',
'updated_ip_address',
'deleted_ip_address',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function hasRole(String $roleName)
{
return $this->roles()->where('name', $roleName)->exists();
}
public function roles()
{
return $this->belongsToMany('App\Models\Role');
}
public function addRole(String $roleName)
{
$role = Role::where('name', $roleName)->first();
if ($role) $this->roles()->save($role);
}
}

You can do it with whereHas() method. it's a way to condition on relation using exists in query
$clients = User::whereHas('roles', function($role) {
$role->where('name', '=', Role::CLIENT);
})->get();
If you want to get the role too, stack the with() method
$clients = User::whereHas('roles', function($role) {
$role->where('name', '=', Role::CLIENT);
})->with(['roles' => function($role) {
$role->where('name', '=', Role::CLIENT);
}])->get();

That's because you're trying to call the roles method on the Model class and not the instance, here's how it should be
$clients = Role::whereName('client')->first()->users;

Related

Configuration observer in Laravel

I am beginner in Laravel. I use in my project Laravel 8.
I have this code:
Controller
public function index(Request $request)
{
$query = $this->model
->orderBy($request->column ?? 'created_at', $request->order ?? 'desc');
if ($request->search) {
$query->where(function ($query) use ($request) {
$query->where('name', 'like', '%' . $request->search . '%')
->orWhere('id', 'like', '%' . $request->search . '%');
});
}
return DictionaryResource::collection($query->paginate($request->per_page));
}
public function create()
{
$statuses = DB::table('status')->select('status.name as label', 'status.id as value')->get();
$types = DB::table('dictionary_types')->select('dictionary_types.name as label', 'dictionary_types.id as value')->get();
return response()->json([$statuses, $types]);
}
public function store(DictionaryRequest $request)
{
$data = $request->only([
'name',
]);
if($request->status == 2) $status = 2;
else $status = 1;
if(is_null($request->type)) $type = 1;
else $type = $request->type;
$data['status'] = $status;
$data['type'] = $type;
$this->model->create($data);
return response()->json(['status' => 'success']);
}
Model
class Dictionary extends Model
{
use ScopeActiveTrait,
SoftDeletes;
protected $guarded = ['id'];
protected $fillable = [
'name',
'type',
'status'
];
protected $dates = [
'deleted_at',
'created_at',
'updated_at'
];
}
Observer
class DictionaryObserver
{
public function created(Dictionary $dictionary)
{
Log::info('yyyyyyyyy');
}
public function retrieved(Dictionary $dictionary)
{
Log::info('xxxxxxxxxx'.$dictionary);
}
public function updated(Dictionary $dictionary)
{
//
}
public function deleted(Dictionary $dictionary)
{
//
}
}
ServiceProvider
public function boot()
{
Paginator::useBootstrap();
Dictionary::observe(DictionaryObserver::class);
}
I have 2 questions / problems:
How can I disable following in the controller (index method)? I only need to record the moment when someone opens one record for editing, and does not list all the records in the list
I have model Action:
class Action extends Model
{
use ScopeActiveTrait,
SoftDeletes;
protected $guarded = ['id'];
protected $fillable = [
'company_id',
'user_id',
'ip',
'user_agent',
'description'
];
protected $dates = [
'deleted_at',
'created_at',
'updated_at'
];
}
I need save to this model information about user ip, user_agent itp (user is logged).
How can I make it?
As you've found, the "retrieved" method on the observer is called when you load the model instance, whether you load one or many (if you load many, it is called once for each model loaded).
You can suppress events being fired (and, having tested it, this includes both Events and Observers) by wrapping it in a callback function using the ::withoutEvents() static method.
So (using code from one of my sites) if I use :
$games = Game::where('id', '>=', 4900)->where('id', '<=', 4910)->get();
then the GameObserver will be called 11 times (because there are 11 models which are loaded). But if I wrap it in the ::withoutEvents method like so :
$games = Game::withoutEvents(function () {
$games = Game::where('id', '>=', 4900)->where('id', '<=', 4910)->get();
return $games;
});

Is there a way to get a nested Eloquent model based on ids from another table?

Hey there stackoverflow
I am currently building a course application as part of my laravel project.
My problem lies in how the eloquent handle model relations, i'm still kinda new to eloquent, so hopefully you can answer my question.
The structure
The Course has many episodes and each episode has many sections.
Which means I have 3 tables in the DB. Courses -> course_episodes -> course_episode_sections
ID table is where i connect courses with users - course_users.
Right now i can create courses and and put in all the data correctly.
The Problem
I need to retrieve all the courses and its nested children that the user has bought, which is connected in the course_users table with columns course_id and user_id
Course structure
Same stucture in DB
course: {
name: null,
sub_title: null,
estimate: null,
trailer: null,
type: null,
text: null,
course_episodes: [
{
name: null,
section: [
{
order: null,
type: null,
content: null,
},
]
},
]
}
Model Pictures
My models as of right now.
class CourseUsers extends Model {
protected $fillable = [
'id',
'course_id',
'user_id',
'active',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courses()
{
return $this->belongsToMany(Course::class);
}
public function user(){
return $this->belongsTo(User::class);
}
public function scopeFindForUserId($query, $userId)
{
return $query->where(function ($q) use ($userId) {
$q->where(function ($q) use ($userId) {
$q->where('user_id', $userId);
});
});
}
Course model
class Course extends Model{
protected $fillable = [
'id',
'name',
'sub_title',
'type',
'estimate',
'trailer',
'gateway_id',
'text',
'active',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courseEpisode()
{
return $this->hasMany(CourseEpisode::class);
}
public function courseUsers() {
return $this->hasMany(CourseUsers::class);
}
public function scopeActive(Builder $builder)
{
return $builder->where('active', true);
}
Course episode Model
class CourseEpisode extends Model implements HasMedia {
use HasMediaTrait;
protected $fillable = [
'id',
'course_id',
'order',
'name',
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function course()
{
return $this->belongsTo(Course::class);
}
public function courseSection()
{
return $this->hasMany(CourseEpisodeSection::class);
}
Course episode sections
class CourseEpisodeSection extends Model {
protected $fillable = [
'id',
'course_episode_id',
'order',
'type',
'content'
];
protected $hidden = [
'deleted_at',
'updated_at',
'deleted_at'
];
public function courseEpisode()
{
return $this->belongsTo(CourseEpisode::class);
}
According to your explanation, course_users table holds many-to-many relationship between Course and User model. In case of a many-to-many relationship, you actually don't need a CourseUser model. This kind of table which holds many-to-many relationship is called pivot table. Read more from the Official Documentation
I am defining only the relationships with your Course, User, CourseEpisode, CourseEpisodeSection models.
Course.php
class Course extends Model
{
public function courseEpisodes()
{
return $this->hasMany(CourseEpisode::class);
}
public function users()
{
return $this->belongsToMany(User::class,'course_users')->withPivot('active');
}
}
CourseEpisode.php
class CourseEpisode extends Model
{
public function courseSections()
{
return $this->hasMany(CourseSection::class);
}
}
User.php
class User
{
public function courses()
{
return $this->belongsToMany(Course::class,'course_users')->withPivot('active');
}
}
If you want to get all the children relationships from a user, use nested eager loading :
$user_with_nested_course_data = User::with('courses.courseEpisodes.courseSections')->find($id);

How can I get all the users that has commented a post?

I'm working with Laravel 5 and I've the following Models
PostComment.php
class PostComment extends Model
{
protected $fillable = [
'post_group_id', 'user_id', 'comment_content'
];
public function post(){
return $this->belongsTo('App\PostGroup');
}
public function user(){
return $this->belongsTo('App\User');
}
}
PostGroup.php
class PostGroup extends Model
{
protected $fillable = [
'group_id', 'user_id', 'post_content'
];
public function user(){
return $this->belongsTo('App\User');
}
public function group(){
return $this->belongsTo('App\Group');
}
public function commented(){
return $this->hasMany(
'App\PostComment'
);
}
}
Group.php
class Group extends Model
{
protected $fillable = ([
'id'
]);
public function users(){
return $this->belongsToMany(
'App\User',
'user_group'
);
}
public function members(){
return $this->belongsToMany(
'App\User',
'user_group'
)->wherePivot('state','accepted');
}
public function posted(){
return $this->hasMany(
'App\PostGroup'
);
}
}
My web application presents groups, in which you can create posts and in which post you can write comments. In my database I've the following relationships:
Group: (id, name, description);
PostGroup: (id, group_id, user_id, post_content);
PostComment: (id, post_group_id, user_id, comment_content);
What I want to do is to create a collection of User objects, and then make a query to get all users, subscribed to a group, who have commented on a certain post, in MySQL looks like:
select users.* from users, post_comments where users.id = post_comments.user_id and post_comments.post_group_id="1"
So in my controller I've the following code
$theGroup = Group::find($groupId);
$thePost = PostGroup::find($postId);
$memberList = User::where('id', '<>', Auth::user()->id)->whereIn('id', $theGroup->users->pluck('id'))->
So, what I want to do is to extend that query to get the desidered result with ->get()->sortBy('last_name');, how can I exted it after the whereIn?
EDIT
User.php
class User extends Authenticatable
{
/**
* 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','created_at','updated_at'
];
public function groups(){
return $this->belongsToMany('App\Group','user_group');
}
public function groupsAsAdmin(){
return $this->belongsToMany('App\Group','user_group')->wherePivot('role','admin');
}
public function groupsAsMember(){
return $this->belongsToMany('App\Group','user_group')->wherePivot('state','accepted');
}
public function groupsAsInvited(){
return $this->belongsToMany('App\Group','user_group')->wherePivot('state','pending');
}
public function posted(){
return $this->hasMany('App\PostGroup');
}
public function commented(){
return $this->hasMany('App\PostComment');
}
}
From your description, you already come up with a list of Users in advance, so that you only will find Posts with a Comment of these specific users.
Basically, what you want is to use whereHas($relation, $calback) to perform the checks you described:
$userIds = [2, 3, 5, 7, 11, 13, 17]; // or query them...
$postId = 123; // the id of the post where we want to look through the comments
User::where('id', '<>', Auth::id())
->whereIn('id', $userIds)
->whereHas('comments', function ($query) use ($postId) {
$query->where('post_group_id', $postId);
})
->get();
This will simply check if a user has written a Comment for the given post. Because you forgot to post your User model, I assumed that there is a relation available for the comments of the user.
You could also combine the first two conditions (user in list, but not the authenticated one) into one, if you want. $userIds = array_diff($userId, [Auth::id()]) does the job. where('id', '<>', Auth::id()) can be dropped from the query then.
If you do also need to check for an active subscription of the user to a group, it will be slightly more complex. But as you commented, you are already finding only users for a group, so this should be fine.
In PostComment, try this
$this->selectRaw(‘user_id, comment_content’)->where(‘post_group_id’, 1)->groupBy(‘user_id’)->get();

Laravel 5.2 Model Relationships

im new to Laravel and have a relationship question.
The goal is to get all News where news.page_id = page.id AND page.pagetype_id = pagetype.id WHERE pagetype.component = news AND page.app_id = 1
class News extends Model
{
protected $table = 'news';
protected $fillable = ['page_id', 'title', 'description', 'active', 'created_at', 'updated_at'];
}
class Page extends Model
{
protected $table = 'pages';
protected $fillable = ['app_id', 'unique_id', 'pagetype_id', 'title', 'picture_url', 'short_description', 'description', 'valid_since', 'valid_until', 'extras', 'active', 'created_at', 'updated_at'];
public function pagetype() {
return $this->belongsTo('App\Models\PageType', 'pagetype_id');
}
}
class PageType extends Model
{
protected $table = 'pagetypes';
protected $fillable = ['pagetype', 'component', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->belongsToMany('App\Models\Page', 'pagetypes', 'id', 'id');
}
}
// now i need All News Items where page.pagetype_id = pagetypes.id and patchtypes.component = news
// First Attempts are
Page::whereHas('pagetype', function ($q) {
$q->where('component', 'news');
})->where(['app_id' => 1])->get();
// result is all Pages which has the proper component news.
This is what i have tried yet, but in my attempt i'll only receive the proper pages but of course not the news.
My "current" solution is to get all the pages and then loop through News::where('page_id', $myPageId). But im pretty sure its possible to get a proper relationship to get also news.
I cant do any other model since there are many different pagetypes and components aswell.
Thanks so far.
You need to add relationship function to news model.
public function pages() {
return $this->belongsTo('App\Models\Page');
}
And call it through News model.
News::with('pages')->where('app_id',1);
First off all I think that you are wrong with you PageType relation
class PageType extends Model
{
protected $table = 'pagetypes';
protected $fillable = ['pagetype', 'component', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->hasMany('App\Models\Page');
// if i understood you correctly you haven't got any pivot table
}
}
Then you should link your News and Page like so
News.php
class News extends Model
{
protected $table = 'news';
protected $fillable = ['page_id', 'title', 'description', 'active', 'created_at', 'updated_at'];
public function page() {
return $this->belongsTo('App\Models\Page');
}
}
Page.php
class Page extends Model
{
protected $table = 'pages';
protected $fillable = ['app_id', 'unique_id', 'pagetype_id', 'title', 'picture_url', 'short_description', 'description', 'valid_since', 'valid_until', 'extras', 'active', 'created_at', 'updated_at'];
public function pagetype() {
return $this->belongsTo('App\Models\PageType');
}
public function news() {
return $this->hasMany('App\Models\News');
}
}
Then you can achieve your goal
News::whereHas('page', function($q) use($appId) {
$q->where('app_id',$appId);
})->whereHas('page.pagetype', function($q) {
$q->where('component', 'news');
})->get();

Save object with foreign keys in laravel

I use PHP, Laravel 5.2 and MySQL.
During user registration, I need to create a new Patient. But, Patient has user id, contact id and guardian id(foreign keys).
When I try to save() the patient, I get the following exception:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'patient_id' in
'field list' (SQL: update users set patient_id = 0, updated_at =
2016-06-07 12:59:35 where id = 6)
The problem is that I DO NOT have patient_id column. Instead I have patientId.
I don't know how to fix this issue. Any help will be appreciated. I can include the migration files if this is important.
UserController.php
public function postSignUp(Request $request)
{
$this->validate($request,[
'email' => 'required|email|unique:users',
'name' => 'required|max:100',
'password' => 'required|min:6'
]);
$guardian = new Guardian();
$guardian->guardianId = Uuid::generate();;
$guardian->save();
$contact = new Contact();
$contact->contactId = Uuid::generate();
$contact->save();
$user = new User();
$user->email = $request['email'];
$user->name = $request['name'];
$user->password = bcrypt($request['password']);
$user->save();
$patient = new Patient();
$patient->patientId = (string)Uuid::generate();
$patient->user()->save($user);
$patient->contact()->save($contact);
$patient->guardian()->save(guardian);
$patient->save();
Auth::login($user);
// return redirect()->route('dashboard');
}
Patient.php
class Patient extends Model
{
protected $primaryKey='patientId';
public $incrementing = 'false';
public $timestamps = true;
public function user()
{
return $this->hasOne('App\User');
}
public function contact()
{
return $this->hasOne('App\Contact');
}
public function guardian()
{
return $this->hasOne('App\Guardian');
}
public function allergies()
{
return $this->belongsToMany('App\PatientToAllergyAlert');
}
public function medicalAlerts()
{
return $this->belongsToMany('App\PatientToMedicalAlert');
}
}
User.php
class User extends Authenticatable
{
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function patient()
{
return $this->belongsTo('App\Patient');
}
}
Contact.php
class Contact extends Model
{
protected $table = 'contacts';
protected $primaryKey = 'contactId';
public $timestamps = true;
public $incrementing = 'false';
public function contact()
{
return $this->belongsTo('App\Patient');
}
}
Guardian.php
class Guardian extends Model
{
protected $table = 'guardians';
protected $primaryKey = 'guardianId';
public $timestamps = true;
public $incrementing = 'false';
public function contact()
{
return $this->belongsTo('App\Patient');
}
}
You have not defined relationships correctly. First of all, fill in table fields into $fillable array in Patient, Contact, Guardian classes (just like in User class).
If you want to use hasOne relationship between Patient and User, you're gonna need user_id field on patients table. You can alternatively use belongsTo relationship.
If you want to use custom column names, just specify them in relationship methods:
public function user()
{
return $this->hasOne('App\User', 'id', 'user_id');
// alternatively
return $this->belongsTo('App\User', 'user_id', 'id');
}
Just go through documentation without skipping paragraphs and you will get going in a few minutes :)
https://laravel.com/docs/5.1/eloquent-relationships#defining-relationships
Also, this will not work:
$patient = new Patient();
$patient->patientId = (string)Uuid::generate();
$patient->user()->save($user);
new Patient() only creates the object, but does not store it in DB, so you will not be able to save relationships. You need to create the object and store it to DB to avoid this problem:
$patient = Patient::create(['patientId' => (string)Uuid::generate()]);
$patient->user()->save($user);
...
// or
$patient = new Patient();
$patient->patientId = (string)Uuid::generate();
$patient->save();
$patient->user()->save($user);
...
When you're setting up your relationship, you can to specify the name of the primary key in the other model. Look here.
I'm not sure, but I think you relationships are not defined properly.

Categories