Invalid parameter number error when using whereIn with livewire - laravel

I am trying to create a multiple select filter. When I use whereIn for the id I get this error
Invalid parameter number (SQL: select * from stations where id in (16128))
With 16128 being one of the two id's selected for that query. It works fine with a manual given array so I am not sure what the problem is. I also tried with array_values but I get the same result.
<label for="" class="col-md-3">Daypart</label>
<div class="container-checkbox">
#foreach($dayparts as $id => $daypart)
<div wire:key="{{ $daypart->id }}">
<input type="checkbox" id="{{ $daypart->daypart_name }}" name="{{ $daypart->daypart_name }}" wire:model="filters.dayparts.{{ $daypart->id }}" wire:click="filtru({{ $daypart->id }})" />
</div>
#endforeach
</div>
public function filtru($id){
$this->filters['dayparts'] = array_filter($this->filters['dayparts']);
$dayp = DaypartStation::whereIn('daypart_id', array_keys($this->filters['dayparts']))->get();
foreach($dayp as $day){
$this->arr[]=$day->station_id;
}
$toate = Station::whereIn('id', [$this->arr])->get();
//dd(Station::whereIn('id', $this->arr)->get());
//dd(Station::whereIn('id', [array_values($this->arr)])->get());
// dd(Station::whereIn('id', [16576, 16776, 16376])->get());
}
public function render()
{
return view('livewire.create-workbooks-table', [
'stations'=> Station::
when($this->filters['dayparts'], function($query){
$query->whereIn('id', [$this->arr]);
})
->search($this->search)
->orderBy($this->sortBy, $this->sortDirection)
->latest()
->Paginate($this->perPage),
]);
}

I believe you should change
$toate = Station::whereIn('id', [$this->arr])->get();
to
$toate = Station::whereIn('id', $this->arr)->get();
since $this->arr is already an array

Related

get many to many values and which of them are selected in laravel

Contacts:
id
name
Tags:
id
name
ContactTags:
contact_id
tag_id
In Contacts model:
public function tags()
{
return $this->belongsToMany(Tags::class, "contacts_tags", "contact_id", "tag_id");
}
So if I do
$contact = Contacts::findOrFail($id);
dd($contact->tags);
I successfully get the tags associated with the contact. But how can I get all tags and a flag indicating which one of those is associated?
I'm trying to prevent fetching all tags, loop them and with each iteration loop all contact_tags and check if tag_id matches. I want to display a list of checkboxes with all tags and check the ones that are in the relation.
This code can help you, but I'm using the SELECT multiple component. You can easily adapt it to use the CHECKBOX component.
Contacts model:
public function tags()
{
return $this->belongsToMany(Tags::class, "contacts_tags", "contact_id", "tag_id");
}
ContactController.php
public function edit(Contact $contact)
{
$tags = Tag::all();
return view('contacts.edit',compact('contact', 'tags'));
}
edit.blade.php
<div class="row">
<div class="col">
<div class="form-group">
<strong>Tags:</strong>
<select name="tags_id[]" multiple>
#foreach ($tags as $tag)
#if( $contact->tags->contains($tag) )
<option value="{{ $tag->id }}" selected>{{ $tag->name }}</option>
#else
<option value="{{ $tag->id }}">{{ $tag->name }}</option>
#endif
#endforeach
</select>
</div>
</div>
</div>
Update in ContactController.php
public function update(Request $request, Post $contact)
{
$validatedData = $request->validate([
'tags_id' => ['array'],
]);
$contact->update($request->all());
$contact->tags()->sync($validatedData['tags_id']);
return redirect()->route('contact.index')->with('success', 'Contact successfully updated!');
}
The validation is just an example. The $validatedData has no use here, but it can be used to update the contact if you validate the other fields.

Laravel checkbox problem which I cannot update the pivot table

