Update url parameters on form submit based on selections - php

I want to update the url with the selected options in the form and send it to session but i keep receiving : (Undefined variable: country).
How can fix this please ? and i am very beginner so excuse my dumb mistakes .
My route :
Route::post('/{country}/{region}/{city}', [
'as' => 'locationFinder',
'uses' => 'User\UserLocationsController#store']);
My controller :
class UserLocationsController extends Controller
{
public function store(Request $request, Country $country, Region $region, City $city)
{
session()->put($country->name, $region->name, $city->name);
return redirect()->route('welcome.index', [$country, $region,
$city]);
}
}
My view :
<form action="{{ route('locationFinder',[$country, $region, $city]) }}" method="POST">
<div class="form-group">
<select class="form-control" name="country_id" id="country_id">
<option value="0" disable="true" selected="true"> Select Country </option>
#foreach ($countries as $key => $value)
<option value="{{$value->id}}">{{ $value->name }}</option>
#endforeach
</select>
</div>
<div class="form-group">
<select class="form-control" name="region_id" id="region_id">
<option value="0" disable="true" selected="true"> Select Region </option>
</select>
</div>
<div class="form-group">
<select class="form-control" name="districts" id="districts">
<option value="0" disable="true" selected="true"> Select City </option>
</select>
</div>
<div class="form-group">
<button class="btn btn-primary">submit</button>
</div>
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
My CountryController :
class CountryController extends Controller
{
public function countries(){
$countries = Country::all();
return view('welcome', compact('countries'));
}
public function regions(){
$countries_id = Input::get('country_id');
$regencies = Region::where('country_id', '=', $countries_id)->get();
return response()->json($regencies);
}
public function cities(){
$regions_id = Input::get('region_id');
$districts = City::where('region_id', '=', $regions_id)->get();
return response()->json($districts);
}
}

in the controller you pass "$country"... but in your view you are using "$countries" in the foreach
controller:
..
return redirect()->route('welcome.index', [$country, $region,
$city]);
..
view:
#foreach ($countries as $key => $value)
<option value="{{$value->id}}">{{ $value->name }}</option>
#endforeach

Related

laravel passing parameters to route in view blade

