Create and Insert Many-to-Many Relationships in Laravel - php

First of all, i'm a beginner and trying to learn all i can. So if i have mistakes please correct me.
So, i am working on a laravel project. I've got two models; drugs and interactions. What i am struggling is, I want to add two drugs and one interaction in one form. But also, i want to check if the drug has inserted already to avoid duplicate data.
Here are my models:
class Drug extends Model
{
//Table Name
protected $table = 'drugs';
//Primary Key
public $primaryKey = 'id';
//Timestamps
public $timestamps = true;
//relationship
public function interactions()
{
return $this->belongsToMany('App\Interaction', 'drug_interaction', 'interaction_id', 'drug_id');
}
}
class Interaction extends Model
{
//Table Name
protected $table = 'interactions';
//Primary Key
public $primaryKey = 'id';
//Timestamps
public $timestamps = true;
//Relationship
public function drugs()
{
return $this->belongsToMany('App\Drug', 'drug_interaction', 'drug_id', 'interaction_id');
}
}
And this is simply the store function in my DrugsController
public function store(Request $request)
{
$this->validate($request, [
'name'=> 'required',
'info'=> 'nullable'
]);
//create drug
$drug = new Drug;
$drug->name = $request->input('name');
$drug->info = $request->input('info');
$drug->save();
return redirect('/drugs')->with('success', 'İlaç Eklendi');
}
And this is my InterationsController's store function.
public function store(Request $request)
{
$this->validate($request, [
'name'=> 'required',
'description'=> 'required',
'category'=> 'nullable'
]);
//create interaction
$interaction = new Interaction;
$interaction->name = $request->input('name');
$interaction->description = $request->input('description');
$interaction->category = $request->input('category');
$interaction->save();
I can attach relationships via artisan tinker so i think relationship works. But i stuck when it comes to multiple input forms goes to different controllers. But using static id's. I need to make it variables. But two drugs should be attached to one interaction. So i couldn't succeed pasing two variables from form at the same time.
In dumb words, what i am trying to achieve is;
request drug_name_one from form's first textbox. Check db for that drug name, if exists; get its id. If it doesn't then create one and get id.
request drug_name_two from form's second textbox. Do the same as step one.
create an interaction as typed in form's third text box.
attach them.
PS: after this attach() work done, i also couldn't find a way to search for two drugs if they have a common interaction. If you can also mention a few tips to achieve that i'll be grateful.
All help and further reading advices appreciated. Thanks All !
Edit:
This is the create_interactions migration.
Schema::create('interactions', function (Blueprint $table) {
$table->BigIncrements('id');
$table->string('name');
$table->string('description');
$table->string('category');
$table->timestamps();
});
}
This is the input for 'category' field:
<div class="form-group">
{{Form::label('category', 'Kategori')}}
{{Form::text('category', '', ['class' => 'form-control', 'placeholder' => 'Etkileşim Kategorisi'])}}
</div>
I couldn't make the structure of a form as i desired btw. It's just the form for creating interactions by itself without relationship.

Here is the solution. It is working well now.
First of all i was trying to assign 2 drugs to one interaction. So i've imported select2 and used this "select" form to list the drugs and chose multiple from them:
<div class="form-group">
{!! Form::label('İlaçları Seçin') !!}
{!! Form::select('drugs[]', $drugs, null, ['multiple' => 'multiple', 'class' => 'form-control drugs']) !!}
</div>
On the InteractionsController:
$interaction = new Interaction;
$interaction->name = $request->input('name');
$interaction->description = $request->input('description');
$interaction->category = $request->input('category');
$interaction->save();
$interaction->drugs()->sync($request->drugs, false);
But i also wanted to show and edit those drugs assigned to the specific interaction. So on the edit.blade.php form there is this script:
<script type="text/javascript">
$('.drugs').select2().val({!! json_encode($interaction->drugs()->allRelatedIds()) !!}).trigger('change');
</script>
This script, calls the related drugs to the selected interaction in the same form as i used in create.blade.

Related

How to add pivot table when inserting data to database in Laravel 8

