Count how many users are there per each category - php

I'm trying to get user data, them get department value to array so I can group it and count how many users are part of the same department.
User table:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Department table:
Schema::create('departments', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('name');
});
Assignment table:
Schema::create('assignments', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('name');
$table->unsignedInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->unsignedInteger('department_id')->nullable();
$table->foreign('department_id')->references('id')->on('departments');
});
public function setDepartment($users)
{
$departmentArray = [];
$users = DB::table('users')
->leftJoin('assignments','assignments.user_id','=','users.id')
->leftJoin('departments','assignments.department_id','=','department.id')
->select('assignments.id as assignments',
'assignments.name as assignment_name',
'departments.id as dept_id',
'departments.name as dept_name',
'users.id as user_id',
'users.name as user_name'
)
->where('user_id','=',$users->id)
->get();
foreach($users as $user) {
$assignments = $user->assignments;
$dept_id = $user->dept_id;
$departmentArray[$user->dept_id] = $user->dept_name;
}
$users->department = $departmentArray;
$users->dept_id = $dept_id;
}
}
Then whenever I try to call this like:
public function index() {
$users = DB::table('users')->get();
$users = $this->setDepartment($users);
return view('/users/list', [
'users' => $users
]);
}
I receive
"Trying to get property 'user_id' of non-object"

'A department has many users through assignments'
Documentation for hasManyThrough: https://laravel.com/docs/5.7/eloquent-relationships#has-many-through
Departments Model:
public function users()
{
return $this->hasManyThrough('App\User', 'App\Assignment');
}
'Count how many users there are for each department'
Departments controller:
public function index()
{
$departments = Department::all();
foreach($departments as $department)
{
// This line returns the number of users for the department
// Use this however you please
$department->users->count();
}
}
Documentation for count() found here: https://laravel.com/docs/5.7/eloquent#retrieving-aggregates
You can work out the reverse of the relationship if you need to go from users to department, but I would suggest looking into eloquent, it can be quite handy for queries such as these. Let me know if you need any further clarification.
Edit:
For access from user to department, this is one way of defining the relationships.
User Model:
// A user belongs to many departments through their assignments
public function departments()
{
return $this->hasManyThrough('App\Department', 'App\Assignment');
}
This way you can access the departments of the user like so:
$departments = $user->departments();
And iterate through the $departments, accessing the count() as explained above.

Related

Laravel get which Categories belong to logged user in ManyToMany

in my simple blog web application i have some categories and users which stored in database, each category may belongs to one or many user and i try to get them to show each user logged, for implementing this scenario i have this tables:
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id')->index()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->string('name')->nullable();
$table->string('family')->nullable();
$table->string('username')->unique();
$table->rememberToken();
$table->softDeletes();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent();
});
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('category_id')->index()->nullable();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->string('category_name');
$table->softDeletes();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent();
});
and then, creating many to many table:
Schema::create('category_user', function (Blueprint $table) {
$table->unsignedBigInteger('user_id')->index();
$table->unsignedBigInteger('category_id')->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->primary(['user_id','category_id']);
});
now how can i get categories of logged user like with this code:
$categories = Category::whereNull('category_id')
->with(['childrenCategories', 'users' => function ($query) {
//$query->where('id',auth()->user()->id);
}])
->withCount('posts')
->get();
You can query the relationship existence with whereHas to get only the categories which belongs to the authenticated user.
$categories = Category::whereNull('category_id')
->whereHas('users', function ($query) {
$query->where('id', auth()->user()->id);
})
->with([
'childrenCategories',
'users' => function ($query) {
$query->where('id', auth()->user()->id);
}
])
->withCount('posts')
->get();
inside Your User Model, add the relationship btw both Models:
public function categories()
{
return $this->belongsToMany('App\Models\Category');
}
inside Your Controller:
$user = App\Models\User::find(1);
now you can get the categories of your user
foreach ($user->categories as $category) {
//
}
https://laravel.com/docs/8.x/eloquent-relationships#many-to-many

I want to display job with company that related to single postjob by category in laravel?

I have three table below:
I want to display all Related job post by category in Single jobpost. and I already have single job post page but in the same single job page I want to display related jobs in the left side. see my picture!
what is controller should be and in the Single job page (view) should be? please help?
My jobController
public function show($id, $company_id)
{
$singleJob = Job::find($id);
$company = Company::find($company_id);
$similarJob = Job::with('company')->where('category_id', $id)->get();
return view('pages.single-job')->with([
'singleJob'=> $singleJob,
'company'=> $company,
'similarJob' => $similarJob,
]);
}
My relationship
job.php
public function company(){
return $this->belongsTo(Company::class);
}
Job.php
public function category(){
return $this->belongsTo(Category::class);
}
//category.php
public function job(){
return $this->hasMany(Job::class);
}
//company.php
public function job(){
return $this->hasMany(Job::class);
}
Job table
Schema::create('jobs', function (Blueprint $table) {
$table->increments('id');
$table->integer('company_id');
$table->string('jobTitle');
$table->longText('jobDescription');
Company Table
Schema::create('company_types', function (Blueprint $table) {
$table->increments('id');
$table->integer('admin_id');
$table->string('name');
$table->timestamps();
});
Category table
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('name');
$table->timestamps();
});
You can use whereHas like this :
public function show($id, $company_id)
{
$singleJob = Job::find($id);
$company = Company::find($company_id);
$similarJobs = Job::with('company')
->whereHas('category', function ($query) use($singleJob) {
$query->where('id', $singleJob->category->id);
})
->get();
return view('pages.single-job')->with([
'singleJob'=> $singleJob,
'company'=> $company,
'similarJobs' => $similarJobs,
]);
}
And in the view you can use it like this :
#foreach ($similarJobs as $similarJob)
// Add the job partial, componnent or just your HTML here for showing the Job
#endforeach
For the question in the comment, to find jobs that have a company that belongs to a given industry :
$some_industry_type_id = 1;
$jobsOfIndustryType = Job::whereHas('company', function ($query) use($some_industry_type_id) {
$query->where('industry_type_id', $some_industry_type_id);
})
->get();

