This search works for me only when I fill all the fields correctly. My wish is that when I fill only one field, I will exclude results only relevant to this field.
Example if I fill only 'mark' field with 'Audi' got my mark name. My function is currently returning the results only if all fields are filled. If I fill one field, it returns an empty array. Also, I'm not sure if this function is well written, I followed the tutorial. Look code:
public function searchFilterCar(Request $request, Car $car){
if($request->has('car_type')){
if($request->has('mark')){
if($request->has('model')){
if($request->has('fuel')){
if($request->has('circuit')){
return $car->where('car_type', $request->input('car_type'))
->where('mark', $request->input('mark'))
->where('model', $request->input('model'))
->where('fuel', $request->input('fuel'))
->where('circuit', $request->input('circuit'))
->get();
}
}
}
}
}
}
Separate the conditions into several if statements, the where works on the existing results so you will be continuing from previous where. Its should something like this:
if($request->has('car_type')){
$car = $car->where('car_type', $request->input('car_type'));
}
if($request->has('mark')){
$car = $car->where('mark', $request->input('mark'));
}
....
return $car->get();
It might look a bit crude but it decreases the size of the code block and it works
Another way similar to Khaldoun Nd's answer would be to use query conditionals. It allows you to remove the subsequent if statements.
The code would become something like that:
return $car
->when($request->car_type, function ($query, $type) {
return $query->where('car_type', $type);
})
->when($request->mark, function ($query, $mark) {
return $query->where('mark', $mark);
})
// Chain the other conditions like the previous ones...
->get();
For reference: https://laravel.com/docs/5.8/queries#conditional-clauses
Related
Can someone help me out, I'm trying to do a where query on a Child Model. Everything seems fine when I have a value for the id but it returns nothing when no id is supplied.
My goal is to get all data when no id is supplied and get specific data when id supplied.
Here's my code
Report::with(['project'])
->whereHas('project' function($q) use($programId){
if($programId){
$q->where('program_id', $programId);
}
})->get();
Is there a better way to achieve my goal? or I just lack something on the query? Thank you in advance.
You can use when method for this.
The when method only executes the given closure when the first argument is true. If the first argument is false, the closure will not be executed.
Report::with('project')
->when($programId, function ($query) use ($programId) {
$query->whereHas('project' function($q) use($programId){
$q->where('project.program_id', $programId);
});
})->get();
So I have a little complex answer for this type of questions where you can create a query and do every logic to it.
// Initialise the model
$query = new Report;
// Start building the query
$query->with('project');
// Check if project Id exists
if ($projectId) {
return $query->whereHas('project', function ($subQuery) use ($projectId) {
$subQuery->where('program_id', $programId);
})->get();
} else {
return $query->get();
}
I presently have 3 tables: Shows, Genres and Show_Genre (associates the two). I have a search form that submits a series of checkboxes with values into an array based on what genres they selected. Presently I want to associate the Shows table and the Genres table into a variable and run a query against it once for every genre checkbox selected. Then, once the selection is filtered, I can display the resulting Show objects that matched the users parameters.
My present setup is the following
public function searchShows(SearchRequest $request)
{
//$ShowsWithGenres give a collection inside a collection which I can't seem to even access its values without doing a bunch of ugly code using count() in a for loop
$ShowsWithGenres = Show::with('genres')->get();
$genres = $request->name;
if(isset($genres))
{
foreach($genres as $genre)
{
//iterate against the selection repeatedly reducing the number of results
}
}
}
Thanks.
You should use whereHas() and whereIn.
Perhaps something like this should do it:
$shows = Show::whereHas('genres', function($q) use($genre_ids)
{
$q->whereIn('id', $genre_ids);
})->get();
EDIT
Try this, however I'm unsure about the performance.
$query= Show::query();
foreach($genre_ids as $id){
$query->whereHas('genres', function($q) use($id)
{
$q->where('id', $id);
})
}
$shows = $query->get();
Using Eloquents whereHas() function you can query results based on the relation's data. http://laravel.com/docs/5.0/eloquent#querying-relations
public function searchShows(SearchRequest $request)
{
// Start a query (but don't execute it at this point as we may want to add more)
$query = Show::with('genres');
$genreNames = (array) $request->name;
// Check there are some genre names, if theres not any it'll cause an SQL syntax error
if (count($genreNames) > 0)
{
$query->whereHas('genres', function($subQuery) use ($genreNames)
{
$subQuery->whereIn('genre_name', $genreNames);
}
}
// Finally execute the query. $shows now contains only shows with the genres that the user has searched for, if they didn't search with any genres, then it contains all the results.
$shows = $query->get();
}
This is my code to filter values based on parameters. I want to move it into to a single line. Is there any option available in laravel4?
if($network) //when $network variable has a value.(i will have the same thing for orderby, customer, etc..)
{
return $deals=$mobiles->deals()->where('network','=',$network)->get();// ->orderby($orderby);
}
else
{
return $deals=$mobiles->deals()->get();
}
Go with a ternary:
return $network ? $mobiles->deals()->where('network','=',$network)->get() : $mobiles->deals()->get();
A more clean way than ternary suggested by #moonwave99 (in my opinion) is to add a scope to your model.
public function scopeNetwork($query, $network = null) {
if (null !== $network)
$query->where('network', $network);
return $query;
}
You can then use
return $mobiles->deals()->network($network)->get();
This is an incredibly round-about way of doing this... Id recommend #moonwave99's solution, but you can pass a closure to where(). That, mixed with a boolean, and whereNotNull() can do it. Technically, it's one line of code, but I've broken it apart for the sake of readability.
Easy way:
return $network ? $mobiles->deals->where('network',$network)->get() : $mobiles->deals->get();
Overly complicated way:
return $mobiles->deals->where(isset($network) ? function($query) use ($network){
$query->where('network', $network);
} : function($query){
$query->whereNotNull('id');
})->get();
Im wondering why nobody suggested to use LIKE instead of =. I did like this, and works very well.:) I can have very dynamic filtering with many fields. Make sure the variable in where is set to null when you want to return all element.
My code become
$sorttype=$orderby[0]=='-'?"desc":"asc"; //To get based on assenting or dissenting order
$orderby=$orderby[0]=='-'?substr($orderby, 1):$orderby; //just removing the first element if - existing, because that is just a flag.
if(!$network){$network=null;} //set to null
if(!$orderby){$orderby='id';} //set to id when there no order by
return $deals=$mobiles->deals()
->where('network','LIKE',$network)
->orderby($orderby,$sorttype)
->get();
I have a search query that needs to be done. However, a search doesn't always have all values set, like in this case.
$aEvents = DB::table('events')
->where('client_id', '=', $client_id);
The question is, how can I make this where statement depend on the value of $client_id. So if the value is empty I don't want the Where statement to occur.
Also, I do not want to write several complete queries with if statements in PHP. To many variables. Ideally I'd like something like this:
$aEvents = DB::table('events')
->(($client_id != "") ? where('client_id', '=', $client_id) : "");
Using eloquent is (really!) nice and save, but I'm not yet up to speed with if statements in std Class objects I guess. Any help is appreciated.
You may try something like this:
$query = DB::table('events');
if(!empty($client_id)) {
$query->where('client_id', $client_id);
}
$aEvents = $query->get(); // Call this at last to get the result
If you are passing client_id to the server via a form/query string(user input) then you may try something like this:
if($client_id = Input::get('client_id')) {
$query->where('client_id', $client_id);
}
Update: For pagination try this:
$aEvents = $query->paginate(10); // For 10 per page
So you may call links() method in your view if you pass it like this:
return View::make('viewName')->with('aEvents', $aEvents);
In the view for pagination links:
$aEvents->links()
You can also use query scopes in the model for this purpose. Scopes allow you to easily re-use query logic in your models. In the model Event, you can add the following query scope:
public function scopeClientID($query, $client_id)
{
if ($client_id != '') {
return $query->where('client_id', '=', $client_id);
} else {
return $query;
}
}
Then from your controller or wherever you're calling it from, you can do the following:
$aEvents = Event::clientID($client_id);
If you want to get all the results, then you can do:
$aEvents = Event::clientID($client_id)->get();
Or if you want pagination, you can do:
$aEvents = Event::clientID($client_id)->paginate();
You can also chain it with other methods like you'd do in a eloquent query.
You can read more about model query scopes at http://laravel.com/docs/eloquent#query-scopes
I am trying to get a column of the last data in the database but so far, I am getting all the data in the database in an array.
This is my code;
public function NewID(){
$adminid=Auth::user()->admin_id;//cooperative ID
$newid = Member::select('member_id')->where('admin_id', '=',$adminid)->get();
return View::make('admin.member.addmember')
->with('NewID', $newid);
}
I have updated the code to be this base on suggestions;
public function NewID(){
$adminid=Auth::user()->admin_id;//cooperative ID
$newid = Member::select('member_id')->where('admin_id', '=',$adminid)->orderBy('id', 'desc')->first();
return View::make('admin.member.addmember')
->with('NewID', $newid);
}
and I am using a For Loop to display data on the view
#foreach ($NewID as $NewIDs)
{{$NewIDs->member_id}}
#endforeach
My error is now ErrorException:Trying to get property of non-object
Answer
I finally got it to work
I used this instead
public function NewID(){
$adminid=Auth::user()->admin_id;//cooperative ID
$newid = Member::select('member_id')->where('admin_id', '=',$adminid)->orderBy('id', 'desc')->take(1)->get();
return View::make('admin.member.addmember')
->with('NewID', $newid);
}
I finally got it to work
I used this instead
public function NewID(){
$adminid=Auth::user()->admin_id;// ID
$newid = Member::select('member_id')->where('admin_id', '=',$adminid)->orderBy('id', 'desc')->take(1)->get();
return View::make('admin.member.addmember')
->with('NewID', $newid);
}
Well, a lot of things could be wrong, so what you should do is find the cause. In you view file, temporarily remove the foreach loop and replace it with {{ dd($NewID) }}. This will 'dump and die' the value of $NewID.
Additionally, I suggest you stick to variable naming conventions. Variables should start lowercase. Also it is confusing to call a collection of Members NewID and a single instance of a member NewIDs. Sticking to the convention helps you and others to read and debug your code.