I'm working on a laravel application. In laravel I'm trying to update a row from a pivot table. In this application I have three tables:
issues: id, title, description
categories: id, name
category_issues:(pivot table) id, issue_id, category_id
In laravel I'm trying to update a row from a pivot table. I have this relationships:
Issue.php
public function categories() {
return $this->belongsToMany('App\Category', 'category_issues');
}
Category.php
public function issues() {
return $this->belongsToMany('App\Issue', 'category_issues');
}
A issue can have many categories.
Html code for displaying category section:
<div class="form-group row">
<label for="category" class="col-md-4 col-form-label text-md-right">{{ __('Category :') }}</label>
<div class="form-check col-md-6">
#foreach ($categories as $category)
<input type="checkbox" name="category[]" id="{{ $category->id }}" value="{{ $category->id }}"
{{ in_array($category->id, $issue->categories->pluck('id')->toArray()) ? 'checked' : '' }}>
<label for="{{ $category->id }}"> {{ $category->name }} </label>
#endforeach
</div>
</div>
Here is the update function file:
public function update(Issue $issue)
{
request()->validate([
'title'=> ['required', 'min:3'],
'description'=> ['required', 'min:3'],
'category' => ['required']
]);
$issue->title = request('title');
$issue->description = request('description');
$issue->save();
//Category_Issue Update
$categoryIssue = new CategoryIssue;
$cats = request('category');
foreach ($cats as $cat) {
$categoryIssue->updateOrCreate([
'issue_id'=> $issue->id,
'category_id' => $cat
]);
}
return redirect('issues')->with('success', 'Issue has been updated');
}
Instead of doing the creation / update on the CategoryIssue model (do you even have a CategoryIssue model?), Laravel makes this really easy to update the pivots of a relationship all at once, with the sync() method. You've set up the relationships correctly already per your code above.
In your update() method, you already have your Issue model, and have saved it. You have a set of categories coming in from the form via the $request object (or none if user didn't choose any), so you can then update the pivot like this:
$issue->categories()->sync($request->get('category', []));
Leaving a blank array as the second argument is optional. One small suggestion: maybe make the name of the field on the form 'categories' instead of 'category' just to keep it easy to remember it is an array coming in.

Getting only 1 radio button to be saved instead of 2

In my page I can have multiple addresses, but the user can only select one address.
The problem I'm having is that both my radio buttons are being saved instead of just one.
So if the user has 2 addresses then only one should have selected = 1 and the other address should be selected = 0, but at the moment both address = 1.
I haven't been able to only have 1 address selected and saved as such in the database. I know that I'm passing the ID of the selected radio button through, but I was hoping to have this happen.
E.G: When the user saves their first address that is then saved as their selected address (selected = 1) and any other addresses they add after that will be (selected = 0).
If they change their mind and want their second address to be the one they use then the select it and that will then become like this, address 1 (selected = 0) and address 2 will become (selected = 1).
I hope this made sense. If it didn't please let me know.
My form
#foreach($addresses as $address)
<div class="col-lg-4">
<form id="address-radio" action="{{ route('account.post.addresses.radio', $address->id) }}" method="post">
#csrf
<div class="form-check">
<input type="radio" class="form-check-input" name="address_option" id="address_{{ $address->id }}" {!! $address->selected == '1' ? 'checked' : '' !!}>
<label for="address_{{ $address->id }}" class="form-check->label">
#if(!empty($address->complex))
{{ $address->complex }} <br>
#endif
{{ $address->address }} <br>
{{ $address->suburb }} <br>
{{ $address->city }} <br>
{{ $address->province }} <br>
{{ $address->postal_code }} <br>
</label>
</div>
</form>
</div>
#endforeach
<script>
$(document).ready(function(){
$('input[type="radio"]').on('change', function(){
$(this).closest("form").submit();
})
})
</script>
and this is my function
public function postAddressesRadio(Request $request, $id)
{
$selected = Address::findOrFail($id);
$user_id = Auth::user()->id;
$not_selected = $selected->where('id', '!=', $id)
->where('user_id', $user_id)->get();
foreach($not_selected as $selected)
{
$selected->selected = "0";
}
if($request->address_option == 'on'){
$selected->selected = '1';
}
$selected->save();
return redirect()->back()->with('success', 'Address was updated');
}
So I've managed to do it. I'm not sure if there is a better way but this works.
In my function I did
public function postAddressesRadio(Request $request, $id)
{
$address = Address::findOrFail($id);
$user_id = Auth::user()->id;
$addresses = Address::where('user_id', $user_id)->get();
foreach($addresses as $address)
{
if($address->id == $id)
{
$address->selected = "1";
}else{
$address->selected = "0";
}
$address->save();
}

Laravel: needing help querying two tables into one result

Im interested in giving users the option to add articles to custom lists that they create. (like youtube's playlist feature).
I want to know how to show a 'checked' checkbox next to a list if the article already exists within it, so they don't add it twice.
My database tables:
list : | id | person_id | list_name | list_desc
list_ref : | id | list_id | article_id
My code for displaying lists.
$lists = Lists::where('person_id', Auth::user()->person_id)->get();
#foreach($lists as $list)
<input type="checkbox" id="available_list" value="{{ $list->id }}">
{{ $list->list_name }}
#endforeach
If anyone could help me understand the code to query the two tables to see if list already used || list is available.
You could use a raw expression in conjunction with a left join like this:
$lists = DB::table('list')->
leftJoin('list_ref', 'list_ref.list_id', '=', 'list.id')->
select(DB::raw('list.*, IF(list_ref.list_id = list.id, 1, 0) used'))->
where('person_id', Auth::user()->person_id)->
get();
The above uses a join to figure out which list rows has a corresponding key in the list_ref table. The result will contain a field called used that will tell if the entry has a reference in the list_ref table.
You should now be able to generate you form like this:
#foreach($lists as $list)
<input type="checkbox" id="available_list" value="{{ $list->id }}" {{ $list->used ? "CHECKED" : "" }}>
{{ $list->list_name }}
#endforeach
First crate class, here is example for facility
class HotelFacilities
{
public $facility_id;
public $facility;
public $status;
}
Get all data
$facilities = Facility::all();
Get user related data
$user_facilities = UserFacility::where('user_id', 3)->get();
//Here you add status
$array_hotel_facility = array();
for($i=0; $i<count($facilities); $i++)
{
$obj_hotel_facilities = new HotelFacilities;
$obj_hotel_facilities->facility_id = $facilities[$i]['id'];
$obj_hotel_facilities->facility = $facilities[$i]['facility'];
$obj_hotel_facilities->status = false;
for($j=0; $j<count($user_facilities); $j++)
{
if($user_facilities[$j]->facility_id == $facilities[$i]->id)
{
$obj_hotel_facilities->status = true;
}
}
//Pass this array to view
$array_hotel_facility[$i] = $obj_hotel_facilities;
}
//Pass to view
return view('extranet.view_facilities')->with('facilities', $array_hotel_facility);
//Generate UI like this
#foreach($facilities as $facility)
<div class="form-group col-md-3">
<div class="form-group">
<label>
<input type="checkbox" class="minimal" name="facilities[]" value="{{ $facility->facility_id }}" <?php if($facility->status){echo "checked";} ?>>
{{ $facility->facility }}
</label>
</div>
</div>
#endforeach

Laravel Pagination Appends Not Keeping Search Data

I've been able to implement the pagination and appends() on my form and it does show the proper values in the url on page 2, though it doesn't actually bring the values back into the form/query, it simply resets the actual data being searched for and displays all.
Here is my form code and the appends.
{{ Form::open(array('class' => 'stdform', 'method' => 'post', 'name' => 'all')) }}
<input type="text" name="srch_lname" class="input-large"
value="{{ Input::old('srch_lname', Session::get('srch_lname')) }}" />
<input type="text" name="srch_fname" class="input-large"
value="{{ Input::old('srch_fname', Session::get('srch_fname')) }}" />
.
.
.
<?php echo $employees->appends(array("srch_lname" => Session::get('srch_lname'),
"srch_fname" => Session::get('srch_fname') ))->links(); ?>
And my Controller
public function getIndex() {
$srch_lname = Session::get('srch_lname');
$srch_fname = Session::get('srch_fname');
$employees = vEmployees::co()->restrictions()
->where('lastname', 'LIKE', $srch_lname . '%')
->where('firstname', 'LIKE', $srch_fname . '%')
->paginate(10);
return View::make('employees.index')
->with('employees', $employees)
->with('title', 'Users');
}
public function postIndex() {
if (Input::has('btnSearch')) {
return Redirect::to('/employees')->with('search', 1)
->with('srch_lname', Input::get('srch_lname'))
->with('srch_fname', Input::get('srch_fname'));
else {
return Redirect::to('/employees');
}
}
Full Form
{{ Form::open(array('class' => 'stdform', 'method' => 'post', 'name' => 'all')) }}
<div class="stepContainer">
<div class="formwiz content">
<h4 class="widgettitle">Search for an Employee</h4>
<p>
<label>Lastname</label>
<span class="field">
<input type="text" name="srch_lname" class="input-large"
value="{{ Input::old('srch_lname', Session::get('srch_lname')) }}" />
</span>
</p>
<p>
<label>Firstname</label>
<span class="field">
<input type="text" name="srch_fname" class="input-large"
value="{{ Input::old('srch_fname', Session::get('srch_fname')) }}" />
</span>
</p>
</div>
</div>
<div class="actionBar" style="text-align: right;">
<button class="btn btn-primary" name="btnSearch" value="1">
Search for Employee(s)
</button>
</div>
{{ Form::close() }}
You need to pass your inputs to the view so that Input::old() has values to work with after the redirect from postIndex to getIndex.
in getIndex(), add to View::make()
->with('input', [ 'srch_lname'=> $srch_lname, 'srch_fname' => $srch_fname ]);
It looks like you do not have the pageSearch value in your pagination query string. Try this.
<?php echo $employees->appends(
array("btnSearch" => "1",
"srch_lname" => Session::get('srch_lname'),
"srch_fname" => Session::get('srch_fname') )
)->links(); ?>
I made a small sample but since I don't have your employees I just used the User model and commented out the filtering, just used as a test to pass and get input values.
Note the change to Input:: from Session, in getIndex() and in the form for $employees->appends(). Use Input instead of Session, I did not see anywhere in your code where you save the filter values in session variables.
I also changed the Redirect::to() to pass the parameters in the URL since it is a get method.
I tested and the filter values are passed to getIndex() and the form fields, also the inputs get properly passed by pagination links.
class EmployeeController extends BaseController
{
public
function getIndex()
{
$srch_lname = Input::get('srch_lname');
$srch_fname = Input::get('srch_fname');
$employees = User::query()
//->where('lastname', 'LIKE', $srch_lname . '%')
//->where('firstname', 'LIKE', $srch_fname . '%')
->paginate(10);
// make input available for page's form fields as old input
Session::flash('_old_input', Input::all());
return View::make('employees')
->with('employees', $employees)
->with('title', 'Users');
}
public
function postIndex()
{
if (Input::has('btnSearch'))
{
return Redirect::to('/employees?search=1&srch_lname=' . urlencode(Input::get('srch_lname')) . '&srch_fname=' . urlencode(Input::get('srch_fname')));
//return Redirect::to('/employees')->with('search', 1)
// ->with('srch_lname', Input::get('srch_lname'))
// ->with('srch_fname', Input::get('srch_fname'));
}
else
{
return Redirect::to('/employees');
}
}
}
Form and ->appends():
{{ Form::open(array('class' => 'stdform', 'method' => 'post', 'name' => 'all')) }}
<div class="stepContainer">
<div class="formwiz content">
<h4 class="widgettitle">Search for an Employee</h4>
<p>
<label>Lastname</label>
<span class="field">
<input type="text" name="srch_lname" class="input-large"
value="{{ Input::old('srch_lname', Session::get('srch_lname')) }}" />
</span>
</p>
<p>
<label>Firstname</label>
<span class="field">
<input type="text" name="srch_fname" class="input-large"
value="{{ Input::old('srch_fname', Session::get('srch_fname')) }}" />
</span>
</p>
</div>
</div>
<div class="actionBar" style="text-align: right;">
<button class="btn btn-primary" name="btnSearch" value="1">
Search for Employee(s)
</button>
</div>
{{ Form::close() }}
<?php echo $employees->appends(array("srch_lname" => Input::get('srch_lname'),
"srch_fname" => Input::get('srch_fname') ))->links(); ?>
I got it working! I continued to do some research and running the search through POST was really a major issue in adding that gap between the search itself and holding the data into the GET method of pagination.
I'll run through everything I did below for anyone in the future having the same issue.
I first created a Route that would direct to a new function in my EmployeesController
Route::get('emp_srch', 'EmployeesController#search');
And created the new function in the Controller
public function search() {
$srch_lname = Input::get('srch_lname');
$srch_fname = Input::get('srch_fname');
$employees = vEmployees::co()->restrictions()
->where('lastname', 'LIKE', $srch_lname . '%')
->where('firstname', 'LIKE', $srch_fname . '%')
->orderBy('lastname')
->orderBy('firstname')
->paginate(10);
Session::flash('_old_input', Input::all());
return View::make('employees.index')
->with('employees', $employees)
->with('title', 'Users')
->with('pagetitle', 'Employees')
}
It's essentially the function I had in the getIndex though rearranging the way the search was functioning I believe was the defining factor in actually getting this to work in my case.
I also changed the url on the form, which directed to my new Route. As well as changing the form so it uses the GET Method and no longer POST.
{{ Form::open(array('url' => 'emp_srch', 'class' => 'stdform', 'method' => 'get')) }}
I do want to thank vladsch and whoacowboy for helping push me in the right direction(s).

Resources