Getting distant belongsToMany through belongsToMany

I'm trying to grab a distant relationship and it isn't working. I've tried doing a hasManyThrough but that doesn't appear to work for belongsToMany relationships. It was throwing a query error.
Here are my migrations:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('role_user', function (Blueprint $table) {
$table->integer('role_id');
$table->integer('user_id');
});
Schema::create('permissions', function (Blueprint $table) {
$table->increments('id');
$table->string('group');
$table->string('name');
$table->timestamps();
});
Schema::create('permission_role', function (Blueprint $table) {
$table->integer('permission_id');
$table->integer('role_id');
});
Here are my models:
class User extends AuthUser
{
//
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
class Role extends Model
{
//
public function permissions()
{
return $this->belongsToMany('App\Permission');
}
}
What I'm trying to do:
$user = App\User::find(1);
Log::info($user->roles->permissions);
This gives me a Property [permissions] does not exist on this collection instance. error.
How do I grab the users permissions through their roles?
EDIT:
I've come up with this ugly solution to what I'm trying to do:
if (auth()->check()) {
if (auth()->user()->roles->contains('name', 'Admin')) {
Gate::before(function () {
return true;
});
}
else {
$permissions = [];
foreach (auth()->user()->roles as $role) {
$permissions = array_merge($permissions, $role->permissions->pluck('name')->all());
}
foreach (array_unique($permissions) as $permission) {
Gate::define($permission, function () {
return true;
});
}
}
}
How can I improve this?
You should eager load those relationships like this:
$user = User::with(['roles', 'roles.permissions'])->where('id', 1)->first();
This will give you an array of roles, and each role with their respective permissions.
Permission::whereHas('role', function($query) use ($user_id) {
return $query->whereHas('user_id', $user_id);
});
The idea in the above query is that when you want the many to many of a distant relationship, you work backwards.
change $user=App\USER->find(1);
to this
$user= App\User::find(1);
try this will work for you
you have not set foreign key in migration
$table->foreign('role_id)->references('id')->on('roles');
Same define for users
It gave you Property [permissions] does not exist on this collection instance. error because: $user->roles returns a collection of roles while permissions in your model Role is for a single model only ..
Basically you have to foreach($user->roles as $role) before you can use $role->permissions
but here's a sample where you don't have to foreach to get a permission depending on a role ..
auth()->user()->roles->where('name','=','Administrator')->permissions;
and that would be returning an array/collection of permissions of an administrator ..

Laravel one to many relationship results

Hello i am trying to create one to many relationship. One user from user table could have many companies, on other side company could have only one user.
my migration for company table is
public function up()
{
Schema::create('companies', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('address');
$table->string('city');
$table->string('state');
$table->string('contact_person');
$table->string('phone');
$table->string('industry');
$table->string('website');
$table->integer('id_user')->unsigned();
$table->foreign('id_user')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
my user model is
/**
* Get the posts for the user.
*/
public function companies()
{
return $this->hasOne('App\Company','user_id');
}
my company model is
public function users()
{
return $this->belongsTo('App\User','id');
}
i am trying to get all companies for specific user
try with whereHas but no data in relation object
$results = Company::whereHas('users', function ($query) {
$query->where('users.id',1);
})->get();
Where is my error?
First thing you should change is companies() relation. It has to be hasMany, not hasOne:
public function companies()
{
return $this->hasMany('App\Company');
}
Then get user with all his companies:
$result = User::where('id', $id)->with('companies')->first();
Or, if you want to use Company model like in your example and get only companies:
$result = Company::where('user_id', $id)->get();
Also, you're using id_user in migration. Change it to user_id.

How to get all items with a certain property in pivot table with eloquent?

I have a 'favourite' functionality for my loops table. I am trying to achieve this with a pivot table. But now I'm trying to find the most efficient way to call all the logged in users favourited loops with eloquent.
loops table :
Schema::create('loops', function(Blueprint $table) {
$table->increments('id');
$table->string('name', 35);
$table->string('loop_path', 255);
$table->string('FK_user_id');
});
users table:
Schema::create('users', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('password', 60);
});
favourites table :
Schema::create('favourites', function(Blueprint $table) {
$table->increments('id');
$table->integer('FK_user_id')->unsigned();
$table->integer('FK_loop_id')->unsigned();
});
Loop.php :
class Loop extends Model {
protected $table = 'loops';
public $timestamps = true;
public function user()
{
return $this->belongsTo('App\User','FK_user_id','id');
}
public function favourites()
{
return $this->belongsToMany('App\User', 'favourites', 'FK_loop_id', 'FK_user_id');
}
}
This is how I achieve this now , but it doesn't seem efficient :
$loops = Loop::with('favourites')->
with('user')->get();
$favouritedLoops = array();
foreach($loops as $loop)
{
//check if logged in user has favourited this
$user_favorites = Favourite::where('FK_user_id', '=', Auth::user()->id)
->where('FK_loop_id', '=', $loop->id)
->first();
if ($user_favorites != null)
{
array_push($favouritedLoops, $loop);
}
}
return Response::json($favouritedLoops);
You should define favouritedLoops method in User model, then You can easily access all favourited loops.
User.php
public function favouritedLoops()
{
return $this->belongsToMany('App\Loop', 'favourites', 'FK_user_id', 'FK_loop_id');
}
and return now will look like:
return Response::json(Auth::user()->favouritedLoops);

Categories