'How can I save two results of the same id using vue-multiselect in Laravel?
I'm creating a Vue Laravel SPA and I have an employees and positions table. Then I'm trying to create a pivot table with many to many relationships between these tables. How can I save a record with the same employees_id if for example I have selected 2 selections in vue-multiselect to a pivot table?
Here's my employees table:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateEmployeesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('employees', function (Blueprint $table) {
$table->id()->unique();
$table->string('first_name', 50);
$table->string('middle_name', 50);
$table->string('last_name', 50);
$table->unsignedInteger('designation_id');
$table->unsignedInteger('position_id');
$table->string('address');
$table->dateTime('birthdate');
$table->dateTime('date_hired');
$table->decimal('basic_pay');
$table->string('cost_classification');
$table->string('sss_number', 25);
$table->string('philhealth_number', 25);
$table->string('pagibig_number', 25);
$table->string('emergency_contact_name');
$table->string('contact_number')->unique()->nullable();
$table->timestamps();
$table->timestamp('deleted_at')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('employees');
}
}
My employees model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\Positions;
class Employees extends Model
{
use HasFactory;
use SoftDeletes;
protected $table = 'employees';
protected $primaryKey = 'id';
public $timestamps = true;
protected $casts = ['basic_pay' => 'decimal:2'];
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'date_hired'];
protected $fillable = [
'first_name',
'last_name',
'designation_id',
'position_id',
'basic_pay',
'date_hired',
'cost_classification',
'sss_number',
'philhealth_number',
'pagibig_number',
'emergency_contact_name',
'contact_number'
];
public function positions()
{
return $this->hasMany(Positions::class);
}
}
My positions table:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePositionsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('positions', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->longText('description')->nullable();
$table->timestamps();
$table->timestamp('deleted_at')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('positions');
}
}
Positions model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\Employees;
class Positions extends Model
{
use HasFactory;
use SoftDeletes;
protected $table = 'positions';
protected $primaryKey = 'id';
public $timestamps = true;
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
protected $fillable = [
'name',
'description'
];
public function employees()
{
return $this->belongsToMany(Employees::class, 'employees_positions', 'employees_id', 'positions_id')
->withTimestamps();
}
}
My pivot employees_positions table:
Then my create-employee.vue:
<template>
<main>
<h3 class="text-2xl text-gray-800 font-bold leading-none mb-6">Create Employee</h3>
<div class="px-5 py-6 shadow-sm rounded-md bg-white">
<div class="row">
<div class="col-md-6">
<form @submit.prevent="addEmployee">
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="name">First Name</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" name="name" id="name" type="text" placeholder="First Name" tabindex="1" v-model="form.first_name" :class="form.errors.has('first_name')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('first_name')" v-html="form.errors.get('first_name')" />
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="name">Last Name</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" name="name" id="name" type="text" placeholder="Last Name" tabindex="2" v-model="form.last_name" :class="form.errors.has('last_name')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('last_name')" v-html="form.errors.get('last_name')" />
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="designation_id">Designation</label>
<div :class="form.errors.has('designation_id')?'border-2 border-red-600':''">
<multiselect
v-model="form.designation_id"
:options="designation_options.map(designation => designation.id)"
:custom-label="opt => designation_options.find(designation => designation.id == opt).name"
:multiple="true"
:taggable="true"
:tabindex="3"
></multiselect>
</div>
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('designation_id')" v-html="form.errors.get('designation_id')" />
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="position_id">Position</label>
<div :class="form.errors.has('position_id')?'border-2 border-red-600':''">
<multiselect
v-model="form.position_id"
:options="position_options.map(position => position.id)"
:custom-label="opt => position_options.find(position => position.id == opt).name"
:multiple="true"
:taggable="true"
:tabindex="4"
></multiselect>
</div>
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('position_id')" v-html="form.errors.get('position_id')" />
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="mb-4" style="width: 620px;">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="address">Address</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" rows="1" placeholder="" tabindex="5"></textarea>
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('address')" v-html="form.errors.get('address')" />
</div>
<div class="md:w-1/3 mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="birthdate">Birthdate</label>
<input type="date" name="birthdate" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" tabindex="6" v-model="form.birthdate" :class="form.errors.has('birthdate')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('birthdate')" v-html="form.errors.get('birthdate')" />
</div>
<div class="md:w-1/3 mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="date_hired">Date Hired</label>
<input type="date" name="date_hired" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" tabindex="7" v-model="form.date_hired" :class="form.errors.has('date_hired')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('date_hired')" v-html="form.errors.get('date_hired')" />
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-1/3 mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="sss_number">SSS Number</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" name="sss_number" id="sss_number" type="text" placeholder="SSS Number" tabindex="8" v-model="form.sss_number" :class="form.errors.has('sss_number')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('sss_number')" v-html="form.errors.get('sss_number')" />
</div>
<div class="md:w-1/3 mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="philhealth_number">Philhealth Number</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" name="philhealth_number" id="philhealth_number" type="text" placeholder="Philhealth Number" tabindex="9" v-model="form.last_name" :class="form.errors.has('philhealth_number')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('philhealth_number')" v-html="form.errors.get('philhealth_number')" />
</div>
<div class="md:w-1/3 mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="pagibig_number">Pagibig Number</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" name="pagibig_number" id="pagibig_number" type="text" placeholder="Pagibig Number" tabindex="10" v-model="form.pagibig_number" :class="form.errors.has('pagibig_number')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('pagibig_number')" v-html="form.errors.get('pagibig_number')" />
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="basic_pay">Basic Pay</label>
<div class="relative rounded">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="text-gray-700">₱</span>
</div>
<input class="shadow appearance-none border rounded w-full py-2 pl-8 pr-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" name="basic_pay" id="basic_pay" type="number" step="any" placeholder="00.00" tabindex="11" v-model="form.basic_pay" :class="form.errors.has('basic_pay')?'border-2 border-red-600':'border'" />
<div class="absolute inset-y-0 right-0 flex items-center"><label for="basic_pay" class="sr-only">Basic Pay</label>
</div>
</div>
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('basic_pay')" v-html="form.errors.get('basic_pay')" />
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="cost_classification">Cost Classification</label>
<div :class="form.errors.has('cost_classification')?'border-2 border-red-600':''">
<multiselect
v-model="form.cost_classification"
:options="cost_classification_options"
:multiple="false"
:taggable="false"
:tabindex="12"
></multiselect>
</div>
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('cost_classification')" v-html="form.errors.get('cost_classification')" />
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="emergency_contact">Emergency Contact</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" name="emergency_contact" id="emergency_contact" type="text" placeholder="Emergency Contact" tabindex="13" v-model="form.emergency_contact" :class="form.errors.has('emergency_contact')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('emergency_contact')" v-html="form.errors.get('emergency_contact')" />
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="contact_number">Contact Number</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" name="contact_number" id="contact_number" type="text" placeholder="Contact Number" tabindex="14" v-model="form.contact_number" :class="form.errors.has('contact_number')?'border-2 border-red-600':'border'" />
<p class="text-red-600 dark:text-red-500 text-sm" v-if="form.errors.has('contact_number')" v-html="form.errors.get('contact_number')" />
</div>
</div>
<button type="submit" class="sm:hidden md:flex bg-blue-500 hover:bg-blue-400 text-white font-bold py-2 px-4 border-b-4 border-blue-700 hover:border-blue-500 rounded outline-none focus:outline-none">Create</button>
</form>
</div>
</div>
</div>
</main>
</template>
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
<script>
import Form from 'vform'
import Multiselect from 'vue-multiselect'
export default {
components: { Multiselect },
data: () => ({
errors: {},
form: new Form({
designation_id: [],
position_id: [],
cost_classification: []
}),
designation_options: [],
position_options: [],
cost_classification_options: ['Direct Labor', 'Indirect Labor', 'General & Admin']
}),
methods: {
addEmployee() {
this.form
.post('/api/employees', this.form)
.then(res => {
this.$swal({
title: 'Are you sure?',
text: 'Do you want to save this record?',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, save it!'
}).then((result) => {
if (result.isConfirmed) {
this.$router.push({ name: 'employees' })
this.$swal(
'Good job!',
'You save the record!',
'success'
)
}
});
})
.catch(err => console.log(err));
},
getDesignationNames() {
this.axios.get('/api/designations').then((res) => {
this.designation_options = res.data;
}).catch(err => console.log(err));
},
getPositionNames() {
this.axios.get('/api/positions').then((res) => {
this.position_options = res.data;
}).catch(err => console.log(err));
},
},
created: function() {
this.getDesignationNames();
this.getPositionNames();
}
}
</script>
Solution 1:[1]
You should just find position model and use attach() or sync() as bellow:
$position->employees()->sync([array_of_employees]);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Farshid Ghiasimanesh |
