Laravel update makes new table rule instead of updating - php

I have a company table and an attributes table with all sorts of value in it.
One company hasMany attributes and an attribute belongsTo a company.
Now I have a value inside the attributes table with a 'account_nr_start' (for example, when a new user is added to a company its account_id starts counting up from 1000).
Controller:
public function __construct(Company $company, User $user)
{
if(Auth::user()->usertype_id == 7)
{
$this->company = $company;
}
else
{
$this->company_id = Auth::user()->company_id;
$this->company = $company->Where(function($query)
{
$query->where('id', '=', $this->company_id )
->orWhere('parent_id','=', $this->company_id);
}) ;
}
$this->user = $user;
$this->middleware('auth');
}
public function edit(Company $company, CompaniesController $companies)
{
$companies = $companies->getCompaniesName(Auth::user()->company_id);
$attributes = $company->attributes('company')
->where('attribute', '=', 'account_nr_start')
->get();
foreach ($attributes as $k => $v) {
$nr_start[] = $v->value;
}
return view('company.edit', ['company' => $company, 'id' => 'edit', 'companies' => $companies, 'nr_start' => $nr_start]);
}
public function update(UpdateCompanyRequest $request, $company, Attribute $attributes)
{
$company->fill($request->input())->save();
$attributes->fill($request->only('company_id', 'attribute_nr', 'value'))->save();
return redirect('company');
}
HTML/Blade:
<div class="form-group {{ $errors->has('_nr_') ? 'has-error' : '' }}">
{!! HTML::decode (Form::label('account_nr_start', trans('common.account_nr_start').'<span class="asterisk"> *</span>', ['class' => 'form-label col-sm-3 control-label text-capitalize'])) !!}
<div class="col-sm-6">
{!! Form::text('value', $nr_start[0], ["class"=>"form-control text-uppercase"]) !!}
{!! $errors->first('account_nr_start', '<span class="help-block">:message</span>') !!}
</div>
</div>
When I update a company now, it will upload like the last input here: :
So it makes a new rule, while it needs to edit the current attribute rule instead of making a new rule with an empty company_id/attribute.

If I understand what you are trying to do, I think this will fix your problem. The issue you have is the Attribute model is a new instance of the model rather than retrieving the model you need.
before running fill() from the attributes method try this
$new_attribute = $attributes->where('company_id', '=', $company->id)->where('attribute', '=', 'account_nr_start')->first();
Then run the fill()
$new_attribute->fill($request->only('company_id', 'attribute_nr', 'value'))->save();

Related

Laravel 6 - `Undefined variable: value` only error in the first time