maybe someone know how to insert pivot table in Laravel 8 automatically every i insert counselings table?
I have Model Counseling n to n Problem,
Input form
counselings table
problems table
Counselings Model
Problem Model
Controller
public function create()
{
return view('admin.counseling.create', [
'title' => 'Tambah Bimbingan dan Konseling',
'students' => Student::all(),
'problems' => Problem::all()
]);
}
public function find_nis(Request $request)
{
$student = Student::with('student_class', 'counselings')->findOrFail($request->id);
return response()->json($student);
}
public function store(Request $request)
{ dd($request->all());
$counseling = new Counseling();
$counseling->student_id = $request->student_id;
$counseling->user_id = Auth::user()->id;
$counseling->save();
if ($counseling->save()) {
$problem = new Problem();
$problem->id = $request->has('problem_id');
$problem->save();
}
}
You can insert into a pivot table in a few different ways. I would refer you to the documentation here.
Attaching
You may use the attach method to attach a role to a user by inserting
a record in the relationship's intermediate table:
Example:
$problem->counselings()->attach($counseling->id);
Sync
You may also use the sync method to construct many-to-many
associations. The sync method accepts an array of IDs to place on the
intermediate table. Any IDs that are not in the given array will be
removed from the intermediate table.
Example:
$problem->counselings()->sync($counselingsToSync);
Toggle
The many-to-many relationship also provides a toggle method which
"toggles" the attachment status of the given related model IDs. If the
given ID is currently attached, it will be detached. Likewise, if it
is currently detached, it will be attached:
Example:
$problem->counselings()->toggle($counselingsToToggle);
I would change your store() method to something like this :
public function store(Request $request)
{
$counseling = Counseling::create([
'student_id' => $request->student_id,
'user_id' => Auth::user()->id
]);
if($request->has('problem_id'){
$counseling->problems()->attach($request->problem_id);
//return something if problem id is in request
}
//return something if problem id is not there
}

Saving relations in Laravel

I've got table Competitions and Competition_categories. Their relationship is
competitions.id = competition_categories.competition_id. I can create new competition with no problem but the Competition_categories is not saving any related records. My models:
Competition Model:
public function competition_category()
{
return $this->hasMany(CompetitionCategory::class, 'competition_id', 'id');
}
CompetitionCategory Model
public function competition()
{
return $this->belongsTo( Competition::class, 'competition_id' );
}
My Controller code - store method:
$request->validate([
'name' => 'required',
'frequency' => 'required|integer',
]);
$competition = Competition::create($request->all());
$competition_category = CompetitionCategory::create($request->all());
$competition_category->competition()->associate($competition);
$competition_category->save();
I've checked the documentation and other related questions but did not manage to get it working can you help me?
I'm expecting when I create new competitions new records to be saved in both tables. (New competitions are created successfully but no records in the category table. Also, one competition can have more than one category)
i can see a problem in your controller class, Laravel would advice not to create a class for pivot table, first you will need to update your question for better clarification, however here is a senerio and how to approach this.
Tables
Competition,
Categories,
Category_competition (pivot table)
reference for you
Competition Model:
public function category()
{
return $this->belongsToMany(Category::class, 'Category_competition','competition_id', 'category_id')->withPivot(['pivot attributes here']);
}
Category Model:
public function compitition()
{
return $this->belongsToMany(Compitition::class, 'Category_competition', 'category_id;'competition_id', 'id');
}
Then
$request->validate([
'name' => 'required',
'frequency' => 'required|integer',
]);
$competition = Competition::create($request->all());
$competition->category()->attach($category_attributes = []);

How to use 1 form to insert into multiple tables using Laravel

I have a form page for storing recording data of a specific artist. Most data belongs to the recording table but some data should be stored in related tables. My main concern right now is the Genre table. In the genre table I have the Name column. My idea of the ideal process after the form has been submitted is something like:
Check if the genre name already exists
If not: store the name and use its id as a fk
If yes: fetch genre id and use it as a fk
What I am working on is the store method in the Recording controller. Currently I am working with
$recording_date, $release_date and $lyrics from the recording table.
DISCLAIMER:
I will not show you much of what I've tried because cannot show you all the ways I've tried and it's also useless cause the problem isn't that I don't understand why it isn't working. I just can't find any way at all to do it properly with Eloquent that includes the same constraints and with a 1-to-many relation. Most people would suggest me to do it in separate forms.
Also I'm aware of that I'm not handling the validation right now.
Anyway, any ideas or suggestions where I can find information of similar cases applicable on mine would help.
<!--Form snippet-->
<div class="form-group">
<div class="input-group">
<input type="text" name="genre" class="form-control" placeholder="Genre" autocomplete="off">
</div>
</div>
The following was the latest piece of code I tried. The obvious reason why it doesn't work is that it doesn't deal with the foreign key.
//Recording controller
public function store(Request $request)
{
$genre = new Genre();
$genre->name = $request->input('genre');
$recording = new Recording();
$recording->genre_id = $genre->id;
$recording->recording_date = $request->input('recording_date');
$recording->release_date = $request->input('release_date');
$recording->lyrics = $request->input('lyrics');
$recording->save();
}
//Recording table
public function up()
public function up()
{
Schema::create('recordings', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('genre_id')->nullable();
$table->string('recording_date')->nullable();
$table->string('release_date')->nullable();
$table->text('lyrics')->nullable();
$table->timestamps();
});
}
//Genres table
public function up()
{
Schema::create('genres', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->unique()->nullable();
$table->string('subgenre')->nullable();
$table->timestamps();
});
}
//Recording model
class Recording extends Model
{
protected $guarded = [];
public function genre() {
return $this->belongsTo(Genre::class);
}
}
//Genre model
class Genre extends Model
{
protected $guarded = [];
public function recordings() {
return $this->hasMany(Recording::class);
}
}
In order to save onto relationship tables you have to do:
$recording->genre()->create('your data array here')
you can read more about it here.
Now if you want to check it out if that $recording has an genre you could first use exists() like:
$recording->genre()->exists()
Another option would be to use the methods firstOrCreate, firstOrNew, you can read more about them here.
Please try this
....
$genre->save();
$genre->recordings()->create([
"recording_date"=>$request->input('recording_date'),
"release_date"=>$request->input('release_date'),
"lyrics"=>$request->input('lyrics')
]);

