Dynamic properties with ManyToOne (Laravel4/Eloquent) - laravel-4

I have a pretty basic relationship wherein searches are logged and stored along with the ID of the user who performed the search.
I'm trying to output this log and display the username instead of the id.
Search
public function user()
{
return $this->belongsTo('User');
}
User
public function searches()
{
return $this->hasMany('Search');
}
If I then pass Search::all(); to the view, how can I echo the username? Among many other things, I've tried:
#foreach($searches as $search)
<tr>
<td>{{ $search->user->username }}</td>
<td>{{ $search->description }}</td>
<td>{{ $search->product }}</td>
<td>{{ $search->group }}</td>
</tr>
#endforeach
Any help is much appreciated. Thanks!

Currently, Your loop has N + 1 problem.
Your loop will execute 1 query to retrieve all of the Searches on the table, then another query for each search to retrieve the user. So, if you have 20 searches, this loop would run 21 queries.
<td>{{ $search->user->username }}</td>
to avoid N + 1 problem, use the eager loading to load the relationship.
Search::with('user')->all()
More info about N+1 problem:
http://laravel.com/docs/eloquent#eager-loading

Related

Jstree in laravel

I am newbie to jsTree, I want to use it in my Laravel project.I have department and user table .A department has many users.A user belongs to one department.This is the foreach loop that i tried to show users and departments,but its not with jstree.I coudn't find any information that could help me with this in Laravel.I would appreciate a lot if someone could help me with some information about this.Thanks in advance
#foreach($employees as $employee)
<tr>
<td>{{ $employee->name }}</td>
<td>{{ $employee->department->name}}</td>
</tr>
#endforeach
department.php
{
return $this->hasMany(Employee::class);
}
employee.php
public function department()
{
return $this->belongsTo(Department::class);
}

Make a sum() of column accessors Laravel

im improving my skills in laravel making a simple challenges web but i stuck on the next problem.
I have the users table with the id, name, mail, etc. The challenges table where i list all the challenges (with columns id, name, body, answer, score) and a third table called "Answers" where i post each try of the users solving a challenge with the columns id, user_id, challenge_id, success (boolean) and score.
Now i'am trying to make a ranking of users with their scores. The problem is to show a sum() of the column 'score' in the table answers where user_id.answers = users.id. So i can get easy the total score for each user.
For now i solved the problem doing this in blade:
#foreach($users as $user)
<tr>
<th>{{ $user->id }}</th>
<td>{{ $user->name }}</td>
<td>Team pindonga</td>
<td>{{ score = DB::table('answers')->where('user_id', $user->id)->sum('score') }} </td> </tr>
#endforeach
works perfectly, but i want to get them by desc score (for now i solved the desc with js but want to get desc order from the eloquent query) and have something like this in the blade:
#foreach($users as $user)
<tr>
<th>{{ $user->id }}</th>
<td>{{ $user->name }}</td>
<td>Team pindonga</td>
<td>{{ $team->score }} </td> </tr>
#endforeach
I was thinking about solve it with accessors doing something like this:
public function getScoreAttribute($value)
{
return $this->groupBy('user_id')->where('user_id', '=', $value)->sum('score');
}
also i have a relationship belongsTo in the answers modle to users and a hasMany in the users to answers. But i'm not sure of how pass the results to blade. Tried in tinker:
>>> \App\Answer::find(1)->score;
=> "3400"
>>> \App\Answer::find(2)->score;
=> "3400"
>>> \App\Answer::find(5)->score;
=> "3400"
allways getting the sum of the id = 1. And with $user->score; in the blade foreach i got a '0'.
Using the relationship with Blade would be {{ $user->answers->sum('score') }}. No accessor needed.
For sorting I would use the sortByDesc collection method.
$users = User::get();
$users = $users->sortByDesc(function ($user) {
return $user->answers->sum('score');
});
I think this is what you're looking for. It takes a while to get used to Eloquent ORM :-)
foreach($users as $user){
print $user->answers->sum('score');
}
https://laravel.com/docs/5.6/queries#aggregates

Laravel 5.4: One to Many with One to One