In the first time I want to save data to database from table this error appear.
ErrorException
Undefined variable: value
so I have to manually input the data from tinker or mysql
My Controller
public function store(Request $request)
{
$validateData = $request->validate([
'name_device_type' => 'required|max:255',
'signature' => 'Nullable'
]);
$id = DeviceType::getidDeviceTypes();
foreach ($id as $value); // Error happend in this line.
$lastdevicetypeId = $value->id;
$newdevicetypeId = $lastdevicetypeId + 1;
$GetnewdevicetypeId = sprintf('DT%04d', $newdevicetypeId);
$devicetypes = new DeviceType();
$devicetypes->idDeviceType = $GetnewdevicetypeId;
$devicetypes->name_device_type = $request->input('name_device_type');
$devicetypes->signature = $request->input('signature');
$devicetypes->save();
return redirect('/devicetypes')->with('success', 'New Device Type is added');
}
My Migration table
public function up()
{
Schema::create('device_types', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('idDeviceType');
$table->string('name_device_type');
$table->mediumText('signature');
$table->timestamps();
});
}
My create.blade.php
{!! Form::open(['action' => 'DeviceTypesController#store', 'method' => 'POST']) !!}
<div class="form-group">
{!! Form::label('name_device_type', 'Type Device'); !!}
{!! Form::text('name_device_type', '', ['class' => 'form-control', 'placeholder' => 'Type Device']); !!}
</div>
<div class="form-group">
{!! Form::label('signature', 'Signature (Optional)'); !!}
{!! Form::textarea('signature', '', ['id' => 'classic-ckeditor5', 'class' => 'form-control', 'placeholder' => 'Signature']); !!}
</div>
{{ Form::button('<i class="far fa-save"></i> Submit', ['type' => 'submit', 'class' => 'btn btn-info'] ) }}
{!! Form::close() !!}
the Model
class DeviceType extends Model
{
// Table Name
protected $table = 'device_types';
// Primary Key
protected $primaryKey = 'idDeviceTypes';
// Timestamps
public $timestamps = true;
public $incrementing = false;
public static function getidDeviceType(){
return $getidDeviceType = DB::table('device_types')->orderBy('id','desc')->take(1)->get();
}
}
But if the table has data this error disappear, also this error will appear again if I remove every data and made the table empty.
You have a Semicolon right after the foreach loop definition: foreach ($id as $value);
and you are using the $value in the next line $lastdevicetypeId = $value->id; which is outside the scope of your loop.
You should remove the ; following the the foreach loop and change it to : and add a endforeach; where you want to end the loop.
Example:
foreach ($id as $value):
$lastdevicetypeId = $value->id;
$newdevicetypeId = $lastdevicetypeId + 1;
$GetnewdevicetypeId = sprintf('DT%04d', $newdevicetypeId);
$devicetypes = new DeviceType();
$devicetypes->idDeviceType = $GetnewdevicetypeId;
$devicetypes->name_device_type = $request->input('name_device_type');
$devicetypes->signature = $request->input('signature');
$devicetypes->save();
endforeach;
Or you can write this code as:
foreach ($id as $value){
$lastdevicetypeId = $value->id;
$newdevicetypeId = $lastdevicetypeId + 1;
$GetnewdevicetypeId = sprintf('DT%04d', $newdevicetypeId);
$devicetypes = new DeviceType();
$devicetypes->idDeviceType = $GetnewdevicetypeId;
$devicetypes->name_device_type = $request->input('name_device_type');
$devicetypes->signature = $request->input('signature');
$devicetypes->save();
}
You could grab the max 'id' of the table and add 1 to it without having to grab a whole record:
...
// validation
$newdevicetypeId = DeviceType::max('id') + 1;
$GetnewdevicetypeId = sprintf('DT%04d', $newdevicetypeId);
// new DeviceType
...
There is the option of having a model event that can set this particular field after the record has been created so it has its own id to use.

How to pass $id of a form to another form

I have multiple forms where I need to pass through the id. In the example bellow I have 2 controllers one is for Courses and one is for the Exams. I'm trying to create a course and then pass through the course id to the exam form.
Here is what I've tried but the value is not passing through.
Course Controller:
public function store(StoreCoursesRequest $request)
{
if (! Gate::allows('course_create')) {
return abort(401);
}
$request = $this->saveFiles($request);
$course = Course::create($request->all()
// $status = array('assigned' => 'assigned', 'canceled'=>'canceled');
+ ['position' => Course::where('curriculum_id', $request->curriculum_id)->max('position') + 1]);
$trainers = \Auth::user()->isAdmin() ? array_filter((array)$request->input('trainers')) : [\Auth::user()->id];
$course->trainers()->sync($trainers);
$course->roles()->sync(array_filter((array)$request->input('roles')));
$course->assigned_user()->sync(array_filter((array)$request->input('assigned_user')));
$curriculum = Curriculum::get(array('id' => 'id'));
$exam = Exam::get(array('id' => 'id'));
foreach ($request->input('course_materials_id', []) as $index => $id) {
$model = config('medialibrary.media_model');
$file = $model::find($id);
$file->model_id = $course->id;
$file->save();
}
session('id', 'id');
return redirect()->route('admin.exams.create');
}
Here is the exams controller
public function create()
{
if (! Gate::allows('exam_create')) {
return abort(401);
}
$exam_assigneds = \App\Exam::get()->pluck('title', 'id')->prepend(trans('global.app_please_select'), '');
$questions = \App\ExamQuestion::get()->pluck('question', 'id');
$in_classes = \App\InClassCourse::get()->pluck('title', 'id')->prepend(trans('global.app_please_select'), '');
$reoccurance_type = \App\ReoccuranceType::get()->pluck('type', 'id')->prepend(trans('global.app_please_select'), '');
$courses = session('id');
return view('admin.exams.create', compact('courses', 'exam_assigneds', 'questions', 'in_classes', 'reoccurance_type'));
}
Here is the view
<div class="row">
<div class="col-xs-12 form-group">
{!! Form::label('course_id', trans('global.exam.fields.course').'', ['class' => 'control-label']) !!}
{!! Form::text('id', $courses, old('id'), ['class' => 'form-control', 'placeholder' => '']) !!}
<p class="help-block"></p>
#if($errors->has('course_id'))
<p class="help-block">
{{ $errors->first('course_id') }}
</p>
#endif
</div>
</div>
All I'm getting is just text value of id. It doesn't pull the actual id.
In Course Controller modify
session('id', 'id');
to
session('id', $course->id);

