Laravel 4 - Update many to many - laravel

I am currently trying to amend an update page which features a many to many relationship. It updates to my database perfectly, however all I'm trying to achieve now is to actually show the already selected items in my multiple select list in my view.
It currently just shows the entire list of oilgas jobs, just not the currently selected ones which should come from the query in some way.
So, it currently looks like this:
I need it to look like this, if Instrument Technician was previously chosen.
The associated files are as follows:
MODELS
OilGasJob.php
<?php
class OilGasJob extends \Eloquent {
protected $table = 'oilgasjobs';
public function industryjobs()
{
return $this->belongsToMany('IndustryJob');
}
}
IndustryJob.php
<?php
class IndustryJob extends \Eloquent {
protected $table = 'industryjobs';
public function oilgasjobs()
{
return $this->belongsToMany('OilGasJob');
}
}
CONTROLLER (CREATE PAGE AND STORE)
public function edit($id)
{
$industryjob = IndustryJob::find($id);
if(is_null($id))
{
return Redirect::to('/admin/industry-jobs')->with('message', 'This division job is not valid');
}
View::share('page_title', 'Edit Division Job');
return View::make('admin/industry-jobs/edit')->with('industryjob',$industryjob);
}
public function update($id)
{
$rules = array(
'job_title' => 'Required|Min:3|Max:80'
);
$validation = Validator::make(Input::all(), $rules);
If ($validation->fails())
{
return Redirect::back()->withErrors($validation);
} else {
$industryjob = IndustryJob::find($id);
if(is_null($id))
{
return Redirect::to('/admin/industry-jobs')->with('message', 'This divison job is not valid');
}
View::share('page_title', 'Edit Division Job');
$industryjob->job_title = Input::get('job_title');
$industryjob->slug = Str::slug(Input::get('job_title'));
$industryjob->job_description = Input::get('job_description');
$industryjob->job_qualifications = Input::get('job_qualifications');
$industryjob->save();
$industryjob->oilgasjobs()->sync(Input::get('oilgasjobs'));
return Redirect::to('/admin/industry-jobs')->with('message', 'Division Job updated successfully');
}
}
VIEW
{{ Form::open(array('url' => URL::to('admin/industry-jobs/edit/'.$industryjob->id), 'class'=>'form-horizontal', 'method' => 'POST')) }}
<div class="form-group">
<label class="col-md-2 control-label" for="industry_name">Job Title (*)</label>
<div class="col-md-10">
<input class="form-control" type="text" name="job_title" id="job_title" value="{{ $industryjob->job_title }}" />
</div>
</div>
<!-- Industry Type -->
<div class="form-group">
<label class="col-md-2 control-label" for="body">Related Jobs in Oil & Gas</label>
<div class="col-md-10">
<select name="oilgasjobs[]" id="oilgasjobs[]" size="6" class="form-control" multiple>
#foreach(OilGasJob::orderBy('job_title', 'ASC')->get() as $oilgasjob)
<option value="{{ $oilgasjob->id }}" >{{ $oilgasjob->job_title }}</option>
#endforeach
</select>
</div>
</div>
<!-- ./ Industry Type -->
<!-- Form Actions -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="reset" class="btn btn-default">Reset</button>
<button type="submit" class="btn btn-success">Update Job</button>
</div>
</div>
<!-- ./ form actions -->
{{ Form::close() }}

In edit method add this code:
// ...
$linkedOilgasjob = DB::table('oilgasjob_industryjob')->lists('oilgasjob_id');
return View::make('admin/industry-jobs/edit'
,compact('industryjob')
,compact('linkedOilgasjob'));
Then in your view
<option value="{{ $oilgasjob->id }}" {{ in_array($oilgasjob->id,linkedOilgasjob) ? "selected='selected'" : "" }} >
{{ $oilgasjob->job_title }}
</option>

CONTROLLER
public function edit($id)
{
$data['industryjob'] = IndustryJob::find($id);
$data['oilgasjobs'] = DB::table('industry_job_oil_gas_job')->where('industry_job_id','=',$id)->lists('oil_gas_job_id');
if(is_null($id))
{
return Redirect::to('/admin/industry-jobs')->with('message', 'This division job is not valid');
}
View::share('page_title', 'Edit Division Job');
return View::make('admin/industry-jobs/edit', $data);
}
VIEW
<select name="oilgasjobs[]" id="oilgasjobs[]" size="6" class="form-control" multiple>
#foreach(OilGasJob::orderBy('job_title', 'ASC')->get() as $oilgasjob)
<?php
$selected = "";
if(in_array($oilgasjob->id, $oilgasjobs))
$selected = "selected";
?>
<option value="{{ $oilgasjob->id }}" <?php echo $selected; ?>>{{ $oilgasjob->job_title }}</option>
#endforeach
</select>

