Laravel print role of user in table - laravel-5

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.

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

Laravel - Using Where Clause with If Statement and Parameter

I have a Laravel Query with where clause statement and a parameter in it. The $plan coming from the source is string and the values are:
Daily, Weekly, Monthly, Wallet
but the value of $plan in the destination, users table ($users) are:
1,2,3,4
Parameter Source:
#foreach($billings as $key => $billing)
<tr>
<td>{{ ++$key }}</td>
<td><a class="btn btn-info" href="{{ route('revenueDetail',$billing->plan) }}">{{ $billing->plan }}</a></td>
<td>{{ $billing->total_plans }}</td>
<td>{{ $billing->total_amount }}</td>
</tr>
#endforeach
<tr>
<td colspan="8">
{{ $billings->links() }}
</td>
</tr>
Controller: Query
public function revenueDetail($plan = null)
{
$revenuedetails = DB::table("users")
->select(
"users.username",
DB::raw("DATE(users.created_at) as subscription_date")
)
->where('users.plan', $plan)
->get();
}
What I want to achieve is that, in the where clause in revenueDetail() function, if:
$plan = Daily then users.plan = 1
$plan = Weekly then users.plan = 2
$plan = Monthly then users.plan = 3
$plan = Wallet then users.plan = 4
How do I achieve this?
Based on last sentences, i assume you need to map Daily string which == 1
protected static $type = [
'Daily' => 1,
'Weekly' => 2,
'Montly' => 3,
]
then
public function revenueDetail($plan = null)
{
$revenuedetails = DB::table("users")
->select("users.username", DB::raw("DATE(users.created_at) as subscription_date"))
->where('users.plan', self::$type[$plan] ?? null) // ?? will escape exception if $plan is null
->get();
}
From view user should send id instead of value. However if u want to send value you should ask plans table for id of value u send. I recommend to store plans in cache. Another solution is to make class with Constans like your plans (if u dont want to extend it in the future)

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

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