Laravel Model binding many to many realtionship does not populate data

I have two tables with a many to many relation (Project and Center, the pivot table is ProjectCenter).
These are my models:
Project:
class Project extends Model {
public function centers()
{
return $this->belongsToMany('App\Models\Center', 'ProjectCenter', 'IDProject', 'IDCenter');
}
public function getCenterListAttribute()
{
return $this->centers->lists('IDCenter')->all();
}
}
Center:
class Center extends Model {
public function projects()
{
return $this->belongsToMany('App\Models\Project', 'ProjectCenter', 'IDCenter', 'IDProject');
}
}
Controller -> edit:
public function edit($id)
{
$project = Project::find($id);
$centerList = Center::lists('Name', 'IDCenter')->toArray();
return view('project/add', array('centerList' => $centerList))->with('project', $project);
}
And the view:
{!! Form::label('centers_list', 'Center*') !!}
{!! Form::select('centers_list[]',
$centerList,
null,
array(
'class' => 'form-control ',
'required' => 'required',
'multiple' => true,
'data-placeholder' =>
'Select a center'
)
) !!}
But I can not select the data already stored previously.
For example: the project 8 (IDProject) has two centers (1 and 2) but the data is not populated in the multiple select:
What am I doing wrong?
You all time get same result $centerList = Center::lists('Name', 'IDCenter')->toArray(); but you must be get product centers using query with model.
$project = Project::with("centers:Name,IDCenter")->find($id);
$centerList = $project->centers->pluck('Name', 'IDCenter')->toArray();
I already solve the problem using a foreach to select the related centers:
<select multiple="multiple" name="centers[]" id="centers" class="form-control select2" required="required" data-placeholder="Select a center">
#if($centerList)
#foreach($centerList as $key => $center)
<option value="{{$key}}" {{ (collect($selectedCenters)->contains($key)) ? "selected='selected'" : '' }} >{{$center}}</option>
#endforeach
#endif
</select>

How to add records to a pivot table in Laravel