Form Update Database Model Record's Relationship

I want to know how to up date a model's relationship using a frontend form. I looked at the documents and found:
Alternatively you may set the relationship using the primary key, this
is useful when working with HTML forms.
// Assign to author with ID of 3
$post->author = 3;
// Assign comments with IDs of 1, 2 and 3
$post->comments = [1, 2, 3];
$post->save();
the backend form to update the relationship works fine. This is my code and where I am getting ID as a value but it doesn't seem to affect the relationship field. Help would be great thanks!
$project = new Projects();
$project->name = Input::get('name');
$project->price = Input::get('price');
$project->work = Input::get('work');
$project->client = Input::get('client');
$project->slug = $slug;
$project->save();
Flash::success('Estimate Added!');
return Redirect::refresh();
This is the Pivot Table:
public function up()
{
Schema::create('brandon_invoice_ip', function($table)
{
$table->engine = 'InnoDB';
$table->integer('invoices_id');
$table->integer('projects_id');
$table->primary(['invoices_id','projects_id']);
});
}
public function down()
{
Schema::dropIfExists('brandon_invoice_ip');
}
}
Here is the model relationship:
public $hasOne = [
'client' => 'Brandon\Invoice\Models\Clients'
];
This is the front end form: The values are correct according to their ID.
<div class="uk-margin uk-first-column">
<label class="uk-form-label" for="client">Client</label>
<div class="uk-form-controls">
<select class="uk-select" name="client">
<option value="1">Brandon</option>
<option value="2">Sanitary Ostomy System</option>
</select>
</div>
</div>
Image of the relationship in the builder.
I think you need to add belongsTo relationship instead of hasOne
public $belongsTo = [
'client' => 'Brandon\Invoice\Models\Clients'
];
After you set the client using:
$project->client = Input::get('client');
You need to save the changes using:
$project->save();
Assuming your tables and models have been setup correctly, the above should work. If it does not, you need to post the structure of your tables and the rest of your code.

error occured when save data using hasmany relationnship in laravel

Create hasmany relatioship in vehicle model and insert data in vehicle and vehicle_staff table. data successfully insert in vehicle table but when store in vehicle_staff following error appear.
Error Comes:
Type error: Argument 1 passed to
Illuminate\Database\Eloquent\Relations\HasOneOrMany::save() must be an
instance of Illuminate\Database\Eloquent\Model, array given, called in
E:\xampp\htdocs\laravel-projects\collegeaccounting\app\Http\Controllers\Transport\VehicleController.php
on line 53
Vehicle Staff Table Schema:
Schema::create('vehicle_staffs', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->unsignedInteger('vehicles_id');
$table->unsignedInteger('staffs_id');
$table->boolean('status')->default(1);
});
Has Many Relationship on Vehicle Model:
class Vehicle extends BaseModel
{
protected $fillable = ['created_by', 'last_updated_by', 'number', 'type', 'model', 'description', 'status'];
public function staff(){
return $this->hasMany(Staff::class);
}
}
Store Function:
public function store(AddValidation $request)
{
$request->request->add(['created_by' => auth()->user()->id]);
$vehicle = Vehicle::create($request->all());
if ($request->has('staffs_id')) {
$staffs = [];
foreach ($request->get('staffs_id') as $staff) {
$staffs[$staff] = ([
'vehicles_id' => $vehicle->id,
'staffs_id' => $staff
]);
}
$vehicle->staff()->save($staffs);
}
$request->session()->flash($this->message_success, ' Created Successfully.');
return redirect()->route($this->base_route);
}
It seems you are creating many to many relationships, that is to say, a vehicle can belongs to many staffs, and a staff can have many vehicles. So, vehicle_staffs is a intermediate table (or pivot table) between vehicle model and staff model.
For Vehicle model, you should change the staff method to:
public function staff(){
return $this->belongsToMany(Staff::class, 'vehicle_staffs', 'vehicles_id', 'staffs_id');
}
To update many to many relationships, you can attach the staff ids to vehicle:
$vehicle->staff()->attach($staffIds);
and the code change of your store function:
if ($request->has('staffs_id')) {
$staffIds = $request->get('staffs_id');
$vehicle->staff()->attach($staffIds);
}
I don't know what version of Laravel you are using, so I assume you are on Laravel 5.x.
You should probably use saveMany() if you want to save more than one object. It takes a Collection or an array of Models as a parameter.
From the documentation:
If you need to save multiple related models, you may use the saveMany method:
$post = App\Post::find(1);
$post->comments()->saveMany([
new App\Comment(['message' => 'A new comment.']),
new App\Comment(['message' => 'Another comment.']),
]);

Categories