Laravel Eloquent query with join, count and group by - laravel

I'm trying to remake this query:
return DB::select(DB::raw("SELECT COUNT(orders.id), name FROM orders JOIN users ON orders.manager_id = users.id GROUP BY users.id"));
I have Order model which has links to another tables using belongsTo() method, there are several of them:
public function user()
{
return $this->belongsTo(User::class);
}
public function post()
{
return $this->belongsTo(Post::class);
}
public function manager()
{
return $this->belongsTo(User::class, 'manager_id');
}
When I use simple queries like Order::all() it works fine but I've tried to call this:
return Order::groupBy('users.id')
->selectRaw('COUNT(orders.id), name')
->get();
Of course, Laravel don't know should I use either user name or manager name as it's two relations with users table in Order. How should I write the query above properly?

return Order::groupBy('users.id')
->select(DB::raw('COUNT(orders) AS TOTAL_ORDERS'))
->addSelect('name')
->get();
You can count with DB:raw i think it will work for u.

Related

How can I paginate Laravel's Eloquent's relationships' relationships?

I have two tables, users and profiles. A user has one profile. Also a user has referrals. The referrals are referenced by the column referrer_id in the users' table. So a user has a referrer, and a user can have many referrals.
Define a one-to-one relationship on the User's Model:
public function profile()
{
return $this->hasOne(Profile::class);
}
Define an inverse one-to-one relationship on the User's Model:
public function referrer()
{
return $this->belongsTo(User::class);
}
Define a one-to-many relationship on the User's Model:
public function referrals()
{
return $this->hasMany(User::class, 'referrer_id');
}
Define an inverse one-to-one or many relationship on the Profile's Model:
public function user()
{
return $this->belongsTo(User::class);
}
I wish to retrieve the user's profile, the user's referrals along with their profiles, and the referrals' referrals along with a count of each of the referrals' referrals.
The following Eloquent query works, but doesn't paginate:
namespace App\Http\Controllers;
class ReferralsController extends Controller
{
public function index(Request $request)
{
return $request->user()->loadMissing(['profile', 'referrals' => function ($query) {
$query->with(['profile', 'referrals'])->withCount('referrals');
}]);
}
}
I've tried to add ->paginate() to the query (on both as show below and also one or the other) but it doesn't work:
return $request->user()->loadMissing(['profile', 'referrals' => function ($query) {
$query->with(['profile', 'referrals'])->withCount('referrals')->paginate(2);
}])->paginate(2);
Adding it to the inner function doesn't do anything, and adding it to the main query just retrieves the entire users table.
EDIT
I've realized that adding ->paginate() to the inner function actually does limit the number of rows in the collection, but there is no Paginator instance anywhere, so I don't have access to any of the links to move pages.
Got it to work by doing it separately:
$profile = $request->user()->profile()
->firstOrFail();
$referralsPaginator = $request->user()->referrals()
->with('profile')
->withCount('referrals')
->paginate(2);

How to get all Users with a specific Role from a Group model

I have a Group that has a many-to-many relationship with User. And each User can have multiple roles which I implement with spatie/larevel-permission
I am trying to retreive all Users attached to a Group that have a specific role, e.g. learner
this is what i have so far:
class Group extends Model
{
// other code
//
public function learners(){
return $this->users::whereHas('roles', function($q) {
$q->where('name', 'learner');
})->get();
}
// other code
public function users() {
return $this->belongsToMany(User::class)->withTimestamps();
}
}
And I get the error:
Illuminate\Database\Eloquent\Collection::whereHas does not exist
I understand that $this->users returns a Collection, and that's why I get that error message. But I'm not sure how else I could get the users of a group who have the 'learner' role.
You should be calling the relationship method users() which returns the Belongs To Many relationship not the dynamic property users which returns the result of the query for the relationship (Collection). Also you could make the learners method a relationship method itself instead of directly returning the result:
public function learners()
{
return $this->users()
->whereHas('roles', fn ($q) => $q->where('name', 'learner'));
}
$group->learners;
It all depends what you intend to do with this method.

Retrieve related models using hasManyThrough on a pivot table - Laravel 5.7