I have a user, student and subject model and I want to register a student into many subjects. So I created a StudentRegistration controller and in my create view I show all the subjects that belong to the course of the current logged in user.
StudentRegistration.php create function
public function create()
{
$user_id = Auth::user()->id;
$student_id = Student::where('user_id', $user_id)->first();
$course = $student_id->course->id;
$subjects = Subject::where('course_id', $course)->get();
return view('student.create', compact('subjects'));
}
In the create template I show all the subjects as checkbox because a user can register for multiple subjects.
{!! Form::open(['method' => 'POST', 'action'=>'StudentRegistration#store', 'files'=>true]) !!}
#foreach($subjects as $subject)
<div class="label-box">
{!! Form::label('name', $subject->name) !!}
{!! Form::checkbox('subject_id[]', $subject->id, null, ['class'=>'form-control']) !!}
</div>
#endforeach
<div class="form-group">
{!! Form::submit('Create User', ['class'=>'btn btn-primary']) !!}
</div>
{!! Form::close() !!}
I have this in my Student.php for the many to many relationship:
public function subjects()
{
return $this->belongsToMany('App\Subject');
}
I created a pivot table named Student_Subject. So, during the store, how can I save all the selected subjects into pivot table (student_subject).
I tried using this:
public function store(Request $request)
{
$data = $request->except('_token');
$subject_count = count($data['subject_id']);
for($i=0; $i < $subject_count; $i++){
$student = Student::where('user_id', Auth::user()->id);
$student->subjects()->attach($data['subject_id'][$i]);
}
}
But I get the following error:
"Method Illuminate\Database\Query\Builder::subjects does not exist."
And how can I view all the course subjects which the student is not registered at?
I have this:
Route::get('/studentsubjects', function(){
$student_id = Student::where('user_id', Auth::id())->first();
$course = $student_id->course->id;
$subjects = $student_id->subjects;
echo 'Registered at' .'<br>';
foreach ($subjects as $registered) {
echo $registered->name .'<br>';
}
$unregistered = Subject::where('course_id', $course)->except($subjects);
});
And see this error:
"Method Illuminate\Database\Query\Builder::except does not exist."
$student = Student::where('user_id', Auth::user()->id);
is not enough to get the Student model, you're only getting the query object here.
In order to actually get the student, use the following:
$student = Student::where('user_id', Auth::user()->id)->first();
Even better if user_id is the primary key for your model Student:
$student = Student::find(Auth::user()->id);
As a side note, you can access directly the user ID from the Auth interface using Auth::id() instead of Auth::user()->id, resulting in:
$student = Student::find(Auth::id());

SQLSTATE[23000] Integrity constraint violation: 1452 in a many-to-many relationship in laravel 5.3

