Laravel checkbox problem which I cannot update the pivot table - laravel

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.

Related

insert into 2 tables (pivot) array values from multiple select dropdown list

I work with events and years, one event can be in several years and a year can have
several events (pivot table created between the two tables).
I change my single dropdown list in multiple list :
<select id="year_id" type="text" class="form-control selectpicker #error('year_id') is-invalid #enderror" name="year_id[]" required multiple>
<option disabled>--Choisir--</option>
#foreach($years as $year)
#if(old('year') == $year->id)
<option value="{{ $year->id }}" selected>{{ $year->name }}</option>
#else
<option value="{{ $year->id }}">{{ $year->name }}</option>
#endif
#endforeach
</select>
The goal is to select several years for one same event.
I don't know why, but I think I'm not able to validate the form.
This is my controller code :
public function store(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'mnemonique' => 'required|string|max:255',
'color' => 'required|string|max:255',
'year_id[]' => 'required|array',
'year_id[].*' => 'required|integer|exists:years,id'
]);
$evenement = new Evenement();
//dd($validatedData);
// $evenement->create($validatedData);
$evenement = Evenement::create($validatedData);
$evenement->years()->sync([$validatedData['year_id[]']]);
I'm not able to insert the events into the pivot table and the new event into the event table.
If I use dd(), I still have a refresh of the form, I think I don't go into the controller...
Do you see something please ?
Thank you in advance.
Change validation rule to
'year_id' => 'required|array',
'year_id.*' => 'required|integer|exists:years,id'
To show Error message in view
#error('year_id')<div class="invalid-feedback">{{$message}}</div> #enderror
and
#if($errors->has('year_id.*')) <div class="invalid-feedback">Selected Year doesnt exists</div> #endif
While saving into database
$evenement->years()->sync($validatedData['year_id']);

Property [costo] does not exist on this collection instance

i need to print the price of a service, but can't find the column with the price.
maybe I'm doing something wrong with relationships, but I can't figure it out on my own
database:
Controller:
public function details(Request $request,$id){
$datax = [
'category_name' => 'apps',
'page_name' => 'calendar',
'has_scrollspy' => 0,
'scrollspy_offset' => '',
];
$evento = Eventos::find($id);
$servicio = \App\Models\Eventos::select("servicio_id")->where('servicio_id', $evento->id)->get('servicio_id');
$event = Eventos::find($id);
$event->asistencia = $request->asistencia;
$event->cancelado = $request->cancelado;
$event->save();
return view("evento",[
"event" => $event,
"servicio" => $servicio
])->with($datax);
}
blade.php
<div class="input-group mb-4">
<div class="input-group-prepend">
<span class="input-group-text">$</span>
</div>
<input type="text" value="{{$servicio->costo}}" class="form-control col-md-3" aria-label="Amount (to the nearest dollar)">
<div class="input-group-append">
<span class="input-group-text"></span>
</div>
</div>
I need to print the "costo" column in relation to service_id
help please
you can use laravel elequent relationship one to one.
if you have this two Servicio.php & Evento.php in App/Models or whatever your models name is, only replace your models in below code do this:
1-
in App/Models/Servicio.php define this relationship:
public function evento()
{
return $this->hasOne(Evento::class);
}
in App/Models/Evento.php define this relationship:
public function servicio()
{
return $this->belongsTo(Servicio::class);
}
now in controller add this:
$evento = Eventos::where('id' , $id)->with('servicio')->first();
in blade use this:
<input type="text" value="{{$evento->servicio->costo}}" >
2- also you can do this but i suggest you the first one:
only in your Codes change this:
$servicio = \App\Models\Servicio::where('id', $evento->servicio_id)->first();

Show checkbox checked from database

Hope you're all fine.
I have an article, and I want to be able to edit it. Inside the article, I have checkboxs, and what I want is to check the ones I've checked when I first create the article (Im using a pivot table).
I have this code for now.
public function createArticle(Request $request)
{
$data = $request->validate([
'titreArticle' => 'bail|required|between:5,40',
'typeArticle' => 'bail|required',
'themeCheckbox' => 'required',
'themeCheckbox.*' => 'required',
'contenuArticle' => 'bail|required',
]);
$type_articles = Type_article::findOrFail($data['typeArticle']);
$article = new Article();
$article->type_article()->associate($type_articles);
$themes = Theme::whereIn('theme_id', array_keys($data['themeCheckbox']))->get();
$article->titre = $data['titreArticle'];
$article->contenu = $data['contenuArticle'];
$article->save();
$article->theme()->attach( $themes);
return view('admin');
}
And inside my view :
#foreach ($themes as $theme)
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="themeCheckbox[{{$theme->theme_id}}]" value="1" >
<label class="form-check-label">{{ $theme->nom_theme }}</label>
</div>
#endforeach
I've seen I must use contains but don't really know how to use it...
Cordially

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 use sync on a many to many that includes a multiple extra fields

I'm trying to use sync on a many to many that includes a status and a comment. I can sync the applications without status and comment just fine.
NewUserAccount Model
public function applications()
{
return $this->belongsToMany('App\Application', 'new_user_account_applications', 'new_user_id')->withPivot('application_comment', 'status');
}
Application Model
public function newUserAccounts()
{
return $this->belongsToMany('App\NewUserAccount', 'new_user_accounts_applications', 'new_user_id')->withPivot('application_comment', 'status');
}
My NewUserAccountController
public function store(StoreRequest $request)
{
$userAccount = NewUserAccount::create(array_merge(
$request->all(),
['submitted_by' => $requester->id],
['start_date' => Carbon::parse($request->input('start_date'))],
['account_expires' => $request->accountExpires('newAccountExpireDate')],
['company_id' => $requester->company_id],
['username' => $request->manuallyAssignId()]
));
// Here I sync applications and include application comment and status
$userAccount->applications()->sync($request->applications, ['application_comment' => $request->application_comment, 'status' => 0]);
....
}
My pivot showing status and comment correctly
My form. Here is where I'm not sure how to handle the comment and get it to save with each application pivot record.
#foreach($applications as $application)
<label class="k-checkbox">
<input value="{{ $application->id }}" name="applications[]" type="checkbox">{{ $application->application_name }} <span></span>
</label>
<div class="form-group col-lg-4 mb-3">
<label>Comments</label>
<textarea name="application_comment[]" class="form-control" rows="2"></textarea>
</div>
#endforeach
First, you need to set the correct index for the application_comment attribute in your textarea. It's needed to correctly determine the comment for each application.
#foreach($applications as $application)
...
<textarea name="application_comment[{{ $application->id }}]" class="form-control" rows="2"></textarea>
...
#endforeach
Then, you just need to format your data to:
$userAccount->applications()->sync([
application_id_1 => ['application_comment' => 'comment for application_id 1'],
application_id_2 => ['application_comment' => 'comment for application_id 2'],
...
]);
So, here it is
$applications = collect($request->applications)->mapWithKeys(function ($appId) use ($request) {
return [$appId => [
'application_comment' => $request->input('application_comment')[$appId],
'status' => 0,
]];
});
$userAccount->applications()->sync($applications);

Resources