So I'm very new to laravel and I have a filter in my website blade as follows:
goal: the user chooses a city and price from and price to and then clicks search and villas with what selected must be shown on another view! all values from the database!
I've tried to do this:
the route:
Route::get('/searched/{city_id}/{pricefrom}/{priceto}', [WebsiteController::class, 'search'])->name('search.clicked');
the controller:
public function index() {
$cities = DB::table('cities')
->select('*')->distinct()->get();
$users = Villa::with('City','Seller', 'Payment')->get();
$pricefrom = DB::table('villas')
->select('price')
->where('price', '<=', 50000)->distinct()->get();
$priceto = DB::table('villas')
->select('price')
->where('price', '>', 50000)->distinct()->get();
return view('website', compact('users','cities','pricefrom','priceto'));
}
public function search($city_id, $pricefrom, $priceto) {
$city = City::find($city_id);
$price = Villa::find($price);
$citydata = Villa::with('City','Seller', 'Payment')->where('city_id', $city_id)->get();
$lowdata = Villa::with('City','Seller', 'Payment')->where('price', $pricefrom)->get();
$highdata = Villa::with('City','Seller', 'Payment')->where('price', $priceto)->get();
$info = Villa::with('City','Seller', 'Payment')->get();
return view ('searched',compact('citydata','lowdata','highdata','info'))->with('city', $city )->with('price', $price);
}
the website view blade: here I didn't know how exactly I should pass the parameters for the route so I get an error
#foreach ($users as $villa)
<form action="{{ route('search.clicked', $villa->city_id,$villa->pricefrom,$villa->priceto) }}" method="get">
#csrf
<select name="city" class="form-select">
<option value="" id="searchoption"> City </option>
#foreach ($cities as $city)
<option >{{ $city->name }}</option>
#endforeach
</select>
<div class="col-lg-3 p-2">
<select name="pricefrom" class="form-select">
<option value="" id="searchoption"> Price From </option>
#foreach ($pricefrom as $low)
<option >{{ $low->price}}</option>
#endforeach
</select>
</div>
<div class="col-lg-3 p-2">
<select name="priceto" class="form-select">
<option value="" id="searchoption"> Price To </option>
#foreach ($priceto as $high)
<option >{{ $high->price}}</option>
#endforeach
</select>
</div>
<div class="col-lg-3 p-2">
<button type="button" class="btn btn-outline-success">search</button>
</div>
</form>
#endforeach
also Villa model
class Villa extends Model {
use HasFactory;
protected $fillable=[
"id", "title", "description", "price", "state", "status", "city_id", "seller_id", "payment_id",
"created_at", "updated_at"
];
public function City()
{
return $this -> hasOne(City::class,'id','city_id');
}
public function Seller()
{
return $this -> hasOne(Seller::class,'id','seller_id');
}
public function Payment()
{
return $this -> hasOne(Payment::class,'id','payment_id');
}
}
I think I have many errors I should fix And I want some help with my search bar!
I get this error:
Missing required parameters for [Route: search.clicked] [URI: searched/{city_id}/{pricefrom}/{priceto}] [Missing parameters: pricefrom, priceto].
try:
<form action="{{ route('search.clicked', [$villa->city_id,$villa->pricefrom,$villa->priceto]) }}" method="get">
According to route function second parameter should be string or array. String or Array if you're passing only 1 & array if you are passing 2 or more.
function route($name, $parameters = [], $absolute = true)
BLADE FILE:
#foreach ($users as $villa)
<form action="{{ route('search.clicked', $villa->city_id,$villa->pricefrom,$villa->priceto) }}" method="get">
#csrf
<select name="city" class="form-select">
<option value="" id="searchoption"> City </option>
#foreach ($cities as $city)
<option >{{ $city->name }}</option>
#endforeach
</select>
<div class="col-lg-3 p-2">
<select name="pricefrom" class="form-select">
<option value="" id="searchoption"> Price From </option>
#foreach ($pricefrom as $low)
<option >{{ $low->price}}</option>
#endforeach
</select>
</div>
<div class="col-lg-3 p-2">
<select name="priceto" class="form-select">
<option value="" id="searchoption"> Price To </option>
#foreach ($priceto as $high)
<option >{{ $high->price}}</option>
#endforeach
</select>
</div>
<div class="col-lg-3 p-2">
<button type="button" class="btn btn-outline-success">search</button>
</div>
</form>
#endforeach
to
#foreach ($users as $villa)
<form action="{{ route('search.clicked', ['city_id' => $villa->city_id, 'pricfrom' => $villa->pricefrom, 'priceto' =>$villa->priceto]) }}" method="get">
#csrf
<select name="city" class="form-select">
<option value="" id="searchoption"> City </option>
#foreach ($villa->cities as $city)
<option >{{ $city->name }}</option>
#endforeach
</select>
<div class="col-lg-3 p-2">
<select name="pricefrom" class="form-select">
<option value="" id="searchoption"> Price From </option>
#foreach ($villa->pricefrom as $low)
<option >{{ $low->price}}</option>
#endforeach
</select>
</div>
<div class="col-lg-3 p-2">
<select name="priceto" class="form-select">
<option value="" id="searchoption"> Price To </option>
#foreach ($villa->priceto as $high)
<option >{{ $high->price}}</option>
#endforeach
</select>
</div>
<div class="col-lg-3 p-2">
<button type="button" class="btn btn-outline-success">search</button>
</div>
</form>
#endforeach
You need add to route :
<form action="{{ route('search.clicked',$object->first()->city_id,$model->first()->pricefrom,$model->first()->priceto) }}" method="get">

Livewire Laravel add dynamic select, how do I resolve the loss of data? Please

