How To Update hasMany relationship data with multiple row at a time in Laravel? - laravel

I want to update SubCategory, which has a relationship with Category as a hasMany relationship. Now I want to update both category and subcategory at a time from one form. I want to update every subcategory which belongs to the category. But I can't do that.
Here is category model:
class Category extends Model
{
use HasFactory;
protected $guarded=[];
public function subcategory(){
return $this->hasMany('App\Models\SubCategory');
}
Here is subcategory model:
class SubCategory extends Model
{
use HasFactory;
protected $guarded=[];
public function category(){
return
$this>belongsTo('App\Models\Category','category_id','id');
}
here is update function in controller:
public function categoryUpdate(Request $request,$id){
if (is_null($this->user) || !$this->user->can('categories-update')) {
abort(403, 'Sorry !! You are Unauthorized !');
}
$request->validate([
'name' => 'required|max:191',
'status' => 'required',
]);
$Category=Category::findOrFail($id);
$Category->name = $request->name;
$Category->slug = Str::slug($request->name);
$Category->status = $request->status;
$Category->updated_by=Auth::user()->id;
$Category->update();
if($request->subcategory_name !=['']){
foreach($request->subcategory_name as $subcat){
if($subcat !=''){
SubCategory::create([
'name'=>json_encode($subcat),
'slug'=>Str::slug(json_encode($subcat)),
'category_id'=>$id,
'created_by' =>Auth::user()->id,
]);
}
}
}
Alert::success('Success','Category has been updated successfully!');
return redirect()->route('category.index');
}
I don't know the code to update multiple subcategories at a time.
Here is the Html form
<form action="{{ route('category.update', $data->id) }}" method="POST">
#csrf
<div class="form-group">
<label for="" class="mb-2">Category name</label>
<input name="name" class="form-control" value="{{ $data->name }}" type="text"
#error('name') is-invalid #enderror" placeholder="Name">
#error('name')
<div class="text-danger">* {{ $message }}</div>
#enderror
</div><br>
<div class="form-group">
<label for="" class="mb-2">SubCategory name</label>
#foreach ($subcat as $sub)
<div class="d-flex w-70 justify-content between mb-2">
<input name="subcategoryname[]" id="subcategoryname" class="form-control w-50" type="text" value="{{json_decode($sub->name)}}"></input>
<button onclick="deleteSubcategory({{$sub->id}})" id="delete_subcat" class="btn btn-danger btn-sm ms-2"><i
class="fa fa-trash text-dark" style="font-size:20px;color:white!important"
aria-hidden="true"></i></button>
</div>
#endforeach
</div><br>
<div class="form-group mt-2">
<label for="" class="mb-2">Add New SubCategory</label>
<div class="subcategory w-50">
<div class="d-flex mb-2">
<input name="subcategory_name[]" class="form-control" id="name" type="text"
placeholder="Name" multiple>
<span id="add" class="btn btn-dark ms-3">+</span>
</div>
</div>
<div class="form-group mt-2">
<label for="" class="mb-2">Status</label>
<br>
<select name="status" class="form-control" style="width:40%"
#error('status') is-invalid #enderror">
<option value="">--Select Status--</option>
<option value="Active" #if ($data->status == 'Active') selected #endif>Active
</option>
<option value="Inactive" #if ($data->status == 'Inactive') selected #endif>Inactive
</option>
</select>
#error('status')
<div class="text-danger">* {{ $message }}</div>
#enderror
</div>
<div class="form-group mt-4 d-flex justify-content-between">
<button type="button" class="btn btn-secondary btn-sm"
data-bs-dismiss="modal">Cancel</button>
<input class="btn btn-primary btn-sm"type="submit" value="Update">
</div>
</form>

The create method takes array of records you want to save. So you can build an array and pass that array to the create method on the SubCategory.
if($request->subcategory_name !=['']){
$subCategories = [];
foreach($request->subcategory_name as $subcat){
if($subcat !=''){
$subCategories[] = [
'name'=>json_encode($subcat),
'slug'=>Str::slug(json_encode($subcat)),
'category_id'=>$id,
'created_by' =>Auth::user()->id,
];
}
}
SubCategory::updateOrCreate(['name', 'slug'], $subCategories);
}

Related

How to insert this array of mySbjects in a database?

I've been trying to insert this into the database and I don't have any idea how to store this information into the database... The relationship between user and grade is many-to-many and between grade and mySubject is One-to-many.
<div class="row">
#foreach($grades as $grade)
<div class="card shadow mx-2 my-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold">
<div class="custom-control custom-checkbox">
<input class="custom-control-input #error('grade') is-invalid #enderror" type="checkbox" id="{{$grade->id}}" name="grade[]" value="{{ $grade->id }}"/>
<label class="custom-control-label pt-1" for="{{$grade->id}}">{{$grade->name}}</label>
</div>
</h6>
</div>
<div class="card-body">
#foreach($grade->subjects as $subject)
<div class="custom-control custom-checkbox mb-2">
<input class="custom-control-input" type="checkbox" id="{{$grade->id}}{{$subject->id}}" name="mySubjects[{{$grade->id}}][]" value="{{ $subject->name }}"/>
<label class="custom-control-label" for="{{$grade->id}}{{$subject->id}}">
{{$subject->name}}
</label>
</div>
#endforeach
</div>
</div>
#endforeach
</div>
The store function
public function store(Request $request)
{
$user->grades()->sync($request->grade);
if($request->mySubjects){
//. . . .
}
}
}
Try below code:
public function store(Request $request)
{
$user->grades()->sync($request->grade);
if($request->mySubjects){
$mySubjects = $request-> mySubjects;
$data = [];
foreach($mySubjects as $subject){
array_push($data,
'your database field name'=> $subject,
'created_at' => now()->toDateTimeString(),
'updated_at' => now()->toDateTimeString(),
}
YourModelName::insert($data);
}
}
}

Laravel - How to display child goal type name on select dropdown on edit form

In my Laravel-5.8 project, I am trying to child name (text) on select list in edit form.
I have this table:
CREATE TABLE `goal_types` (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`parent_id` int(11) DEFAULT NULL,
`max_score` int(11) DEFAULT 0,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Model
class GoalType extends Model
{
public $timestamps = false;
protected $table = 'goal_types';
protected $primaryKey = 'id';
protected $fillable = [
'name',
'parent_id',
'max_score',
];
protected $casts = [];
public function children()
{
return $this->hasMany('App\Models\GoalType', 'parent_id');
}
public function parent()
{
return $this->hasOne(App\Models\GoalType::class, 'id', 'parent_id');
}
}
Controller
public function index()
{
$categories = GoalType::with('children')->whereNull('parent_id')->get();
return view('goal_types.index')->with('categories', $categories);
}
public function create()
{
return view('goal_types.create');
}
public function store(StoreGoalTypeRequest $request)
{
$data = GoalType::create([
'name' => $request->name,
'parent_id' => $request->parent_id,
'max_score' => $request->max_score,
]);
Session::flash('success', 'Goal Type is created successfully');
return redirect()->route('goal_types.index');
}
I have a modal form for the edit
view
<div class="row">
<div class="col-md-8">
<div class="card card-secondary">
<div class="card-header">
<h3 class="card-title">Goal Type(s)</h3>
</div>
<div class="card-body">
<ul class="list-group">
#foreach ($categories as $category)
<li class="list-group-item">
#if ($category->children)
<ul class="list-group mt-2">
#foreach ($category->children as $child)
<li class="list-group-item">
<div class="d-flex justify-content-between">
{{ $child->name }}
<div class="button-group d-flex">
#can('goal_type_edit')
<button type="button" class="btn btn-sm btn-primary mr-1 edit-category" data-toggle="modal" data-target="#editCategoryModal" data-id="{{ $child->id }}" data-name="{{ $child->name }}">Edit</button>
#endcan
</div>
</div>
</li>
#endforeach
</ul>
#endif
</li>
#endforeach
</ul>
</div>
</div>
</div>
<div class="modal fade" id="editCategoryModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Edit Goal Type</h4>
<form action="" method="POST">
#csrf
#method('PUT')
<div class="modal-body">
<div class="form-group">
<label class="control-label"> Parent Goal Type:</label>
<select class="form-control select2bs4" data-placeholder="Choose Parent Goal Type" tabindex="1" name="parent_id" style="width: 100%;">
<option value="">Select Goal Type</option>
#foreach ($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
</select>
</div>
<div class="form-group">
<label class="control-label"> Name:<span style="color:red;">*</span></label>
<input type="text" name="name" class="form-control" value="" placeholder="Category Name" required>
</div>
<div class="form-group">
<label class="control-label"> Max. Weight (%):</label>
<input type="number" name="max_score" class="form-control" value="" step="0.01" placeholder="Enter maximum weight here: 15, 50, 75 etc" style="width: 100%;">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Update</button>
</div>
</div>
</form>
</div>
</div>
</div>
When I click on edit from the index a modal form should popup to display the child name where the parent_id equals the id of the parent as it is in the database. But the select dropdown value/text is not displaying anything until when I click on the select dropdown.
How do I modify
#foreach ($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
in the edit to achieve that (displaying the name of the select child on the dropdown)?
Thanks
In your edit view you must pass your category id in your form action like this action="{{ route('admin.categories.update' , $category->id) }}" and then compare it with parent_id and in your category model you have to pass children.
category model:
public function children()
{
return $this->hasMany(GoalType::class, 'parent_id' , 'id')->with('children');
}
edit.blade.php view
<div class="col-md-12">
<label for="parent_id" class="form-control-label">parents category name</label>
<select class="form-control" data-toggle="select" data-live-search="true" name="parent_id" id="parent_id">
<option value="0" {{ $category->parent_id === 0 ? 'disabled' : '' }} selected> - Default</option>
#foreach(\App\Models\Category::latest()->get() as $cate)
<option value="{{ $cate->id }}" {{ $cate->id === $category->parent_id ? 'selected' : '' }} {{ $cate->id === $category->id ? 'disabled' : '' }} {{ $cate->id === $category->parent_id ? 'disabled' : '' }}>{{ $cate->name }}</option>
#endforeach
</select>
</div>

Laravel Error during update - Undefined variable: id

I am working on a project using Laravel-5.8
protected $table = 'ratings';
protected $fillable = [
'rating_type',
'rating_value',
'rating_description',
];
public function rules()
{
return [
'rating_type' => 'required|numeric|min:1|max:10|unique:appraisal_ratings,rating_type,company_id'.$this->id,
];
}
The rating has an id column, and that's the primary key. Why I checked it against company_id is that different companies can have the same rating type.
Controller
public function edit($id)
{
$rating = Rating::where('id', $id)->first();
return view('ratings.edit')
->with('rating', $rating)
->with('rating_types', $this->rating_types)
->with('rating_descriptions', $this->rating_descriptions)
->with('rating_values', $this->rating_values);
}
public function update(UpdateRatingRequest $request, $id)
{
$rating = Rating::find($id);
$rating->rating_type = $request->rating_type;
$rating->rating_value = $request->rating_value;
$rating->rating_description = $request->rating_description;
$rating->save();
Session::flash('success', 'Rating is updated successfully');
return redirect()->route('ratings.index');
}
edit.blade
<form action="{{route('ratings.update', ['id'=>$rating->id])}}" method="post" class="form-horizontal" enctype="multipart/form-data">
{{ csrf_field() }}
<input name="_method" type="hidden" value="PUT">
<div class="card-body">
<div class="form-body">
<div class="row">
<div class="col-12 col-sm-4">
<div class="form-group">
<label class="control-label"> Rating:<span style="color:red;">*</span></label>
<select class="form-control select2bs4" data-placeholder="Choose Rating" tabindex="1" name="rating_type" style="width: 100%;">
<option value="">Select Rating</option>
#foreach($rating_types as $k => $rating_type)
<option value="{{$k}}" #if($rating->rating_type == $k) selected #endif>{{$rating_type}}</option>
#endforeach
</select>
</div>
</div>
<div class="col-12 col-sm-4">
<div class="form-group">
<label class="control-label"> Description:<span style="color:red;">*</span></label>
<select class="form-control select2bs4" data-placeholder="Choose Description" tabindex="1" name="rating_description" style="width: 100%;">
<option value="">Select Description</option>
#foreach($rating_descriptions as $k => $rating_description)
<option value="{{$k}}" #if($rating->rating_description == $k) selected #endif>{{$rating_description}}</option>
#endforeach
</select>
</div>
</div>
<div class="col-12 col-sm-4">
<div class="form-group">
<label class="control-label"> Rating Score:<span style="color:red;">*</span></label>
<select class="form-control select2bs4" data-placeholder="Choose Rating Score" tabindex="1" name="rating_value" style="width: 100%;">
<option value="">Select Rating Score</option>
#foreach($rating_values as $k => $rating_value)
<option value="{{$k}}" #if($rating->rating_value == $k) selected #endif>{{$rating_value}}</option>
#endforeach
</select>
</div>
</div>
</div>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-primary">{{ trans('global.save') }}</button>
<button type="button" onclick="window.location.href='{{route('ratings.index')}}'" class="btn btn-default">Cancel</button>
</div>
</form>
When I clicked on the save button to update, I got this error:
rating_type already exists.
That error should not have occured since I am doing update.
How do I resolve it?
Thank you.
You are checking the unique on update wrong
Unique Rule Usage
unique:table,column,except,idColumn
* 3rd param is for value for column to except and 4th is for column to except
Fix
//App\Http\Requests\UpdateRatingRequest
'rating_type' => 'required|numeric|min:1|max:10|unique:table_name,rating_type,table_primary_key'.$this->id,

Hidden type input value not being passed in Laravel gallery Project

I have created an album. I am trying to upload photos to the album and storing the album_id through the 'hidden' type input. When i check the source code, album_id is shown in 'value' attribute but unfortunately the value is not being passed to the query during form submission.
My create method of PhotoController which shows the form
public function create($id)
{
$albums = Album::where('id',$id)->first();
return view('admin.pages.photos',compact('albums', 'id'));
}
Here is the form.
<div class="container">
<div class="row">
<a class="btn btn-success" href="/gallery/{{$albums->slug}}">Back to Gallery</a>
<h4>Upload Photos to <strong>{{$albums-> name}}</strong> Gallery</h4>
#if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
#endif
<img class="thumbnail" src="/images/gallery/{{$albums->cover_pic}}" alt="{{$albums->name}}">
</div>
<div class="col-md-8">
<form class="form-horizontal" action="/photo" method="POST" enctype="multipart/form-data" >
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<label class="col-md-8">Photo Title:</label>
<input type="text" name="photo_name" class="form-control" placeholder="Name of the Photo" value="{{ old('photo_name') }}" >
</div>
<div class="form-group">
<label class="col-md-8">Description</label>
<input type="text" name="desc" class="form-control" placeholder="Write Description" value="{{ old('desc') }}">
</div>
<div class="form-group">
<label class="col-md-8">Upload Pic</label>
<input type="file" name="photo" class="form-control" value="{{old('photo')}}" >
</div>
<input type="hidden" name="album_id" value="{{$albums->id}}">
<button type="submit" name="submit" class="btn btn-success waves-effect waves-light m-r-10">Submit</button>
</form>
and the store method
public function store(Request $request)
{
$this->validate($request, [
'photo_name'=>'required|min:3',
'desc'=>'required',
'photo'=>'required'
]);
$photo = new Photo;
$photo->album_id = $request->album_id;
$photo->photo_name = $request->photo_name;
$str = strtolower($request->photo_name);
$photo->slug = preg_replace('/\s+/', '-', $str);
if($file=$request->file('photo')){
$name = time().'.'.$file->getClientOriginalName();
$file->move('images/gallery', $name);
$photo['photo'] = $name;
}
$photo->desc = $request->desc;
$photo->save();
return redirect()->back()->with('status', 'Photo Successfully Added!');
}

Laravel 5.2 cannot update record

I cannot seem to update my record.
My controller
public function add()
{
return view('cars.add');
}
public function edit($id)
{
$car = Cars::whereId($id)->firstOrFail();
return view('cars.edit', compact('car'));
}
public function store(CarFormRequest $request)
{
$car = new Cars(array(
'name' => $request->get('name'),
'color_id' => $request->get('color')
));
$car->save();
$car->position_id = $car->id;
$car->save();
session()->flash('status', 'Successfully Added a Car!');
return view('cars.add');
}
public function update($id, CarFormRequest $request)
{
$car = car::whereId($id)->firstOrFail();
$car->name = $request->get('name');
$car->color_id = $request->get('color');
if($request->get('status') != null) {
$car->status = 0;
} else {
$car->status = 1;
}
$car->save();
return redirect(action('CarController#edit', $car->id))->with('status', 'The ticket '.$id.' has been updated!');
}
my routes:
Route::get('/', 'PagesController#home');
Route::get('/about', 'PagesController#about');
Route::get('/contact', 'PagesController#contact');
Route::get('/cars', 'CarsController#index');
Route::get('/cars/edit/{id?}', 'CarsController#edit');
Route::post('/cars/edit/{id?}', 'CarsController#update');
Route::get('/cars/add', 'CarsController#add');
Route::post('/cars/add', 'CarsController#store');
here is my view:
<div class="container col-md-8 col-md-offset-2">
<div class="well well bs-component">
<form class="form-horizontal" method="post">
<input type="hidden" name="_token" value="{!! csrf_token() !!}">
<input type="text" id="color_id" name="color_id" value="{!! $car->color_id !!}">
<fieldset>
<legend>Edit Car Information</legend>
<div class="form-group">
<label for="title" class="col-lg-2 control-label">Car Name</label>
<div class="col-lg-10">
<input type="text" value="{{ $car->name }}" class="form-control" id="name" placeholder="Car Name">
</div>
</div>
<div class="form-group">
<label for="title" class="col-lg-2 control-label">Car Color</label>
<div class="col-lg-10">
<div class="btn-group" data-toggle="buttons">
<label id="opt1" class="btn btn-primary">
<input type="radio" name="color" id="option1" autocomplete="off"> Red
</label>
<label id="opt2" class="btn btn-primary">
<input type="radio" name="color" id="option2" autocomplete="off"> Blue
</label>
<label id="opt3" class="btn btn-primary">
<input type="radio" name="color" id="option3" autocomplete="off"> Yellow
</label>
<label id="opt4" class="btn btn-primary">
<input type="radio" name="color" id="option4" autocomplete="off"> Green
</label>
<label id="opt5" class="btn btn-primary">
<input type="radio" name="color" id="option5" autocomplete="off"> Black
</label>
<label id="opt6" class="btn btn-primary">
<input type="radio" name="color" id="option6" autocomplete="off"> White
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<button class="btn btn-default">Cancel</button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
The $id variable in whereIn must be array and you need to specify the database column too. This should be like -
public function edit($id)
{
$car = Cars::whereId('id', [$id])->firstOrFail();
return view('cars.edit', compact('car'));
}
Change all occurrence of
$car = car::whereId($id)->firstOrFail();

Resources