I've got a BlogPost Controller which has a user form that takes inputs from the user through the create() method. Then that form redirects to the store method on the same controller. The problem I'm facing is with the many-to-many relationship. BlogPost model has a many-to-many relationship with the BlogTag model. I'm taking input from a user through checkboxes. The user can choose multiple radio buttons associated with individual tags (form code has been posted below). Everything seems to work fine, but when I'm trying to attach all the tag ids to the post instance in my store() method. I get the error that is shown below. I've looked through all the available solutions on the internet but nothing seems to work for my case. The store method has also been posted below.
QueryException in Connection.php line 761: SQLSTATE[23000]: Integrity
constraint violation: 1452 Cannot add or update a child row: a foreign
key constraint fails (erp_system_solution.posts_tags, CONSTRAINT
posts_tags_ref_tag_id_foreign FOREIGN KEY (ref_tag_id) REFERENCES
blog_tags (tag_id) ON DELETE CASCADE ON UPDATE CASCADE) (SQL:
insert into posts_tags (ref_post_id, ref_tag_id) values (2, 34),
(7, 34), (8, 34), (15, 34))
Form for posting a BlogPost
{{Form::open(array(
'action' => 'Blog\BlogPostController#store',
'class' => 'form-horizontal',
'method' => 'POST',
))}}
{{ Form::hidden('user_id', Auth::user()->user_id) }}
<div class="form-group">
{{ Form::label("post_title", "Post Title", array("class" => "col-sm-2 control-label")) }}
{{ Form::text ("post_title", "", array("class" => "col-sm-6")) }}
</div>
<div class="form-group">
{{ Form::label("post_body", "Post Body", array("class" => "col-sm-2 control-label")) }}
{{ Form::textarea("post_body", "", array("class" => "col-sm-6 col-sm-offset-2 top-info-panels", "rows" => "16", "columns" => "2")) }}
</div>
<div class="form-group">
{{ Form::label("published", "Publish Blog Post", array("class" => "col-sm-2 control-label")) }}
{{ Form::radio("published", "Yes", true) }} Yes
{{ Form::radio("published", "No") }} No
</div>
<div class="form-group">
{{ Form::label("category_id", "Choose a Category", array("class" => "col-sm-2 control-label")) }}
{{ Form::select("category_id", $categories, '-----Choose Any One-----') }}
</div>
<div class="form-group">
{{ Form::label("tag_id", "Choose Appropriate Tags", array("class" => "col-sm-2 control-label")) }}
<div class="col-sm-offset-2">
#for($i=1; $i<count($tags)+1; $i++)
{{ Form::checkbox("tag_id[]", $i), array("class" => "col-sm-offset-2 col-sm-10") }} {{ $tags[$i] }}
#endfor
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
{{Form::submit('Create Post', array("class" => "btn btn-warning"))}}
</div>
</div>
{{Form::close()}}
BlogPostModel
<?php
namespace App;
use App\PostsTagsPivot as Pivot;
use App\BlogCategory;
use App\BlogTag;
use App\Comment;
use App\RegisteredUser;
use Illuminate\Database\Eloquent\Model;
class BlogPost extends Model
{
public $timestamps = true;
protected $table = 'blog_posts';
protected $primaryKey = 'post_id';
protected $fillable = ['post_title', 'post_body', 'published', 'registered'];
public function post_category() {
return $this->belongsTo(BlogCategory::class, 'category_id');
}
public function posts_with_tags() {
return $this->belongsToMany(BlogTag::class, 'posts_tags', 'ref_tag_id', 'ref_post_id');
}
public function comments() {
return $this->hasMany(Comment::class, 'comment_id');
}
public function posts_author() {
return $this->belongsTo(RegisteredUser::class, 'user_id');
}
}
BlogPostController
public function store(Request $r) {
$u_id = $this->user::find((int)$r->input('user_id'));
$cat_id = $this->category::find((int)$r->input('category_id'));
$tag_id = $r->input('tag_id');
$role = $this->user::find((int)$r->input('user_id'))->has_role($u_id);
$registered = ($role == 'super_admin') ? true : false;
$published = ($r->input('published') == 'Yes') ? true : false;
$create_post = $this->blog_posts::create(['post_title' => $r->input('post_title'), 'post_body' => $r->input('post_body'), 'published' => $published, 'registered' => $registered]);
$create_post->save();
$create_post->posts_with_tags()->attach($tag_id);
$create_post->save();
$create_post->posts_author()->associate($u_id);
$create_post->save();
$create_post->post_category()->associate($cat_id);
if($create_post->save()) return redirect()->route('blog_post.create')->with('post_saved', 'Your post has been saved');
else return redirect()->route('blog_post.create')->with('post_not_saved', 'Something went wrong');
}
BlogTagModel
<?php
namespace App;
use App\BlogPost;
use Illuminate\Database\Eloquent\Model;
class BlogTag extends Model
{
public $timestamps = true;
protected $table = 'blog_tags';
protected $primaryKey = 'tag_id';
protected $fillable = ['tag_name', 'post_id', 'tag_id'];
public function tags_on_posts() {
return $this->belongsToMany(BlogPost::class, 'posts_tags', 'ref_tag_id', 'ref_post_id');
}
}
Migration for a pivot table joining BlogPost with BlogTag
public function up()
{
Schema::create('posts_tags', function ($table) {
$table->integer('ref_tag_id')->unsigned()->index();
$table->foreign('ref_tag_id')->references('tag_id')->on('blog_tags')->onDelete('cascade')->onUpdate('cascade');
$table->integer('ref_post_id')->unsigned()->index();
$table->foreign('ref_post_id')->references('post_id')->on('blog_posts')->onDelete('cascade')->onUpdate('cascade');
});
}
Well, I figured it out. The solution is to change the ordering in posts_with_tags() action/method
It was:
public function posts_with_tags() {
return $this->belongsToMany(BlogTag::class, 'posts_tags', 'ref_tag_id', 'ref_post_id');
}
It should be:
public function posts_with_tags() {
return $this->belongsToMany(BlogTag::class, 'posts_tags', 'ref_post_id', 'ref_tag_id');
}

Categories