when add next select, you lose the data of the first select of the municipalities.
Livewire controller SelectUsuario.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use Illuminate\Support\Facades\Http;
class SelectUsuario extends Component
{
public $estados;
public $estado;
public $estadoSigla;
public $municipios;
public $selects = [];
public $i = 0;
public function add($i)
{
$i = $i + 1;
$this->i = $i;
array_push($this->selects, $i);
}
public function remove($i)
{
unset($this->selects[$i]);
}
public function mount()
{
$this->estados = Http::get(
url("https://servicodados.ibge.gov.br/api/v1/localidades/estados"),
['orderBy' => 'nome']
)->json();
}
public function updatedEstadoSigla()
{
$this->getMunicipios();
}
public function getMunicipios()
{
if ($this->estadoSigla != '') {
foreach ($this->estadoSigla as $estado) {
$this->municipios = json_decode(
Http::get(
url("https://servicodados.ibge.gov.br/api/v1/localidades/estados/{$estado}/municipios")
)->body(),
true
);
}
}
}
public function render()
{
return view('livewire.select-usuario');
}
}
Livewire component select-usuario.blade.php
<div class="form-group row">
<div class="col-3"><label>Viagem</label></div>
<div class="col-3"><label>Seção</label></div>
<div class="col-4"><label>Funcionário</label></div>
<div class="col-2"><label>Ação</label></div>
<div class="col-3">
<select class="form-control" data-item_id="0">
<option value="R">Responsável</option>
</select>
</div>
<div class="col-3">
<select wire:model="estadoSigla.0" class="form-control" id="estado.0" name="estado.0">
<option value="">selecione estado...</option>
#foreach ($this->estados as $estado)
<option value="{{ $estado['sigla'] }}">{{ $estado['nome'] }}</option>
#endforeach
</select>
</div>
<div class="col-4">
#if ($this->estadoSigla)
<select class="form-control" name="municipio.0" id="municipio.0">
<option value="" selected>selecione município...</option>
#foreach ($this->municipios as $municipio)
<option value="{{ $municipio['id'] }}">{{ $municipio['nome'] }}</option>
#endforeach
</select>
#endif
</div>
<div class="col-2">
<button class="btn btn-info mb-2" wire:click.prevent="add({{ $i }})">adicionar</button>
</div>
{{-- Add Form --}}
#foreach ($selects as $key => $value)
<div class="col-3">
<select name="item_name[]" class="form-control" data-item_id="{{$value}}">
<option value="I">Ida</option>
<option value="V">Volta</option>
<option value="O">Ida e Volta</option>
<option value="R">Responsável</option>
</select>
</div>
<div class="col-3">
<select wire:model="estadoSigla.{{ $value }}" class="form-control" name="estado.{{ $value }}" id="estado.{{ $value }}">
<option value="">selecione estado...</option>
#foreach ($this->estados as $estado)
<option value="{{ $estado['sigla'] }}">{{ $estado['nome'] }}</option>
#endforeach
</select>
</div>
<div class="col-4">
#if ($estadoSigla)
<select class="form-control" name="municipio.{{ $value }}" id="municipio.{{ $value }}">
<option value="" selected>selecione município...</option>
#foreach ($this->municipios as $municipio)
<option value="{{ $municipio['id'] }}">{{ $municipio['nome'] }}</option>
#endforeach
</select>
#endif
</div>
<div class="col-2">
<button class="btn btn-dark mb-2" wire:click.prevent="remove({{ $key }})">remover</button>
</div>
#endforeach
</div>
try adding wire:key directive to the looped select elements while livewire need to keep tracking all the values of them.
<select wire:model="estadoSigla.{{ $value }}" class="form-control" id="estado.{{ $value }}" wire:key="estado-select-{{ $key }}"> // or $value, the unique identifier for its
also, try adding wire:ignore.self to the root div of the select elements

How can I get results of one search query filter only in Laravel

