Laravel Count from database - laravel

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.

Related

Laravel what relation to use in order to see data from another model and column

I have two models
Item:
protected $fillable = [
'code',
'name',
'uom'
];
public function recipe()
{
return $this->belongsTo('App\Recipe');
}
Recipe:
protected $fillable = [
'recipecode',
'itemcode',
'qty'
];
public function item()
{
return $this->hasMany('App\Item');
}
In migration I have:
public function up()
{
Schema::table('recipes', function (Blueprint $table) {
$table->foreign('itemcode')->references('code')->on('items');
});
}
In RecipesController I have:
public function index()
{
$recipes = Recipe::all()->sortBy('recipecode');
$items = Item::all();
return view ('recipe.index', compact('recipes', 'items'));
}
I want to see in the view recipecode, itemcode and ItemName, ItemQty etc.
#foreach($recipes as $recipe)
<tr>
<td>{{ $recipe->recipecode }}</td> // this works
<td>{{ $recipe->itemcode }}</td> // this works
<td>{{ $recipe->item->name }}</td> // this doesn't work
<td>{{ $recipe->item->uom }}</td> // this doesn't work
<td>{{ $recipe->item->qty }}</td> // this doesn't work
</tr>
#endforeach
What should I do in order to see 'name' and 'uom' columns from Items table? I think there is a problem with relations...
First, $recipe->item->name does not work as you expected because $recipe->item is a collection of App\Item, not an App\Item model instance. That's because you have set the relationship to be "hasMany"
Second, please read more about eager loading. What you're doing now are multiple queries. That's the N+1, for each recipe you are querying the database to get the items. You do not need to do that, as it's not performant at all. Use Recipe::with('item')->sortBy('recipecode')->get().
Now, keep in mind that $recipe->item is not a single item, but a collection of items that belong to that Recipe. You'll probably have to work a bit on your table to display multiple items for one Recipe.
Since you are using hasMany you must follow naming convention in naming function
public function items()
{
return $this->hasMany('App\Item');
}
In RecipesController you can eager load.
$recipes = Recipe::with('items')->sortBy('recipecode')->get();
Read documentation here: https://laravel.com/docs/master/eloquent-relationships
Also to show it in your blade
#foreach($recipes as $recipe)
<tr>
<td>{{ $recipe->recipecode }}</td> // this works
<td>{{ $recipe->itemcode }}</td> // this works
#foreach($recipe->items as $item)
<td>{{ $item->name }}</td>
#endforeach
</tr>
#endforeach
Other answers share why you can't directly use $recipe->item. However, I think there is a bigger mistake in database design.
The database that you have designed have a one to many relation. Like, one recipe has a lot of items. However, the reverse one that one item has only one recipe seems wrong. You can cook many recipes with one items. I.E. you can make chicken fry and chicken curry with chicken.
The database design should be something like this,
recipes: code, name, uom
items: code, name
item_recipe: item_code, recipe_code, qty

Unable to display relations data from eloquent relationship

I'm trying to display in my view data from an eloquent relationship but i seem to be doing a tiny bit wrong. dd shows the relation in the collection but i just can't call the data correctly in my view. Below is what i have done
Employee model
public function task()
{
return $this->hasMany(Task::class);
}
Task model
public function employee()
{
return $this->belongsTo(Employee::class);
}
TaskController
public function index()
{
$alltask = Task::with('employee')->get();
dd($alltask);
/*return view('task.task', compact('alltask', 'empwithtask'));*/
}
task view
#foreach ($alltask as $task)
<tr>
<td>{{ $task->priority }}</td>
<td>{{ $task->firstname }}</td>
/* this is meant to be the employee.firstname */
<td>{{ $task->title }}</td>
<td>{{ $task->begin }}</td>
</tr>
#endforeach
I'm not able to display $task->firstname, firstname is from the employees table. Below is a snapshot of the result of dd
How do I show the employee firstname?
$task->employee->firstname

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.

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

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