Dear I am stuck in the realization of a search engine please I would appreciate any kind of guidance.
In the view I have two inputs. One is a select that the user must choose the type of property: Rent - Sale - Temporary - Commercial
In the other input you must write the location.
SEARCH VIEW
{{ Form::open(['route' => 'busquedas', 'method' => 'get', 'class' => 'form-inline'])}}
<select id="categoria" name="categoria" class="form-control">
{{-- <option value="" disabled>Seleccionar</option> --}}
@foreach($categorias as $index => $categoria)
<option value="{{ $categoria->nombre_categoria }}">
{{ $categoria->nombre_categoria }}
</option>
@endforeach
</select>
<div class="form-group">
{{ Form::text('ubicacion', null, ['class' => 'form-control', 'placeholder' => '¿Que ubicación está buscando? ']) }}
</div>
<div class="form-group">
<button type="submit" class="btn btn-default question-btn">
<span class="fa fa-search">Buscar</span>
</button>
</div>
{{ Form::close() }}
In the controller I want to filter in the Category.php model based on the user's selection Rent - Sale - Temporary - Commercial and I also have to search in two tables for the written location.
In two tables because on the one hand there is a location and on the other, which in turn are related.
Model Property:
public function category(){
return $this->belongsTo(Category::class);
}
public function ubicacion(){
return $this->belongsTo(Ubicacion::class);
}
Model Category:
public function properties(){
return $this->hasMany(Property::class);
}
Model Location:
public function properties(){
return $this->hasMany(Property::class);
}
public function area(){
//hasOne: una ubicacion tiene un area
return $this->hasOne(Area::class);
}
public function scopeUbicacion($query, $ubicacion){
if($ubicacion)
return $query->where('ubicacion', 'LIKE', "%$ubicacion%");
}
Model Area:
public function properties(){
return $this->hasMany(Property::class);
}
public function scopeArea($query, $area){
if($area)
return $query->where('name', 'LIKE', "%$area%");
}
In the controller I have so far the following:
$categoria = $request->get('categoria');
$ubicacion = $request->get('ubicacion');
$categoria_id = Category::where('nombre_categoria', $categoria)->pluck('id');
$propiedadesObtenidas = Property::with(['category', 'ubicacion'])
->when($categoria_id, function ($query) use ($categoria_id) {
$query->where('category_id', $categoria_id);
})
->when($ubicacion, function ($query) use ($ubicacion) {
$query->whereHas('ubicacion', function ($q) use ($ubicacion) {
$q->ubicacion($ubicacion);
});
})
->get();
dd($propiedadesObtenidas);
I don't finish finding a solution to join the searches.
Please any suggestion will be welcome. Thank you very much!
Assuming everything else is working as you want, I reply to
when()
In this case, I would use the Query Builder clause :conditional clauses
Sometimes you may want clauses to apply to a query only when something else is true. For example, you may only want to apply a statement
where
if a given input value is present in the incoming request. You can achieve this using the methodwhen
:The method
when
only executes the given closure function when the first parameter ($categoria_id
) is true (works like an if).
If the first parameter is false, the closure will not execute.So, in your query on the model
Property
, you can put awhen
for each filter, which will be executed conditionally if the value of the filter returns true (note that itnull
will return false, so if the user didn't fill in theinput
for that filter, you don't search for that value).For the location you will see that I used whereHas, here the explanation:
Check relationship existence
When accessing records from a model, you may want to limit your results based on the existence of a relationship, for that matter you can pass the name of the relationship to the method
has
, or you can use the methodwhereHas
to put conditions"where"
on your queries ofhas
. This method allows you to add custom constraints to a relationship constraint.EDIT: If the category is going to be always present, the conditional is not needed, you can directly put the
where
. For the other two you would have to leave the conditional and group the parameters (such as putting parentheses) and an OR so that it returns data if one or the other matches. Something like that:EDIT2
Or this other one, that if the filter has
$ubicacion
and$area
, it looks for a Property that meets the two conditions. If the filter does not have both ($ubicacion
and$area
), search for the one that has ($ubicacion
or$area
), and if it does not have any, return all of the$categoria
.EDIT3
Some remarks about Models, relationships and the database:
Model Property :
Model Category :
Model Location :
Area Model :