Related

Laravel Update DB with array from views

i'm doing a simple project but having some difficulties with updating my database with values that I get from a form. The project is having a list of movies and when you click on one it would take you to a page with more details. Theres a button which you can update the details of that movie. I'm trying save whatever details are made to the relevant index of the table using the id. I can't seem to get it to work though. I did something similar when creating a new entry but having some difficulty updating the values of a specific movie/page. Thanks for any help!
Route:
Route::get('catalog', 'App\Http\Controllers\CatalogController#getIndex');
Route::get('catalog/show/{id}', 'App\Http\Controllers\CatalogController#getShow');
Route::get('catalog/create', 'App\Http\Controllers\CatalogController#getCreate');
Route::get('catalog/edit/{id}', 'App\Http\Controllers\CatalogController#getEdit');
Route::post('catalog/create', 'App\Http\Controllers\CatalogController#postCreate');
Route::put('catalog/edit/{id}','App\Http\Controllers\CatalogController#putEdit');
Controller:
public function getEdit($id)
{
return view('catalog.edit', ['arrayPeliculas' => Movie::all()]);
}
public function getCreate()
{
return view('catalog.create');
}
public function postCreate(Request $request)
{
$Movie = new Movie;
$Movie->title = $request->title;
$Movie->year = $request->year;
$Movie->director = $request->director;
$Movie->poster = $request->poster;
$Movie->synopsis = $request->synopsis;
$Movie->save();
return redirect()->action('App\Http\Controllers\CatalogController#getIndex');
}
public function putEdit(Request $request, $id)
{
$Movie = new Movie;
$Movie[$id]->title = $request->title;
$Movie[$id]->year = $request->year;
$Movie[$id]->director = $request->director;
$Movie[$id]->poster = $request->poster;
$Movie[$id]->synopsis = $request->synopsis;
$Movie->save();
return redirect()->action('App\Http\Controllers\CatalogController#getIndex');
}
Edit page:
<form method="PUT">
{{ method_field('PUT') }}
{{-- TODO: Protección contra CSRF --}}
{{ csrf_field() }}
<div class="form-group">
<label for="modificar">Modificar Pelicula</label>
<input type="text" name="title" id="title" class="form-control" value="{{ $arrayPeliculas[$id]->title }}">
</div>
<div class="form-group">
{{-- TODO: Completa el input para el año --}}
<label for="Año">Año</label>
<input type="text" name="year" id="year" class="form-control" value="{{ $arrayPeliculas[$id]->year }}">
</div>
<div class="form-group">
{{-- TODO: Completa el input para el director --}}
<label for="Director">Director</label>
<input type="text" name="director" id="directo" class="form-control" value="{{ $arrayPeliculas[$id]->director }}">
</div>
<div class="form-group">
{{-- TODO: Completa el input para el poster --}}
<label for="Poster">Poster</label>
<input type="text" name="poster" id="poster" class="form-control" value="{{ $arrayPeliculas[$id]->poster }}">
</div>
<div class="form-group">
<label for="synopsis">Resumen</label>
<textarea name="synopsis" id="synopsis" class="form-control" rows="3" >{{ $arrayPeliculas[$id]->synopsis }}"</textarea>
</div>
<div class="form-group text-center">
<button type="submit" class="btn btn-primary" style="padding:8px 100px;margin-top:25px;">
Añadir película
</button>
</div>
</form>
I tried a few other things like->update but I can't seem to get it to work properly.
To update an existing model, first find() it.
public function putEdit(Request $request, $id)
{
$Movie = Movie::find($id);
$Movie->title = $request->title;
$Movie->year = $request->year;
$Movie->director = $request->director;
$Movie->poster = $request->poster;
$Movie->synopsis = $request->synopsis;
$Movie->save();
return redirect()->action('App\Http\Controllers\CatalogController#getIndex');
}
Using the update function should also work then:
public function putEdit(Request $request, $id)
{
$Movie = Movie::find($id);
$Movie->update([
'title' => $request->title,
'year' => $request->year,
'director' => $request->director,
'poster' => $request->poster,
'synopsis' => $request->synopsis,
]);
return redirect()->action('App\Http\Controllers\CatalogController#getIndex');
}
You could really simplify it with some Laravel magic like Route Model Binding...
Route::put('catalog/edit/{movie}','App\Http\Controllers\CatalogController#putEdit');
...
public function putEdit(Request $request, Movie $movie)
{
$movie->update($request->all());
return redirect()->action('App\Http\Controllers\CatalogController#getIndex');
}

