Display results of join query in blade - laravel

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'] }}

Related

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 Prevent foreach loop from repeating same results

Am doing a loop where a product can have many sizes so I display the name of the product and its 1st size and the name of the same product again with its 2nd size but anytime i try, it repeats both sizes on both product names. For example:
I want Product 1 = small, Product 1 = medium but in this case it displays...
Product 1 = small medium, Product 2= small medium. How do I solve this. Below is my blade;
#foreach ($productProductOptions as $productProductOption)
#foreach($productProductOption->product->options as $productOptions)
<tr>
<th>{{ $loop->iteration }}</th>
<td>{{ $productProductOption->product->title }}</td>
<td>{{ $productOptions->name }}</td>
</tr>
#endforeach
#endforeach
Below is my controller code which am passing to the view;
$productProductOptions = ProductProductOption::all();
This is the picture of the table am displaying the items inside...https://cdn.pbrd.co/images/H9UulFq.png
Distinct()
is the function you are seeking, which returns only distinct values from the database, I would suggest updating your controller to send only this specific detail as to save time and gain performance, however it only depends how you show your data and how big is it.
DB Query
$productProductOptions = DB::table('products')
->select('title', 'size')
->distinct()
->groupBy('title')
->orderBy('title', 'asc')
->get();
Eloquent
$productProductOptions = ProductProductOption::select('title', 'size')
->distinct()
->groupBy('title')
->orderBy('title', 'asc')
->get();

Laravel print role of user in table

I have a Laravel application. I'm using this package for roles and permissions. It works great.
I would now like to display a table of all users with their roles. Currently I'm solving it through the definition of the following in my UsersController.
public function listUsers()
{
$users_admin = Role::where('name', 'admin')->first()->users()->get();
$users_buyers = Role::where('name', 'buyer')->first()->users()->get();
$users_sellers = Role::where('name', 'seller')->first()->users()->get();
return view('admin.users.index', [
'users_admin' => $users_admin,
'users_buyers' => $users_buyers,
'users_sellers' => $users_sellers
]);
}
In the view, I then have 3 separate loops to display 3 tables (for admin users, buyers and sellers).
Needless to say I don't really like this approach and I would ideally have a single table displaying the users with their role.
So the idea is that I can write the following code (or similar) in the UsersController:
$users = User::all();
while my view contains a single foreach stating the following:
#foreach( $users_sellers as $user )
<tr>
<td align="center" class="hidden-xs">{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>{{ $user->displayRole($user->id) }}</td>
</tr>
#endforeach
In the above pseudocode, I have defined a helper that retrieves the role based on the user-id. Problem is I can't figure out what to put in the helper function?
Note: if there are other (better) methods than a helper, that would work as well for me.
As far as I see this package adds a relation in your User model, so $user->roles should be a collection with the roles assigned to the current user. To not make a query for each user you should eager load the users with their roles, like this: $users = User::with('roles')->get();.
In your Controller, get the Role, if you have it in your table
public function listUsers()
{
$users_admin = Role::where('name', 'admin')->first()->users()->get();
$users_buyers = Role::where('name', 'buyer')->first()->users()->get();
$users_sellers = Role::where('name', 'seller')->first()->users()->get();
$role = Role::get();
return view('admin.users.index', [
'users_admin' => $users_admin,
'users_buyers' => $users_buyers,
'users_sellers' => $users_sellers
'role' => $role
]);
}
In your view, just print the Role's name like this
#foreach( $users_sellers as $user )
<tr>
<td align="center" class="hidden-xs">{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>{{ $role['$user->id']['role_name']</td>
</tr>
#endforeach
Note :
<td>{{ $role['$user->id']['role_name']</td>
This line depends on how you send the $role from controller to your view. It's purpose is to return the name of the role's id's array
Hope this helps you.

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.

Dynamic properties with ManyToOne (Laravel4/Eloquent)

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

Resources