I'm trying to retrieve related models of the same type on from a pivot table.
I have 2 models, App\Models\User and App\Models\Group and a pivot model App\Pivots\GroupUser
My tables are have the following structure
users
id
groups
id
group_user
id
user_id
group_id
I have currently defined relationships as
In app/Models/User.php
public function groups()
{
return $this->belongsToMany(Group::class)->using(GroupUser::class);
}
In app/Models/Group.php
public function users()
{
return $this->belongsToMany(User::class)->using(GroupUser::class);
}
In app/Pivots/GroupUser.php
public function user()
{
return $this->belongsTo(User::class);
}
public function group()
{
return $this->belongsTo(Group::class);
}
I'm trying to define a relationship in my User class to access all other users that are related by being in the same group. Calling it friends. So far I've tried this:
app/Models/User.php
public function friends()
{
return $this->hasManyThrough(
User::class,
GroupUser::class,
'user_id',
'id'
);
}
But it just ends up returning a collection with only the user I called the relationship from. (same as running collect($this);
I have a solution that does work but is not ideal.
app/Models/User.php
public function friends()
{
$friends = collect();
foreach($this->groups as $group) {
foreach($group->users as $user) {
if($friends->where('id', $user->id)->count() === 0) {
$friends->push($user);
}
}
}
return $friends;
}
Is there a way I can accomplish this using hasManyThrough or some other Eloquent function?
Thanks.
You can't do that using hasManyThrough because there is no foreign key on the users table to relate it to the id of the group_user table. You could try going from the user to their groups to their friends using the existing belongsToMany relations:
app/Models/User.php:
// create a custom attribute accessor
public function getFriendsAttribute()
{
$friends = $this->groups() // query to groups
->with(['users' => function($query) { // eager-load users from groups
$query->where('users.id', '!=', $this->id); // filter out current user, specify users.id to prevent ambiguity
}])->get()
->pluck('users')->flatten(); // massage the collection to get just the users
return $friends;
}
Then when you call $user->friends you will get the collection of users who are in the same groups as the current user.

How to retrieve only those object and its related model which passes the required criteria in laravel4?

I have three tables: users, departments and designations
I have created corresponding model for 'users', 'designations' and 'departments' table.
Relationship between table is:
User model
public function department(){
return $this->belongsTo('Department');
}
public function designation(){
return $this->belongsTo('Designation');
}
--
Department model
public function users(){
return $this->hasMany('User');
}
--
Designation model
public function users(){
return $this->hasMany('User');
}
Now, how would I query (in an eloquent way) to retrieve all the users that belongs to only specified department (say, 'account' department only).
I tried eager loading as well, but since there were two models that have to be fed with, it was more confusing.
I have a code as below, but now working. Help me to find the mistake
$users = new User;
$users = $users->department()->where('dept_code', '=', 'account')->get();
return View::make('staffs', compact('users'));
Here are two ways to do it:
1. From the Department side
$department = Department::where('dept_code', 'account')->first();
$users = $department->users;
2. From the User side using whereHas
$users = User::whereHas('department', function($q){
$q->where('dept_code', 'account');
})->get();
(Of course you can also use them like $users = new User; $users->where(, but I prefer the static call syntax so I use them in my examples)
You define a relationship with the constant. Like this:
User model
public function department(){
return $this->belongsTo('Department');
}
public function accounts_department(){
return $this->belongsTo('Department')->where('dept_code', 'account');
}
Then you use it like this
$all_users = new User;
$all_users = $all_users->department()->get();
$account_only_users = new User;
$account_only_users = $account_only_users ->accounts_department()->get();

Laravel 4 eloquent

Is there any way I can do this with eloquent?
$orders = Customer::with('orders','orders.shop')->where('orders.shop.location','=','Japan')->get()
Customers, orders and shop are tables where 1 customer has many orders and each order has one shop only.
Location is a column in the shop table
I keep getting an error stating orders.shop.location is a column not found.
Anyone can help? Thanks in advance.
You need to defined relationship in your model classes.
Customer model:
public function orders()
{
return $this->hasMany('Order');
}
Order model:
public function customer()
{
return $this->belongsTo('Customer');
}
Then if you want orders of a special customer you just have to do :
$orders = Customer::find($id)->orders;
Or find the user attatched to an order:
$user = Order::find($id)->user;
You can also use the same kind of relation between your Shop and Order model and do something like this:
$orders = Order::with(array('shop' => function($query)
{
$query->where('location', '=', 'japan');
}))->get();
Which should give you all orders for a shop located in japan.
More informations about this type of request:
http://laravel.com/docs/eloquent#eager-loading
in CostumerModel you need set a relationship (One To Many):
public function order()
{
return $this->hasMany('OrderModel', 'foreign_key_in_orderTable');
}
in OrderModel too:
public function costumer()
{
return $this->belongsTo('CostumerModel', 'foreign_key_in_orderTable');
}
then in OrderModel one more relationship with Shop (One To One):
public function shop()
{
return $this->hasOne('ShopModel', 'foreign_key');
}
Now in ShopModel (One To One):
public function order()
{
return $this->belongsTo('OrderModel', 'local_key');
}
query:
$orders = Customer::with('costumer', 'shop')->where('location','=','Japan')->get();

Resources