How to use Eloquent model property in subquery? - php

I have two tables (users, posts) and I'm trying to order users according to recent post's date.
But unfortunately I couldn't find a way to use User model's firebase_id to use in subquery. I don't want to use raw query or DB directly if it's possible to use Eloquent for such query.
How can I use User model's firebase_id as subquery parameter?
Here is my non-working code to give an idea about what I try to do:
User::select('users.*', DB::raw("SELECT MAX(id) FROM posts WHERE posts.firebase_id = users.firebase_id as recent_post_date"))
->whereHas('posts', function ($q) {
$q->withCount('comments');
})
->with(['posts' => function ($q) {
$q->withCount('comments')
->orderBy('created_at', 'ASC');
}])
->orderBy('recent_post_date', 'DESC')
->get();

You can use selectSub to add a subquery.
Try the following
$recentPostQuery = Post::select('created_at')
->whereColumn('firebase_id', 'users.firebase_id')
->latest()
->limit(1)
->getQuery();
User::select('users.*')
->selectSub($recentPostQuery, 'recent_post_date')
->whereHas('posts', function ($q) {
$q->withCount('comments');
})
->with(['posts' => function ($q) {
$q->withCount('comments')
->orderBy('created_at', 'ASC');
}])
->orderBy('recent_post_date', 'DESC')
->get();

You can do with QueryBuilder and a join:
$users = DB::table('users')
->join('posts.firebase_id ', '=', 'users.firebase_id ')
->orderBy('posts.recent_post_date', 'DESC')
->get();
UPDATE
You asked for Eloquent. You can do it with whereHas.
$users = User::whereHas('posts', function (Builder $query) {
$query->orderBy('posts.recent_post_date', 'DESC');
})->get();

Related

Laravel orWhere with left join

