OrderBy from relationship, Laravel - laravel

I have a table of Questions, where I use:
$query->orderBy($request->sort_by, ($request->sort_direction === 'false') ? 'asc' : 'desc');
//sort_by and sort_direction are from front-end, and this works for my main table
But in that table I have 2 relationships, and I want to sort by a column from the table that has a relationship, also to sort by a count of that.
Ex: a Question has many answer_history, each answer_history has a answer_type column ('none' or 'skipped') I want to sort by count(answer_type = 'none').
$query = Question::select(['id', 'free_text', 'title', 'best_match', 'created_at']);
$query->with('answer_history');
$query->with(['bestMatch']);
$query->orderBy($request->sort_by, ($request->sort_direction === 'false') ? 'asc' : 'desc');
return response()->json($query->paginate($request->per_page));
//this works just for main table
UPDATE:
if($request->sort_by){
if($request->sort_by === 'best_match'){
$query->orderBy(function ($bestMatch, $key) {
return count($bestMatch['name']);
},($request->sort_direction === 'false') ? 'asc' : 'desc');
}else{
$query->orderBy($request->sort_by, ($request->sort_direction === 'false') ? 'asc' : 'desc');
}
}
// I tried to do this for a column from best_match, but is not working

You can apply the check on the relationship when you lazy load it.
->with(['bestMatch' => function ($query) use ($request){
if($request->sort_by && $request->sort_by === 'best_match') {
$query->orderBy('name', 'desc');
}
}
])
You can do same for the 'answer_history'.
Note: Code is not tested.

Related

How can I write the on Laravel eloquent?

The is my DB table screen shot
$query = DB::table('categories');
$query->select('categorsies.*', 'c2.value as name', 'c2.store_id as store_id', 'c2.attribute_id as attribute_id', 'c2.entity_id as entity_id');
if ($this->store_id != 0) {
$query->where('c2.store_id', $this->store_id)->orWhere('store_id', 0);
} else {
$query->where('c2.store_id', $this->store_id);
}
$result_data = $query->get();
I want to get the row, if there is a store_id match get that row from the table otherwise get 0 default row
You're missing the c2 table in your query. Also, you could use when to get the if statement logic in the query.
$query = DB::table('categories')
->when(
$this->store_id != 0,
fn ($query) => $query->where('store_id', $this->store_id)->orWhere('store_id', 0),
fn ($query) => $query->where('store_id', $this->store_id)
)
->get();

Laravel - Filter collection with closure on relationship

Wondering if there is a way to use closure on a relationship in order to filter the whole line if there isn't a value which corresponds?
Example code:
foreach ($paiementMethods as $value) {
$giftCards = GiftCard::with(['userEntered', 'userEmployee', 'client', 'payement', 'payement.payementMethods' => function($query) use ($value)
{
$query->where('id', $value);
}])
->where('date','>=', $dateStart)
->where('date','<=', $dateEnd)
->orderBy('updated_at', 'desc')->get();
$giftCardsCollection = $giftCardsCollection->merge($giftCards);
}
}
In this example, if $query->where doesn't find a row for the payement.payementMethods which matches the $value, I want the giftCard to return null. The result I get is the giftCard with only the relation on payement.payementMethods being empty.
My other solution would be to query the giftCard and after that checking the $value to see if I have to include the giftCard in the collection or not.
Best regards
I think using whereHas, it can be solved
$giftCards = GiftCard::with(['userEntered', 'userEmployee', 'client', 'payement', 'payement.payementMethods'])
->whereHas( 'payement.payementMethods', function($query) use ($paiementMethods) {
$query->whereIn('id', $paiementMethods);
})
->where('date','>=', $dateStart)
->where('date','<=', $dateEnd)
->orderBy('updated_at', 'desc')
->get();

Laravel OrderBy Errors with 5.8 Upgrade

Having trouble with Laravel 5.8 because the orderBy commands stopped working. How would I rewrite these two areas of a controller so it stops throwing an error?
public function index(Request $request)
{
$clients = Client::orderBy('identifier', 'name')->paginate(15);
return view('admin.clients.index')->with('clients', $clients);
}
public function closed()
{
$sortBy = 'name';
$query = Client::onlyTrashed()->orderBy($sortBy, $sortBy == 'created_at' ? 'name' : 'asc')
->orderBy('created_at', 'name');
$projects = $query->get();
return view('admin.clients.index')->with(['clients' => $projects, 'sortBy' => $sortBy]);
}
orderBy(string $column, string $direction = 'asc')
orderBy has two parameters, the second one is direction.
Before version 5.8, if the direction value you passed is not asc, it will automatically set desc as direction value:
$this->{$this->unions ? 'unionOrders' : 'orders'}[] = [
'column' => $column,
'direction' => strtolower($direction) == 'asc' ? 'asc' : 'desc',
];
After Laravel 5.8+, if the direction value is not asc or desc, it will show the error:
if (! in_array($direction, ['asc', 'desc'], true)) {
throw new InvalidArgumentException('Order direction must be "asc" or "desc".');
}
So if you want to order by two column, you can use two orderBy:
$clients = Client::orderBy('identifier')->orderBy('name')->paginate(15);
# Raw SQL:
# select * from clients order by identifier asc, name asc

Laravel remove parent if related collection

I have a model with a related collection
now im doing this query
$data = DeliveryPartner::when($filter, function ($q) use ($request) {
})
->with(['orders' => function ($query) {
$query
->where('delivery_partner_invoice_id', '=', '')
->orWhereNull('delivery_partner_invoice_id')
->whereIn('status', ['payment-accepted', 'completed', 'full-refund', 'partial-refund']);
}])->get();
Now i am wondering. If the orders returns empty is it posible to remove this parent from the collection?
I Know i can do this after the eloquent query with a loop. But is it possible to do this in the query?
we cant completely remove that parent ( with index ) BUT you can set those to null using transform() like this;
$data = DeliveryPartner::when($filter, function ($q) use ($request) {
})
->with(['orders' => function ($query) {
$query
->where('delivery_partner_invoice_id', '=', '')
->orWhereNull('delivery_partner_invoice_id')
->whereIn('status', ['payment-accepted', 'completed', 'full-refund', 'partial-refund']);
}])->get()->transform(function($item){
if(!$item->orders->count() ){
return;
}
return $item;
});
Note: this will not completely remove those parents but it will set them to empty.

Laravel eloquent relation search using child table record

Problem :
I want only that records where relational records [ user ] not null.
In my case I want only first record. where user is not null
Result:
User Table
id
name
email
Project Tabel
id
title
user_id [foreign key]
My code is like this
$projects = App\Project::with(['user' => function ($user) {
$user->where('name', '=', 'Ketan');
}])
->get();
foreach ($projects as $project) {
echo $project->title.' - '.$project;
}
My result is like this :
The below code is working
$projects = App\Project::whereHas('user', function ($user) {
$user->where('name', '=', 'Ketan');
}])->get();
Change 'with' to 'whereHas' and note that whereHas doesn't accept the array as the param
For reference Laracasts Link
I got solution of my question
$projects = App\Project::whereHas(['user' => function ($user) { <--Change Here
$user->where('name', '=', 'Ketan');
}])
->get();
Only Change 'with' to 'whereHas'
By this solution, I have got only those Project records in which user ( relational record ) is not null.
You can try:
$projects = App\Project::with(['user' => function ($user) {
$user->where('name', '=', 'Ketan');
}])
->get();
foreach ($projects as $project) {
if($project->user != null){
echo $project->title.' - '.$project;
}
}

Resources