Laravel 5.4: Cannot retrieve data from a relationship - php

I'm trying to display the name of the assignee (foreign key from Users table) of each ticket by storing each name in an array from two UNION'd tables (Accesses and Reports) but it gives me this error. ErrorException
Undefined property: stdClass::$assignee.
//HomeController
$accesses = DB::table('accesses')
->select(array('id', 'fullname','emp_id','shift','state','resolved_at', 'closed_at','assigned_to'))
->where('state','=','Assigned');
$all = DB::table('reports')
->select(array('id', 'fullname','emp_id','shift','state','resolved_at', 'closed_at','assigned_to'))
->union($accesses)
->where('state', '=', 'Assigned')
->get();
$names[] = array();
foreach ($all as $one)//store in array to display in a chart
{
$names[] = $one->assignee->name; //error here
}
//Report Model
public function assignee()
{
return $this->belongsTo(User::class, 'assigned_to');
}
//Access Model
public function assignee()
{
return $this->belongsTo(User::class, 'assigned_to');
}
//Report Migration
public function up()
{
Schema::create('reports', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->nullable();
$table->string('fullname');
$table->string('emp_id');
$table->string('shift');
$table->longText('report');
$table->string('status')->default('Pending'); //Pending, Approved
$table->string('state')->default('Open'); //Open, Assigned, Resolved, Closed
$table->date('resolved_at')->nullable();
$table->date('closed_at')->nullable();
$table->integer('assigned_to')->nullable();
$table->longText('action')->nullable();
$table->timestamps();
});
}
//Access Migration
public function up()
{
Schema::create('accesses', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->nullable();
$table->string('fullname');
$table->string('emp_id');
$table->string('shift');
$table->string('request');
$table->longText('note')->nullable();
$table->string('status')->default('Pending'); //Pending, Approved
$table->string('state')->default('Open'); //Open, Assigned, Resolved, Closed
$table->date('resolved_at')->nullable();
$table->date('closed_at')->nullable();
$table->integer('assigned_to')->nullable();
$table->longText('action')->nullable();
$table->timestamps();
});
}
It gives me this error
The results should be like this

You should use merge method of collection:
$accesses = Access::select(array('id', 'fullname','emp_id','shift','state','resolved_at', 'closed_at','assigned_to'))
->where('state','=','Assigned')
->get();
$reports = Report::select(array('id', 'fullname','emp_id','shift','state','resolved_at', 'closed_at','assigned_to'))
->where('state', '=', 'Assigned')
->get();
$all = $accesses->merge($reports);

Related

Laravel WhereHas only the latest record on the HasMany Relationship

I have Items table that has relation to Histories table.
I want to get count of items that has only latest history.status
I still can't get the exact same count result because its always count all of the histories not the latest one
Here is my code:
create_items_table.php
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->string('code');
$table->string('name');
$table->longText('description')->nullable();
$table->longText('picture')->nullable();
$table->timestamps();
});
create_histories_table.php
$table->foreignId('item_id')->constrained();
$table->string('status')->nullable();
$table->longText('description')->nullable();
$table->dateTime('date')->nullable();
model of Item.php
public function histories(){
return $this->hasMany(History::class);
}
public function latestHistory(){
return $this->hasOne(History::class)->latest();
}
model of History.php
public function item()
{
return $this->belongsTo(Item::class);
}
MyController.php
$items_status['good'] = Item::with('latestHistory')->whereHas('latestHistory', function ($q) {
$q->where('status', 'good');
})->count();
$items_status['broken'] = Item::with('latestHistory')->whereHas('latestHistory', function ($q) {
$q->where('status', 'broken');
})->count();
dd($items_status);
i guess you mean latestOfMany() ?
//Item.php
public function latestHistory() {
return $this->hasOne(History::class)->latestOfMany();
}
Also do you have any solution for count the items that doesn't have
history?
Check docs for doesntHave
$items_status['no_history'] = Item::doesntHave('history')->count();

fetch data for all users in same group

My code works. But I'm not sure is it a best solution. I need option to display user players and / or players from a group user belong to. Thank you for you time.
$user = $request->user();
$userGroups = $user->groups;
$friendsPlayers = [];
foreach ($userGroups as $group) {
$groupUsers = $group->users;
foreach ($groupUsers as $groupUser) {
if ($groupUser->id !== $user->id) {
$userPlayer = $groupUser->players;
foreach ($userPlayer as $player) {
if (!in_array($player, $friendsPlayers)) {
$friendsPlayers[] = $player;
}
}
}
}
}
1.Schema/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Schema::create('groups', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('info');
$table->timestamps();
});
Schema::create('players', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->index();
$table->string('name');
$table->string('url');
$table->string('type');
$table->integer('wins');
$table->integer('lost');
$table->integer('draws');
$table->timestamps();
});
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('group_user', function (Blueprint $table) {
$table->integer('group_id')->unsigned()->nullable();
$table->foreign('group_id')->references('id')
->on('groups')->onDelete('cascade');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')
->on('users')->onDelete('cascade');
$table->timestamps();
});
2.Models/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Group extends Model
{
protected $fillable = [
'name', 'info',
];
public function users() {
return $this->belongsToMany(User::class);
}
}
class Player extends Model
{
protected $guarded = [];
public function user() {
return $this->belongsTo(User::class);
}
public function leagues() {
return $this->belongsToMany(League::class)->withPivot('win', 'lost',
'draw')->withTimestamps();
}
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function players() {
return $this->hasMany(Player::class);
}
public function leagues() {
return $this->hasMany(League::class);
}
public function scoreboards() {
return $this->hasMany(Scoreboard::class);
}
public function groups() {
return $this->belongsToMany(Group::class);
}
}
This could be a perfect use case to use Laravel Collection.
$result = $user->load('groups.groupUsers.players')
->groups
->map->groupUsers
->collapse()
->filter(function ($groupUser) use ($user) {
return $groupUser->isNot($user);
})
->unique('id')
->map->players
->collapse()
->unique('id');
A different approach is using a query to get the result.
First, lets create a sub query to get all the groups the user joined.
$groupsJoinedByUser = Group::whereHas('users', function ($query) use ($user) {
$query->whereKey($user->id);
});
We can also create that sub-query this way:
$groupsJoinedByUser = Group::select('groups.*')
->join('group_user', 'groups.id', '=', 'group_user.group_id')
->where('group_user.user_id', $user->id);
Now we can create the query to get the players:
$players = Player::select('players.*')
->join('users', 'players.user_id', '=', 'users.id')
->join('group_user', 'users.id', '=', 'group_user.user_id')
->joinSub($groupsJoinsByUser, 'groups_joined_by_user', function($join) {
$join->on('group_user.group_id', '=', 'groups_joined_by_user.id')
})
->where('users.id', '!=', $user->id);
->distinct()
->get();

Count how many users are there per each category

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.

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();

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