I'm not that good with Laravel Eloquent, so be cool pls.
I have 1 product table and 4 "target" tables (sales, novelties, liquidations and exposure).
I'm trying to get all products that have at least one of the four "targets" with this query:
return Product::leftjoin('sales', 'sales.product_id', '=', 'products.id')
->leftjoin('liquidations', 'liquidations.product_id', '=', 'products.id')
->leftjoin('noveltys', 'noveltys.product_id', '=', 'products.id')
->leftjoin('exposures', 'exposures.product_id', '=', 'products.id')
->select('products.*', 'sales.*', 'liquidations.*', 'noveltys.*', 'exposures.*')
->where('noveltys.novelty_end_at', '!=', null)
->orwhere('sales.sale_end_at', '!=', null)
->orWhere('liquidations.liquidation_end_at', '!=', null)
->orWhere('exposures.exposure_end_at', '!=', null)
->get();
Problem is, it only return products that have the first "where" clause true. (In other word, currently, this query only return produtcs with a not null novelty_end_at, it doesn't return products with a sale_end_at and others).
How can I achieve that it also return products with a not null sale_end_at, exposure_end_at and a liquidation_end_at ?
Thank you!
seems a syntax mistake
->orwhere('sales.sale_end_at', '!=', null)
should be
->orWhere('sales.sale_end_at', '!=', null)
also you can try using orWhereNotNull
like
return Product::leftjoin('sales', 'sales.product_id', '=', 'products.id')
->leftjoin('liquidations', 'liquidations.product_id', '=', 'products.id')
->leftjoin('noveltys', 'noveltys.product_id', '=', 'products.id')
->leftjoin('exposures', 'exposures.product_id', '=', 'products.id')
->select('products.*', 'sales.*', 'liquidations.*', 'noveltys.*', 'exposures.*')
->whereNotNull('noveltys.novelty_end_at')
->orWhereNotNull('sales.sale_end_at')
->orWhereNotNull('liquidations.liquidation_end_at')
->orWhereNotNull('exposures.exposure_end_at')
->get();
I found the solution, it's almost the same thing, execpt that I'm using orWhereNotNull and that I'm using DB::table at the start instead of Product::leftjoin directly.
return DB::table('products')
->leftjoin('sales', 'sales.product_id', '=', 'products.id')
->leftjoin('liquidations', 'liquidations.product_id', '=', 'products.id')
->leftjoin('noveltys', 'noveltys.product_id', '=', 'products.id')
->leftjoin('exposures', 'exposures.product_id', '=', 'products.id')
->whereNotNull('sales.sale_end_at')
->orwhereNotNull('noveltys.novelty_end_at')
->orwhereNotNull('liquidations.liquidation_end_at')
->orwhereNotNull('exposures.exposure_end_at')
->get();
Thank you!
Perhaps you could use ->orWhereHas() method. To use this function, you must define the relationship in your Sales and the four target Model classes. Documentation: https://laravel.com/docs/9.x/eloquent-relationships
Then in your query,
return Product::whereHas('noveltys', function(Builder $query) {
// your where clause
})
->orWhereHas('sales', function(Builder $query) {
// your where clause
})
->orWhereHas('liquidations', function(Builder $query) {
// your where clause
})
->orWhereHas('exposures', function(Builder $query) {
// your where clause
})
->get();

Get last record on GROUP BY using Laravel & MySql

I have two table (users and messages) .. I wrote a query to get all messages that users sent to me or I sent, using JOIN .. to get all the users I have contacted or they did.
as in the code below:
$users = Message::join('users', function ($join) {
$join->on('messages.sender_id', '=', 'users.id')
->orOn('messages.receiver_id', '=', 'users.id');
})
->where(function ($q) {
$q->where('messages.sender_id', Auth::user()->id)
->orWhere('messages.receiver_id', Auth::user()->id);
})
->orderBy('messages.created', 'desc')
->groupBy('users.id')
->paginate();
The problem here is when records grouped, I'm getting the old message not the new one according to its created_at .. So, I want to get the last record of the grouped records.
It seems like it would make more sense to make use of Eloquent's relationships here so that you can eager load the relationships instead of having to use join and group by:
$messages = Message::with('sender', 'receiver')
->where(function ($query) {
$query->where('sender_id', auth()->id())
->orWhere('receiver_id', auth()->id())
})
->orderByDesc('created') // is this meant to be 'created_at'?
->paginate();

Laravel query relationship where clause

I need filter by departamento, like where('departamento_id', '=', 1).
Tables:
membro_bancas
id
departamento_id
user_id
trabalhos
id
titulo
orientador_id (references id of membro_bancas)
coorientador_id (references id of membro_bancas)
I have this code:
$trabalho = Trabalho::with('membrobanca.departamento')
->with('coorientador')
->with('academico')
->get();
And returns this:
I got it!
I needed add orWhereHas for coorientador too. The result is this:
Trabalho::whereHas('membrobanca', function($q) use ($departamento_id) {
$q->where('departamento_id', '=', $departamento_id);
})
->orWhereHas('coorientador', function($q) use ($departamento_id) {
$q->where('departamento_id', '=', $departamento_id);
})
->with('academico')
->get();
Try this eloquent filter using whereas
$trabalho = Trabalho::whereHas('membrobanca',function($query) use ($id){
$query->where('departamento_id', '=', $id)
})
->with('coorientador')
->with('academico')
->get();
example of filter using with
$trabalho = Trabalho::with(['membrobanca',function($query) use ($id){
$query->where('departamento_id', '=', $id)
}])
->with('coorientador')
->with('academico')
->get();

Laravel Eloquent query get users from another model

I have another table called tableb and it has a user relationship defined through the user_id field.
I want to run a query against tableb where a certain date is within a certain range but then I want to grab the user table associated with that row but I only want it to grab the user if it's not been grabbed yet. I'm trying to do this all in 1 DB query. I have most of it done, but I'm having trouble with the unique part of it.
Here's what I have right now:
$tableB = TableB::select('users.*')
->join('users', 'tableb.user_id', '=', 'users.id')
->where('tableb.start_date', '>', date('Y-m-d'))
->get();
So right now I have 3 entries in tableB from the same user, and ideally I'd like to only get 1 entry for that user.
How would I go about doing this?
Since you're selecting only users data, just add a groupBy clause in your query.
$tableB = TableB::select('users.*')
->join('users', 'tableb.user_id', '=', 'users.id')
->where('tableb.start_date', '>', date('Y-m-d'))
->groupBy('users.id')
->get();
You should just add groupBy like this :
$tableB = TableB::select('users.*')
->join('users', 'tableb.user_id', '=', 'users.id')
->where('tableb.start_date', '>', date('Y-m-d'))
->groupBy('users.id')
->get
Try This Code
App/user.php
public function getrelation(){
return $this->hasMany('App\tableB', 'user_id');
}
In Your Controller
Controller.php
use App/user;
public funtion filterByDate(user $user)
{
$date = '2016-02-01';
$result = $user->WhereHas('getrelation', function ($query) use($date) {
$query->whereDate('tableb.start_date', '>', $date)
->first();
});
}

laravel 5.2 nested Where clause

How to perform a where clause using laravel eloquent with the following query:
select * from stats where payed = 1 AND WHERE (user_id = 1 OR owner_id = 1)
I don't know how to modify this code for this:
$payouts = Stat::where('payed', '1')
->???(function ($query) {
$query->where('owner_id', Auth::user()->id)
->where('user_id', Auth::user()->id);
})->get();
Change like this
$payouts = Stat::where('payed', '1');
$payouts->where(function ($payouts) {
$payouts->where('owner_id', Auth::user()->id)
->orWhere('user_id', Auth::user()->id);
})->get();
Try this
$payouts = Stat::where('payed', '1')
->where(function ($query) {
$query->where('owner_id', Auth::user()->id)
->orwhere('user_id', Auth::user()->id);
})->get();
You're close, this should do the trick:
$payouts = Stat::where('payed', '1')
->where(function ($query) {
$query->where('owner_id', Auth::user()->id)
->orWhere('user_id', Auth::user()->id);
})->get();
This is looking for where payed = 1 AND (owner_id is the current user ID OR the user_id is the current user ID)

Categories