I am creating a real estate project, which will have a search option for different pages with different search filters.
Here is one example of the search view
<form class="form-row basic-select-wrapper" method="POST" action="{{route('filter')}}">
#csrf
{{-- <div class="form-group">
<input type="text" name="prop_name">
</div> --}}
<div class="form-group col-lg col-md-6">
<label>Property type</label>
<select name="type_id" class="form-control basic-select">
<option>Select Type</option>
#foreach ($types as $type)
#if ($type->status == 1)
<option value="{{ $type->id }}">{{ $type->name }}</option>
#endif
#endforeach
</select>
</div>
<div class="form-group col-lg col-md-6">
<label>Property Category</label>
<select name="cat_id" class="form-control basic-select">
<option>Select Category</option>
#foreach ($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
</select>
</div>
<div class="form-group col-lg col-md-6">
<label>Location</label>
<select name="loc_id" class="form-control basic-select">
<option>Select Location</option>
#foreach ($locations as $location)
<option value="{{ $location->id }}">{{ $location->loc_name }}</option>
#endforeach
</select>
</div>
<div class="form-group col-lg col-md-6">
<label>Budget</label>
<select name="start_price" class="form-control basic-select">
<option>Select Budget</option>
#foreach($price['price'] as $key => $val)
<option value="{{$key}}">{{$val}}</option>
#endforeach
</select>
</div>
<div class="form-group col-lg col-md-6">
<label>Bedroom(s)</label>
<select name="min_bed" class="form-control basic-select">
<option>Select Bedroom</option>
<option value="0">studio</option>
<option value="1">one bedroom</option>
<option value="2">two bedroom</option>
<option value="3">three bedroom</option>
<option value="4">four bedroom</option>
<option value="5">five bedroom</option>
<option value="6">six bedroom</option>
<option value="7">seven bedroom</option>
</select>
</div>
<div class="advanced-search" id="advanced-search">
<div class="card card-body">
<div class="form-group col-md-12">
<div class="mt-0">
<button class="btn btn-primary align-items-center" type="submit"><i
class="fas fa-search mr-1"></i><span>Search</span></button>
</div>
</div>
</div>
</div>
</form>
Here is my search controller
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
//use App\Models\Listing;
use App\ListingSearch\ListingSearch;
class SearchController extends Controller
{
public function filter(Request $request)
{
return ListingSearch::apply($request);
}
}
Now, to implement this since there are multiple search filters and I wanted to simplify it. Here is the folder structure
folder structure
Here is the Listitng Search Class
<?php
namespace App\ListingSearch;
use Illuminate\Database\Eloquent\Builder;
use App\Models\Listing;
use Illuminate\Http\Request;
class ListingSearch
{
public static function apply(Request $filters)
{
$query = static::applyDecoratorsFromRequest(
$filters, (new Listing)->newQuery()
);
// Get the results and return them.
return static::getResults($query);
}
private static function applyDecoratorsFromRequest(Request $request, Builder $query)
{
foreach ($request->all() as $filterName => $value) {
$decorator = static::createFilterDecorator($filterName);
if (static::isValidDecorator($decorator)) {
$query = $decorator::apply($query, $value);
}
}
return $query;
}
private static function createFilterDecorator($name)
{
return __NAMESPACE__ . '\\Filters\\' .
str_replace(' ', '',
ucwords(str_replace('_', ' ', $name)));
}
private static function isValidDecorator($decorator)
{
return class_exists($decorator);
}
private static function getResults(Builder $query)
{
return $query->get();
}
}
here is an example of one of the filters CATID for category
<?php
namespace App\ListingSearch\Filters;
use Illuminate\Database\Eloquent\Builder;
class CatId implements Filter
{
public static function apply($builder, $value)
{
return $builder->where('cat_id', $value);
}
}
The problem with this is that I have to enter all the required filters to get a result, otherwise if I only fill one filter I get null results, for example I want only apartments, without entering location or category. How can I achieve this?
search query
Did you try to filter the $value before stacking them in your where?
if (!empty($value)) {
}
empty() will take care of filtering out the empty and null values. So you end up adding to your query filter values that actually exists.
EDIT
foreach ($request->all() as $filterName => $value) {
if (!empty($value)) {
$decorator = static::createFilterDecorator($filterName);
if (static::isValidDecorator($decorator)) {
$query = $decorator::apply($query, $value);
}
}
}
EDIT 2
Your option tag has no value attribute defined and there for is not empty when posted to your controller because the browser defaults to the value inside the tag (Select Type, Select Category ect). You need to provide the value attribute as empty so that the POST does not use the inner text like this:
<option value="">Select Type</option>
[...]
<option value="">Select Category</option>
[...]
<option value="">Select Location</option>
[...]
<option value="">Select Budget</option>
Then if (!empty($value)) {} can do it's thing

Adding data with multiple tables in one form many to many relationship in laravel 5.4