Laravel - How to make students not to score beyond the max mark

I am using Laravel-5.8 for a web application project. In the project I have these tables:
class SubjectCategory extends Model
{
protected $table = 'subject_categories';
protected $fillable = [
'name',
'parent_id',
'max_mark',
];
public function children()
{
return $this->hasMany('App\Models\SubjectCategory', 'parent_id');
}
public function exams()
{
return $this->hasMany('App\Models\Exam');
}
}
class Exam extends Model
{
protected $table = 'exams';
protected $fillable = [
'subject_category_id',
'student_id',
'student_mark',
'subject_name',
];
public function subjectcategory()
{
return $this->belongsTo('App\Models\SubjectCategory','subject_category_id');
}
}
SubjectCategory is an hierarchical table. Only the parent have the max_mark
Here is the Controller
public function create()
{
$categories = SubjectCategory::with('children')->whereNull('parent_id')->get();
return view('exams.create')
->with('categories', $categories);
}
public function store(StoreExamRequest $request)
{
$exam = new Exam();
$exam->stubject_category_id = $request->stubject_category_id;
$exam->student_id = $student_id;
$exam->student_mark = $request->student_mark;
$exam->save();
return redirect()->route('exams.index');
}
view blade
<div class="row">
<div class="col-md-12">
<!-- general form elements -->
<div class="card card-secondary">
<form method="POST" action="{{route('exams.store')}}">
#csrf
<div class="card-body">
<div class="form-body">
<div class="row">
<div class="col-12 col-sm-6">
<div class="form-group">
<label class="control-label"> Subject Category:<span style="color:red;">*</span></label>
<select id="subject_category" class="form-control" name="subject_category_id">
<option value="">Select Subject Category</option>
#foreach ($categories as $category)
<option disabled="disabled" value="{{ $category->id }}" {{ $category->id == old('category_id') ? 'selected' : '' }}>{{ $category->name }}</option>
#if ($category->children)
#foreach ($category->children as $child)
<option value="{{ $child->id }}" {{ $child->id == old('category_id') ? 'selected' : '' }}> {{ $child->name }}</option>
#endforeach
#endif
#endforeach
</select>
</div>
</div>
<div class="col-12 col-sm-6">
<div class="form-group">
<label class="control-label"> Subject Name:<span style="color:red;">*</span></label>
<input type="text" name="subject_name" placeholder="Enter Subject Name here" class="form-control">
</div>
</div>
<div class="col-12 col-sm-4">
<div class="form-group">
<label class="control-label"> Mark Obtained:</label>
<input type="number" name="student_mark" placeholder="Enter Mark Obtained here" class="form-control">
</div>
</div>
</div>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
<!-- /.card -->
</div>
<!--/.col (left) -->
</div>
Subjects are categorized. From SubjectCategory, the parent subject have sub subjects as children. Only the Parent Subject Category have the Maximum Obtainable Score (Max Mark).
From the Exam (subject_category_id) dropdownlist contains all the children fields from subject_categories. What I want to achieve is this:
When Subject Category is selected from the dropdownlist, the system goes to the exams table. It displays total student_mark based on student_id and subject_category_id.
In each subject, the student accumulated mark cannot be more than the max_mark in the parent subject_category.
When the user tries to enter data into student_mark text field, the application adds the value in the text field to the student aggregate. If the result is more than the max_mark in subject_categories (SubjectCategory) based on the parent max_mark, then an error message is displayed.
How do I achieve this?
Thank you.
This is achievable in a couple of different ways; you could use validation to prevent someone entering a value over the max mark, or if they do enter a value over the max mark then you just silently reduce it back to the max mark.
I would suggest you take the validation approach and to do this you would need to use a custom validation rule.
You can read up on the documentation for how to create one (https://laravel.com/docs/5.8/validation#custom-validation-rules) but the implementation might look a little something like this:
// Inside a form request (or you could use inline validation in your controller
'student_mark' => [new NotOverMaxMark($this->input('subject_category_id'))]
Then for the rule itself might look a little something like this:
<?php
namespace App\Rules;
use App\SubjectCategory;
use Illuminate\Contracts\Validation\Rule;
class NotOverMaxMark implements Rule
{
private $subjectCategory;
public function __construct($subjectCategoryId)
{
$this->subjectCategory = SubjectCategory::findOrFail($subjectCategoryId);
}
public function passes($attribute, $value)
{
return $value <= $this->subjectCategory->max_mark;
}
public function message()
{
return 'The :attribute must not be higher than the max mark.';
}
}
The above is an example of how you might do this, you may need to tweak the imports or implementation to your needs.

Laravel - How to Make Lesson aggregate score not more than course max score

I am developing a web application on Student Course Management using Laravel-5.8
Models
class Lesson extends Model
{
protected $table = 'Lessons';
protected $fillable = [
'lesson_name',
'course_id',
'student_id',
'score_obtained',
];
public function gradelevel()
{
return $this->belongsTo('App\Models\Course','course_id');
}
public function student()
{
return $this->belongsTo('App\Models\Student','student_id');
}
}
class Course extends Model
{
protected $table = 'courses';
protected $fillable = [
'course_code',
'course_name',
'max_score',
];
}
Controller
class LessonController extends Controller
{
public function create()
{
$courses = Course::all();
$students = Student::all();
return view('lessons.create')->with('courses', $courses)->with('students', $students);
}
public function store(StoreLessonRequest $request)
{
try {
$lesson = Lesson::create([
'lesson_name' => $request->lesson_name,
'course_id' => $request->course_id,
'lesson_id' => $request->lesson_id,
'score_obtained' => $request->score_obtained,
]);
Session::flash('success', 'Lesson is created successfully');
return redirect()->route('lessons.index');
} catch (Exception $exception) {
Session::flash('danger', 'Lesson creation failed!');
return redirect()->route('lessons.index');
}
}
}
create.blade
<form action="{{route('lessons.store')}}" method="post" class="form-horizontal" enctype="multipart/form-data">
{{csrf_field()}}
<div class="card-body">
<div class="form-body">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label>Course</label>
<select class="form-control select2bs4" data-placeholder="Choose Course" tabindex="1" name="course_id" style="width: 100%;">>
<option value="">Select Course</option>
#if($courses->count() > 0)
#foreach($courses as $course)
<option value="{{$course->id}}">{{$course->course_name}}</option>
#endforeach
#endif
</select>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label>Student</label>
<select class="form-control select2bs4" data-placeholder="Choose Course" tabindex="1" name="student_id" style="width: 100%;">>
<option value="">Select Student</option>
#if($students->count() > 0)
#foreach($students as $student)
<option value="{{$student->id}}">{{$student->student_name}}</option>
#endforeach
#endif
</select>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label>Lesson<span style="color:red;">*</span></label>
<input type="text" name="lesson_name" placeholder="Enter lesson here" class="form-control" value="{{old('lesson_name')}}">
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label>Obtained Score<span style="color:red;">*</span></label>
<input type="text" name="score_obtained" placeholder="Enter score obtained here" class="form-control" value="{{old('score_obtained')}}">
</div>
</div>
</div>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" id="submit_create" class="btn btn-primary">Score</button>
</div>
</form>
Each core have maximum score allocated and this is done at the setting. For each course, students have lesson and scores are obtained for each lesson.
What I want to achieve is that on the lesson create form, what student score_obtained are being entered the application should sum up all the scores (from the lesson table and the just entered one) the student obtained for that particular course including the one in the textbox, if its more that what is in the max_score in the courses table for that particular course the application should display a message and shouldn't allow the user to submit.
How do I achieve this?
Thank you.
In store method, you can write below code:
$maxScore = Course::find($request->course_id)->max_score;
$scoresObtained = Lession::where('course_id' , $request->course_id)->sum('score_obtained');
$totalScore = intval($scoresObtained) + intval($request->score_obtained);
if($totalScore > $maxScore)
{
return redirect()->back()->withErrors([__('Total score exceeds max score for selected course')]);
}
You can use floatval() in place of intval() in case your scores are in decimals

I got this error "Argument 1 passed to Illuminate\Database\Grammar::parameterize() must be of the type

When i try to insert data into my table this error occurs
Argument 1 passed to Illuminate\Database\Grammar::parameterize() must be of the type array, string given, called in C:\xampp\htdocs\Portal\vendor\laravel\framew...
view
<form method="post" action="{{ route('notice.store') }}">
{{ csrf_field() }}
<div class="form-group">
<label for="Select Group to Post Notice">Select Group to Post Notice </label>
<select class="bg-white text-danger form-control " name='GroupID[]' multiple>
#foreach ($users as $user)
<option value="{{ $user->GroupID }}">{{ $user->GroupID }}</option>
#endforeach
</select>
</div>
<div class="form-group">
<label for="Enter Notice">Enter Notice</label>
<input class="bg-white text-danger p-2 form-control form-control-sm" type="text" name="Notice" placeholder="Enter Notice">
</div>
<input class="btn btn-danger btn-lg px-5" type="submit" name="submit">
</form>
controller
public function store(Request $request)
{
$member = $request->input('GroupID');
foreach($member as $value) {
$storeInfo = new notice();
$storeInfo->GroupID = $request->input('GroupID');
$storeInfo->Notice = $request->input('Notice');
$storeInfo->save();
}
return redirect('/notice');
}
I would imagine the reason you're getting this error is because of:
$storeInfo->GroupID = $request->input('GroupID');
$request->input('GroupID') will return an array (name='GroupID[]') and not an individual id.
Since you're already looping through the group ids you can instead use the value for the GroupId:
public function store(Request $request)
{
foreach ($request->input('GroupID') as $groupId) {
$storeInfo = new notice();
$storeInfo->GroupID = $groupId; //<--here
$storeInfo->Notice = $request->input('Notice');
$storeInfo->save();
}
return redirect('notice');
}
try changing controller logic
public function store(Request $request)
{
//
$member=$request->input('GroupID');
foreach($member as $value){
$storeInfo = new notice();
$storeInfo->GroupID = $value;
$storeInfo->Notice = $request->input('Notice');
$storeInfo->save();
}
return redirect('/notice');
}

Updating Item from Pivot Table Fields

I have item_color and item_size pivot tables, and would like to update my size and color fields using their field values, and an not exactly sure where to start. Here's what I have so far.
ItemSize.php
<?php
class ItemSize extends \Eloquent
{
protected $table = 'item_size';
protected $fillable = [];
public function item() {
return $this->belongsTo('Item');
}
}
ItemColor.php
<?php
class ItemColor extends \Eloquent
{
protected $table = 'item_color';
protected $fillable = [];
public function item() {
return $this->belongsTo('Item');
}
}
VendorController
public function postVendorUpdateItems ($id)
{
$input = Input::all();
$items = Item::find($id);
$validator = Validator::make($input,
[ 'item_name' => 'max:50',
'item_id' => 'max:50',
'normalprice' => 'numeric',
'karmaprice' => 'numeric',
'asin' => 'max:50',
]);
if($validator->passes())
{
$items->name = $input['item_name'];
$items->normalprice = $input['normalprice'];
$items->karmaprice = $input['karmaprice'];
$items->asin = $input['asin'];
$items->id = $input['item_id'];
$items->save();
return Redirect::route('account-vendor-index')
->with('global', 'You have updated your item.');
}
return Redirect::route('account-vendor-index')
->withErrors($validator)
->with('global', 'Your item could not be updated.');
}
View
<form class="form-horizontal" role="form" method="post" action="{{url('account/vendor/update/items')}}/{{$item->id}}">
<input type="hidden" id="brand_id" placeholder="brand_id" value="{{$brand->id}}" name="brand_id">
<input type="hidden" id="item_id" placeholder="item_id" value="{{$item->id}}" name="item_id">
<div class="form-group">
<label for="colors" class="col-xs-3 control-label">Colors</label>
<div class="col-xs-6">
<input type="text" class="form-control input-sm" id="colors" name="colors" placeholder="#foreach($item->colors as $color){{$color->color}}#endforeach" value="">
</div>
<button type="" class="btn btn-primary btn-sm">Add color</button>
<div class="clear"></div>
<div class="col-xs-offset-3 showColors">
#foreach($item->colors as $color)
{{$color->color}}
#endforeach
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Sizes</label>
<div class="col-xs-9">
<select id="selectSizes" multiple="multiple" class="form-control selectSizes" name="sizes">
<option value="XS (0-2)">XS (0-2)</option>
<option value="S (4-6)">S (4-6)</option>
<option value="M (8-10)">M (8-10)</option>
<option value="L (12-14)">L (12-14)</option>
<option value="XL (16-18)">XL (16-18)</option>
<option value="XXL (20-22)">XXL (20-22)</option>
</select>
</div>
</div>
<div class="form-group bot-0">
<div class="col-xs-offset-3 col-xs-9">
<button type="submit" class="btn btn-main btn-sm">Save changes</button>
</div>
</div>
</form>
item_size and item_color are not pivot tables. They are in fact a one to one relationship with your schema. If want you truly want are pivot tables, you need to define a color and a size table, then create a many-to-many relationship. See here: https://laravel.com/docs/master/eloquent-relationships
Then to update related models, you'll use the attach, sync, detach, etc. methods.
Also, what version of Laravel are you running? If you're running 5.1+ look into form request validation. See here: https://laravel.com/docs/master/validation#form-request-validation
That will remove all the validation logic from your controller.

Resources