I created one to one relationship where user belongs to town, so in User model I have:
public function town()
{
return $this->belongsTo('App\Town');
}
and in users table I have town_id column. So, when user post something it says that user is from that town. That works.
Now, I created Settlement model which in same way belongs to App\Town (many users can come with one town), so again when settlement is created with some user it displays town of user and settlement which also contain town_id as that user table. (I hope I'm not confusing)
Question: When user is logged in, how to display settlements from his town only?
This is my code until now:
AdminSettlementsController:
public function index()
{
$settlements = Settlement::paginate(10);
$towns = Auth::user()->town->id;
$town[$towns] = Auth::user()->town->name;
$reon = Reon::pluck('name', 'id')->all();
return view('admin.settlements.index', compact('settlements', 'town', 'reon'));
}
User model has this:
public function town()
{
return $this->belongsTo('App\Town');
}
and index.blade.php in settlements folder has this table:
#if ($settlements)
#foreach ($settlements as $settlement)
<tr>
<td>{{ $settlement->id }}</td>
<td>{{ $settlement->town->name }}</td>
<td>{{ $settlement->reon->name }}</td>
<td>{{ $settlement->name }}</td>
</tr>
#endforeach
#endif
I presume that in Town model I need to have settlements() method where that method hasMany App\Settlement but I don't know how to go from there.
I hope my english is not too bad. Thanks

Display results of join query in blade

I'm having a bit of a struggle displaying results from a query in a blade template. The basics: I have two tables; countries and issuers. The Country model has a hasMany relation to Issuer, and vice versa. Both relations are properly defined in the models. I am trying to display a list of issuers that contains the name (nation) of the country as well. My query, in the IssuersController, is as follows:
$issuers = ISSUER::join('countries', 'issuers.country_id', '=', 'countries.id')
->select('issuers.*', 'countries.nation')
->orderBy('nation', 'asc')
->orderBy('author', 'asc')
->get();
This query works and dd(); shows it returning an array for each issuer that includes all of the issuer data as well as the corresponding country name as nation. Perfect. However, when I attempt to display this in my view I run into a wall. My first attempt was to just use
#foreach($issuers as $issuer)
<tr>
<td>{{ $issuer->id }}</td>
<td>{{ $issuer->nation }}</td>
<td>{{ $issuers->author }}</td>
This returns an undefined variable on $nation. I'm not sure why this happens as I'm not attempting to access the relationship. I'm simply trying to access the results of an array that was returned from the query. The relationship should not be relevant at that point. Anyway, attempting to use the relationship I try
#foreach($issuers as $issuer)
<tr>
<td>{{ $issuer->id }}</td>
#foreach($issuer->nation as $nation)
<td>{{ $issuer->nation }}</td>
#endforeach
<td>{{ $issuers->author }}</td>
Which returns and invalid argument supplied in foreach() error. Next I attempt to use the method...
#foreach($issuers as $issuer)
<tr>
<td>{{ $issuer->id }}</td>
#foreach($issuer->Country() as $nation)
<td>{{ $issuer->nation }}</td>
#endforeach
<td>{{ $issuers->author }}</td>
This throws no error but also returns nothing. The colum is simply skipped and everything else that is echoed gets shifted one column to the left.
I'm sort of lost here and I think it's because my brain is stubbornly holding on to the idea that I'm accessing elements of a query result rather than elements of a relationship, so I can't quite figure out why I need a separate loop for that one column, or how that loop should work. Any help would be appreciated.
EDIT: Changed the last part because I typed it wrong.
Answering this for anyone that stumbles upon it later. I was able to access the value of nation directly from the query result without the model relation by changing the query from
->select('issuers.*', 'countries.nation')
to
->select('issuers.*', 'countries.nation as nation')
From their I simply accessed the value as I would everything else:
<td>{{ $issuer->id }}</td>
<td>{{ $issuer->nation }}</td>
<td>{{ $issuers->author }}</td>
Change this
$issuers = ISSUER::join('countries', 'issuers.country_id', '=', 'countries.id')
->select('issuers.*', 'countries.nation')
->orderBy('nation', 'asc')
->orderBy('author', 'asc')
->get();
TO
$issuers = ISSUER::
->join('countries', 'issuers.country_id', '=', 'countries.id')
->derBy('nation', 'asc')
->orderBy('author', 'asc')
->get();
Get all the content in your Blade like this
{{ $issuers ['type_the_name_of_the_column_you_want_to_display'] }}

Laravel Count from database

I want to count the amount of workers a company has.
So it shows like: McDonalds - 200 Employees (example)
Model:
public function getTotalWorkers()
{
return $this->hasMany('App\User')->whereCompanyId($this->company_id)->count();
}
View:
#foreach($companies as $company)
<tr>
<td>{!! link_to_route('company.edit', $company->name, [$company->id] )!!}</td>
<td>{{ $getTotalWorkers }}</td>
<td>{{ ' /' }}</td>
<td>{{ $company->parent_id }}</td>
<td>{{ ' /' }}</td>
<td>{{ $company->active }}</td>
</tr>
#endforeach
Controller:
public function index()
{
$getTotalWorkers = $this->company->getTotalWorkers();
$companies = Company::get();
return view('company.index', ['companies' => $companies, 'getTotalWorkers' => $getTotalWorkers]);
But this gives me an error: Call to a member function getTotalWorkers() on a non-object
How can I fix this or what am I doing wrong?
it looks like you are calling getTotalWorkers() on $post, not $company on the fourth line of the view snippet you have posted.
How you are doing it currently fundamentally will not work for what you want it to do.
You are currently calling ->getTotalWorkers() on your Controller class since you are using:
$getTotalWorkers = $this->company->getTotalWorkers();
This wont work as the controller does not have this method (Your use of $this-> tells PHP to call it on the current class, it will work inside your model class but not on your controller. You have to call it on something, ie a company).
To get it to work how you are wanting it, remove that line from your controller, remove the "getTotalWorkers" => $getTotalWorkers, too.
In your view you can change:
<td>{{ $getTotalWorkers }}</td>
To:
<td>{{ $company->getTotalWorkers() }}</td>
Which will get it to count the number of workers for each company. Note this will run a new query for each different company you list.

Resources