I am trying to insert with two tables with many to many relationship: Assignments and Collectors. I also make a intermediate or pivot table between them named assignment_collector.
create.blade.php in assignment folder
<form method="POST" action="{{ route('assignments.store') }}">
{{ csrf_field() }}
<div class="form-group">
<label for="area_id">Area: </label>
<select class="form-control" name="area_id">
#foreach ($areas as $area)
<option value= "{{ $area->id }}">
{{ $area->campus }} {{ $area->building }} {{ $area->floor }}
</option>
#endforeach
</select>
</div>
<div class="form-group">
<label for="mts_id">MTS: </label>
<select class="form-control" name="mts_id">
#foreach ($mts as $mt)
<option value= "{{ $mt->id }}">
{{ $mt->location }}
</option>
#endforeach
</select>
</div>
<div class="form-group">
<input type="hidden" class="form-control" id="status" name= "status" value="Active">
</div>
<div class="form-group">
<label for="collector_id">Collector: </label>
<select class="form-control" name="collector_id">
#foreach ($assignments as $assignment)
#foreach($assignment->collectors as $collector)
<option value= "{{ $collector->id }}">
{{ $collector->firstname }} {{ $collector->lastname }}
</option>
#endforeach
#endforeach
</select>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Add</button>
</div>
</form>
AssignmentsController
public function store(Request $request)
{
$this->validate($request, [
'area_id' => 'required',
'mts_id' => 'required',
'status' => 'required',
'collector_id' => 'required'
]);
$assignment = new Assignment();
$assignment->area_id = $request->area_id;
$assignment->mts_id = $request->mts_id;
$assignment->status = $request->status;
$assignment->save();
$assignment_collector = new AssignmentCollector();
$assignment_collector->collector_id = $request->collector_id;
$assignment_collector->assignment_id = $assignment->id;
$assignment_collector->save();
return redirect('/assignments');
}
Assignment Model
public function collectors()
{
return $this->belongsToMany(Collector::class);
}
Collector Model
public function assignments()
{
return $this->belongsToMany(Assignment::class);
}
I got an error on this: App\AssignmentCollector since there is no AssignmentCollector and as I read the tutorials, you don't need to make a model for the pivot table. I reading the other articles but I get even more confused. Please help me because I'm still new in Laravel and I have get confused. Thanks!
You don't need a Model for your assignment collector table. What you want to do is create the Assignment then assign
$assignment->collectors()->create([
// all the collector data
]);

Editing drop-down doesn't fetch value

I have created a drop-down for categories and subcategory. It works fine when i submit the form, but when I edit the form, category field does not come with refilled data from the database, category drop-down come like it show in create form.
here is my edit:
<div class="form-group">
{!! Form::label('category','Category:') !!}
<select name="category" id="category" class="form-control input-sm">
#foreach($s as $k)
<option value="{{ $k['id'] }}">{{ $k['name'] }}</option>
#endforeach
</select>
</div>
<div class="form-group">
{!! Form::label('subcategory','Subcategory:') !!}
<select name="subcategory" id="subcategory" class="form-control input-sm">
<option value=""></option>
</select>
</div>
Controller:
public function edit($id)
{
// get the event
$event = Event::findOrFail($id);
$s = Category::all()->where('parent_id','=','0');
$r = Event::all();
$daysOfWeek = unserialize(Event::find($id)->days_of_week);
// show the edit form and pass the event
return view('event.edit',compact('event','s','r','daysOfWeek'));}
I haven't used relations for the dropdown, I have used jquery and ajax to select subcategory after I select category.
What can i do to get the value stored in database when I do edit form?
I got my answer thanks every one for help!
View:
<div class="form-group">
{!! Form::label('category','Category:') !!}
<select name="category" id="category" class="form-control input-sm">
#foreach($s as $k)
#if($k['id'] == $m)
<option value="{{ $k['id'] }}" selected="{{$m}}">{{ $k['name'] }}</option>
#else
<option value="{{ $k['id'] }}">{{ $k['name'] }}</option>
#endif
#endforeach
</select>
</div>
<div class="form-group">
{!! Form::label('subcategory','Subcategory:') !!}
<select name="subcategory" id="subcategory" class="form-control input-sm">
#foreach($subcat as $k)
#if($k['name'] == $subid)
<option value="{{ $k['id'] }}" selected="{{$subid}}">{{ $k['name'] }}</option>
#else
<option value="{{ $k['id'] }}">{{ $k['name'] }}</option>
#endif
#endforeach
<option value=""></option>
</select>
</div>
Controller:
public function edit($id)
{
$event = Event::findOrFail($id);
$s = Category::where('parent_id','=','0')->get();
$r = Event::all();
$m = Event::find($id)->category;
$subid = Event::find($id)->subcategory;
$subcat = Category::where('parent_id','=',$m)->get();
$daysOfWeek = unserialize(Event::find($id)->days_of_week);
return view('event.edit',compact('event','s','subcat','subid','r','daysOfWeek','m'));
}
There is a mistake in your Controller method edit()
Your code:
$s = Category::all()->where('parent_id','=','0'); // wrong
Isn't that supposed to be:
$s = Category::where('parent_id','=','0')->get(); // correct
You are already fetching the categories with all, and then passing the where condition, hence it is not showing you the results. where condition returns the instance of Illuminate\Database\Eloquent\Builder and not the desired results.
Update the wrong line with the correct one and the result should appear as you want.

Categories