Can this code be written using WhereHas and with only and not using Join? am filtering few data from multiple tables
public function filterByOffer(Request $request, User $user, Offer $offer)
{
$query = TradeRequest::query()
->select(
'trade_requests.uuid as trade_request_uuid',
'trade_requests.card_images_url',
'trade_requests.status',
'trade_requests.card_value',
'trade_requests.amount_payable',
'offers.*',
'cards.name',
'card_currencies.currency'
)
->join('offers', 'trade_requests.offer_id', 'offers.id')->where('offers.uuid', $offer->uuid)
->join('card_currencies', 'offers.card_currency_id', 'card_currencies.id')
->join('cards', 'offers.card_id', 'cards.id')->where('offers.user_id', $user->id)
->orderBy('trade_requests.created_at', 'DESC');
$request->whenHas('card', function ($value) use ($query) {
return $query->where('cards.name', 'like', '%' . $value . '%');
});
$request->whenHas('currency', function ($value) use ($query) {
return $query->where('card_currencies.currency', 'like', '%' . $value . '%');
});
$request->whenHas('status', function ($value) use ($query) {
return $query->where('trade_requests.status', 'like', '%' . $value . '%');
});
return $query->paginate();
}
Can this code be written using WhereHas and with only and not using Join?
Related
I have a collection of users
$department = Department::find(1)->users;
I need to get Journal relations to them, the code below is working, but here the conditions are used directly from the Users table, and I specifically need from the $department collection
User::where('name', '<>', 'Manager')
->with(['journal' => function($query) use ($request){
$query->where('schedule', 'like', "%" . $request->date . "%");
}])->get();
Try this :
$department = Department::with('users.journal')
->whereHas('users', function ($query) use ($request) {
$query->where('name', '<>', 'Manager')->whereHas('journal', function ($q) use ($request) {
$q->where('schedule', 'like', "%" . $request->date . "%");
});
})->find(1);
I want to refactor my source code when filtering records in all and specific fields.
Currently, I'm filtering all fields by passing 'search' in my request:
GET request: /api/users?search=
public function index(Request $request) {
$search = request("search") ?? "";
$users = $users->where(function ($query) use ($search) {
$query->where('code', "like", "%" . $search . "%");
$query->orWhere("first_name", "like", "%" . $search . "%");
$query->orWhere("last_name", "like", "%" . $search . "%");
$query->orWhereHas('department', function ($q) use ($search) {
$q->where('name', "like", "%" . $search . "%");
});
});
return $users->paginate(10);
}
I tried to follow this article, and now my GET request should be: /api/users?first_name=Juan&last_name=Cruz
Should I pass all request like /api/users?all=Juan to filter all fields at once?
What is the best approach when applying this kind of functionality?
If you know any acticles/resources which can serve as my reference, it would be a great help.
If you are following the article you shared, your url should look like /users?name=John&last_name=Doe&code=123
Then, you just call User::filter($filters)->get(), and it will automatically apply your query string filters to the query.
If you dont want to implement the filters functionality, you can use eloquent when method. It only apply the filter when a given condition is true.
public function index(Request $request) {
$query = User::query();
$query = $query->when(request('code'), function($query) {
$query->where('code', "like", '%'.request('code').'%')
})
->when(request('first_name'), function($query) {
$query->where('first_name', 'like', '%'.request('first_name').'%');
})
->when(request('last_name'), function($query) {
$query->where('last_name', 'like', '%'.request('last_name').'%');
})
->when(request('department'), function($query) {
$query->where('last_name', 'like', '%'.request('last_name').'%');
})
->when(request('department'), function($query) {
$query->whereHas('department', function($query) {
$query->where('name', 'like', '%'.request('department').'%');
});
});
return $query->paginate(10);
}
Based on some inputs, whether they are not null, I want to perform a Eloquent Query. I want to add the following attributes to query if they are not null.
How to make this query work?
$property = Property::
where('published','=','1');
if(!empty($searchInput)){
$property+=$property
->orWhere('name', 'like', $percentageSearch)
->orWhere('village', 'like', $percentageSearch)
->orWhere('address', 'like', $percentageSearch)
->orWhere('reference_point', 'like', $percentageSearch)
->orWhere('price', 'like', $percentageSearch);
}
if(!empty($typeInput)){
$property+=$property
->orWhere('type', '=', $typeInput);
}
if(!empty($categoryInput)){
$property+=$property
->orWhere('category_id', '=', $categoryInput);
}
$prop=$property->get();
Use a local scope and conditional queries.
$property = Property::where('published_at', 1)->search($searchInput, $typeInput, $categoryInput)->get();
// Property Model
public function scopeSearch($builder, $search, $type, $category)
{
return $builder->where(function ($query) use ($search, $type, $category) {
$query->when($search, function ($property, $search) {
$property->orWhere('name', 'like', $search)
->orWhere('village', 'like', $search)
->orWhere('address', 'like', $search)
->orWhere('reference_point', 'like', $search)
->orWhere('price', 'like', $search);
})
->when($type, function ($property, $type) {
$property->orWhere('type', '=', $type);
})
->when($category, function ($property, $category) {
$property->orWhere('category_id', '=', $category);
});
});
}
Logical Grouping
Conditional Clauses
Local Scopes
I'm having two models Company and Contact search controller, my Contact model look something like:
class Contact extends Model {
public function companies()
{
return $this->belongsToMany('App\Company', 'company_contact', 'contact_id', 'company_id');
}
}
Few of my companies are referred as client for which I have a boolean field under the name of is_client.
I want to search contacts through a param request search which compares contact's first_name and last_name also with company name. If any body wants to have contact list of all the client then they can pass a extra request of client so accordingly I made a controller something like this:
Contact::when($request->client && $request->search, function ($q) use($request) {
$q->whereHas('companies', function ($q) use ($request) {
$q->where('is_client', true)->where(function ($q) use ($request) {
$q->orWhere('name', 'like', '%'. $request->search . '%');
});
})->where(function ($q) use ($request) {
$q->orWhere('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%');
});
})->when($request->client == null && $request->search, function ($q) use($request) {
$q->where('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%')
->orWhereHas('companies', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
})->when($request->client && $request->search == null, function ($q) use ($request) {
$q->whereHas('companies', function ($q) use ($request) {
$q->where('is_client', true);
});
})
->paginate(30)
It work perfectly fine with non-client contacts and for client contact initial list appears fine but when we type something it behaves not as desired. I may be doing some logic error. Help me out in this or guide me for better approach.
Your conditions when you got client and search are not correctly grouped
Contact::when($request->client && $request->search, function ($q) use($request) {
$q->whereHas('companies', function ($q) use ($request) {
$q->where('is_client', true);
})->where(function ($q) use ($request) {
$q->where('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%')
->orWhereHas('companies', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
})->when($request->client == null && $request->search, function ($q) use($request) {
$q->where('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%')
->orWhereHas('companies', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
})->when($request->client && $request->search == null, function ($q) use ($request) {
$q->whereHas('companies', function ($q) use ($request) {
$q->where('is_client', true);
});
})
->paginate(30)
the condition is_client must be separated from the condition of search
You should have noticed that you can easily shrink the code here
$contactQuery = Contact::query();
if ($request->client) {
$contactQuery->whereHas('companies', function ($q) {
$q->where('is_client', true);
});
}
if ($request->search) {
$contactQuery->where(function ($q) use ($request) {
$q->where('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%')
->orWhereHas('companies', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
$contacts = $contactQuery->paginate(30);
I'm building a small application in Laravel 5.5 where I'm querying something like this:
$models = Contact::where('first_name', 'LIKE', '%'.$request->search_input.'%')
->orWhere('last_name', 'LIKE', '%'. $request->search_input.'%')
->orWhereHas('company', function ($q) use($request) {
$q->where('name', 'LIKE', '%'.$request->search_input.'%');
})
->whereHas('company', function ($query) {
$query->where('type', '=', 'Research');
})
->orderBy('created_at', 'desc')
->take(50)
->get();
The idea behind is, I want to search the list of contact with first_name, last_name and their company name (which is a relational data) with the search_input and filter them with type = Research in the company list, I mean only those contact should appear which is having company type as research.
But currently I'm getting all the list of contacts without filtering it with type. Help me out with this. Thanks.
You need to use where closure:
Contact::where(function($q) use($request) {
$q->where('first_name', 'like', '%' . $request->search_input . '%')
->orWhere('last_name', 'like', '%' . $request->search_input . '%')
->orWhereHas('company', function ($q) use($request) {
$q->where('name', 'like', '%' . $request->search_input . '%');
});
})
->whereHas('company', function ($query) {
$query->where('type', 'Research');
})
->latest()
->take(50)
->get();