Storing data to multiple tables from single form in laravel - laravel

My schemas are:
Schema::create('persons', function (Blueprint $table) {
$table->bigInteger('university_id')->unique()->unsigned();
$table->string('category');
$table->string('name');
$table->timestamps();
});
Schema::create('teachers', function (Blueprint $table) {
$table->increments('teacher_id');
$table->bigInteger('university_id')->unsigned();
$table->string('position');
$table->string('courses');
$table->integer('salary');
$table->timestamps();
});
Schema::create('students', function (Blueprint $table) {
$table->increments('student_id');
$table->bigInteger('university_id')->unsigned();
$table->string('year');
$table->string('semester');
$table->string('programme');
$table->integer('rollNum');
$table->timestamps();
});
I have a two forms with fields:
For Teachers:University ID, Name, Category, Position, Courses, Salary
For Students:University ID, Name, Category, Year, Semester, Programme, Roll Number
I tried to store data in the database through my controller in single method as follows:
After requesting all data into variables from form, I tried to store data in the following way.
University::create([
'university_id' =>$universityID,
'category' => $category,
'name' => $name
]);
//I passed values of category as Teacher when submitting from teacher form
//and Student while submitting student form.
if($category == 'Teacher'){
Teacher::create([
'university_id' => $universityID,
'position' => $position,
'courses' => $course,
'salary' => $salary
]);
}
if($category == 'Student'){
Student::create([
'university_id' => $universityID,
'year' => $year,
'semester' => $semester,
'programme' => $programme,
'rollNum' => $roll
]);
}
When i submitted Teacher's form, I was expecting that data will be stored in University and Teachers table only and it did. But there was an unexpected problem occurred. The Student table was filled with Null values. I was expecting if condition will prevent running Student::create([])
So how can I store values only in University and Teachers table when submitting from teachers form and University and Students table only when submitting from students form without having null values in either of them.

Instead of using like this, simple would be use if and else statements and that would do the job.
Example:
$university = University::create([
'university_id' =>$universityID,
'category' => $category,
'name' => $name
]);
if($category == 'Teacher') {
Teacher::create([
'university_id' => $university->id,
'position' => $position,
'courses' => $course,
'salary' => $salary
]);
else if($category == 'Student') {
Student::create([
'university_id' => $university->id,
'year' => $year,
'semester' => $semester,
'programme' => $programme,
'rollNum' => $roll
]);
}else{
//Unknown Category name
}
Let me know if that works for you. The way I see it's very simple and straight forward.

Related

How Do I Prevent Duplicate When Storing My API Fetched Data

I am fetching data from an API. I am able to store the data in my database but whenever i refresh, it stores another copy of the same set of data fetched from the API. I simply want to know how to only update the database with the new records whilst ignoring the old once stored already.
Controller
public function dashboard()
{
$client = new Client();
$uri = 'https://api.clickmeeting.com/v1/conferences/active';
$header = ['headers' => ['X-Api-Key' => '123456']];
$res = $client->get($uri, $header);
$conferences = json_decode($res->getBody()->getContents(), true);
collect($conferences)
->each(function ($conference, $key) {
ClickMeeting::create([
'conference_id' => $conference['id'],
'parent_id' => $conference['parent_id'],
'room_type' => $conference['room_type'],
'room_pin' => $conference['room_pin'],
'name' => $conference['name'],
'name_url' => $conference['name_url'],
'access_type' => $conference['access_type'],
'lobby_enabled' => $conference['lobby_enabled'],
'lobby_description' => $conference['lobby_description'],
'registration_enabled' => $conference['registration_enabled'],
'status' => $conference['status'],
'timezone' => $conference['timezone'],
'timezone_offset' => $conference['timezone_offset'],
'paid_enabled' => $conference['paid_enabled'],
'automated_enabled' => $conference['automated_enabled'],
'type' => $conference['type'],
'permanent_room' => $conference['permanent_room'],
'room_url' => $conference['room_url'],
'embed_room_url' => $conference['embed_room_url'],
]);
});
return view('admin.clickmeeting.dashboard');
}
Migration Schema
public function up()
{
Schema::create('clickmeeting', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('conference_id')->unique();
$table->string('parent_id')->nullable();
$table->string('room_type');
$table->string('room_pin');
$table->string('name');
$table->string('name_url');
$table->string('ends_at');
$table->string('access_type');
$table->string('lobby_enabled');
$table->string('lobby_description');
$table->string('registration_enabled');
$table->string('status');
$table->string('timezone');
$table->string('timezone_offset');
$table->string('paid_enabled');
$table->string('automated_enabled');
$table->string('type');
$table->string('permanent_room');
$table->string('room_url');
$table->string('embed_room_url');
});
}
Help is gratefully appreciated. Thank You
Laravel has a firstOrCreate() method, which either finds the model or creates it. Perfect for your example. The first parameter, is the columns that defines the uniqueness and the second parameter is the columns that should be added to the row. These columns are concatenated when saved. It is very uncommon and flaky, to expect such a big request to use all columns for uniqueness.
Let's imagine that these 3 columns would define a non present composite key room_type, parent_id and room_url. This can be adjusted by you to follow the correct columns.
ClickMeeting::firstOrCreate([
'parent_id' => $conference['parent_id'],
'room_type' => $conference['room_type'],
'room_url' => $conference['room_url'],
],
[
'conference_id' => $conference['id'],
'room_pin' => $conference['room_pin'],
'name' => $conference['name'],
'name_url' => $conference['name_url'],
'access_type' => $conference['access_type'],
'lobby_enabled' => $conference['lobby_enabled'],
'lobby_description' => $conference['lobby_description'],
'registration_enabled' => $conference['registration_enabled'],
'status' => $conference['status'],
'timezone' => $conference['timezone'],
'timezone_offset' => $conference['timezone_offset'],
'paid_enabled' => $conference['paid_enabled'],
'automated_enabled' => $conference['automated_enabled'],
'type' => $conference['type'],
'permanent_room' => $conference['permanent_room'],
'embed_room_url' => $conference['embed_room_url'],
],
]);

Save multiple data in database column from select multiple

I want to save more than one university under one student. For html select I used
<select class="selectpicker" multiple data-live-search="true" name="university">
#foreach($districts as $row)
<option value= {{$row->name}} > {{$row->name}} </option>
#endforeach
</select>
This taking previously saved university. I am using district as university.
Controller->
public function store(Request $request)
{
Seller_info::create([
'name' => $request['name'],
'email' => $request['email'],
'passport' => $request['passport'],
'phone_number' => $request['phone_number'],
'address' => $request['address'],
'dateofbirth' => $request['dateofbirth'],
'ielts' => $request['ielts'],
'openingcharge' => $request['openingcharge'],
'serviceCharge' => $request['serviceCharge'],
'applydate' => $request['applydate'],
'visaStatus'=> $request['visaStatus'],
'country' => $request['country'],
'university'=> $request['university'],
]);
return back();
}
This is saving the students. This is a mishmash code I am sorry about that. I am working on a different for fast learning. Here I am using seller_info as student.
The data is is saving university but only one university in the database. I tried to use for loop in case of storing. But could not able to implement it properly.
My table file->
Schema::create('seller_infos', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable();
$table->string('email')->unique();
$table->string('passport')->nullable();
$table->string('phone_number')->unique();
$table->string('address')->nullable();
$table->string('dateofbirth')->nullable();
$table->string('ielts')->nullable();
$table->string('openingcharge')->nullable();
$table->string('serviceCharge')->nullable();
$table->string('applydate')->nullable();
$table->string('visaStatus')->nullable();
$table->string('country')->nullable();
$table->string('university')->nullable();
$table->timestamps();
});
And model
protected $fillable = [
'name', 'email', 'passport', 'phone_number','address','dateofbirth','ielts', 'openingcharge','serviceCharge','applydate',
'visaStatus','country','university'
];
If you want to store multiple university data for one student first of all you need 3 table, students(so your Seller Info), universities and seller_info_university(will be pivot table),
seller_info_university Migration must be like;
Schema::create('seller_info_university', function (Blueprint $table) {
$table->bigInteger('seller_info_id')->unsigned();
$table->bigInteger('university_id')->unsigned();
});
Add this code your SellerInfo Model;
public function universities()
{
return $this->belongsToMany(University::class); // Your University model
}
Add this code your University Model;
public function students()
{
return $this->belongsToMany(SellerInfo::class); // Your Student(SellerInfo) model
}
In your Controller try this
$student = Seller_info::create([
'name' => $request['name'],
'email' => $request['email'],
'passport' => $request['passport'],
'phone_number' => $request['phone_number'],
'address' => $request['address'],
'dateofbirth' => $request['dateofbirth'],
'ielts' => $request['ielts'],
'openingcharge' => $request['openingcharge'],
'serviceCharge' => $request['serviceCharge'],
'applydate' => $request['applydate'],
'visaStatus'=> $request['visaStatus'],
'country' => $request['country'],
// 'university'=> $request['university'], you dont need there anymore
]);
$student->universities()->attach($request['universities']); // You can use attach(), detach() or sync() functions, you can search in Laravel Documentation
return back();
And View;
<select class="selectpicker" multiple data-live-search="true" name="universities[]">
#foreach($districts as $row)
<option value= {{$row->name}} > {{$row->name}} </option>
#endforeach
</select>

Laravel 8 adding data to pivot table with seeder using factory

I have Product and Category model and I've crated a many to many relationships with a pivot table named category_product.
I have also created 2 factories for category and product.
I am trying to add 100 products with 2 categories for each. Somehow it ads 200 records to my categories table. What I am doing wrong?
My CategoryFactory class:
public function definition()
{
return [
'name' => $this->faker->numberBetween(1, 12),
'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
'updated_at' => Carbon::now()->format('Y-m-d H:i:s')
];
}
And my ProductFactory class is looking like that:
public function definition()
{
return [
'name' => $this->faker->name,
'description' => $this->faker->text,
'image' => 'image-' . rand(1, 10) . '.jpg',
'price' => $this->faker->numberBetween(300, 20000),
'code' => $this->faker->regexify('[A-Z0-9]{12}'),
'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
'updated_at' => Carbon::now()->format('Y-m-d H:i:s')
];
}
I have these in my ProductSeeder
Product::factory(100)->has(Category::factory()->count(2))->create();
My pivot table migration:
Schema::create('category_product', function (Blueprint $table) {
$table->id();
$table->foreignId('product_id')->constrained();
$table->foreignId('category_id')->constrained();
$table->timestamps();
});
In your factory seeder, you are essentially saying "for every product, create two new categories, and then link them to the product", which is why you are ending up with 200 categories. If you look in your pivot table, you'll see you also have 200 entries, but no category_id will be the same.
If, I am assuming, you want 100 products, 2 categories and a linkage between them, your seeder should be more like
$categories= Category::factory()->count(2)->create();
$products = Product::factory()
->count(100)
->hasAttached($categories)
->create();
You'll end up with 100 products, 2 categories, and 200 pivot entries where the category_id has a cardinality of 2 (i.e. ids 1 and 2)

Two store() methods, one doesn't work (Call to undefined method save())

One of two similar store methods doesn't work. Could you clarify this for me?
Relations
A Team hasMany Users <> A User belongsTo a Team
A User hasMany Characters <> A Character belongsTo a User
Working Code (CharacterController)
public function store()
{
$fighters = Fighter::pluck('name')->toArray();
$this->validate(request(), [
'name' => 'required|min:3|max:25|alpha_num|not_in:'.Rule::notIn($fighters).'unique:characters',
'fighter' => 'required|in:'.Rule::in($fighters),
]);
auth()->user()->characters()->save(new Character([
'name' => request('name'),
'fighter' => request('fighter'),
]));
return redirect()->route('character.index');
}
Not Working (TeamController)
public function store()
{
$this->validate(request(), [
'name' => 'required|min:3|max:25|alpha_num|unique:teams',
]);
auth()->user()->team()->save(new Team([
'name' => request('name'),
'fame' => 0,
]));
return redirect()->route('team.index');
}
Questions
Why is the same method not available? Is it relation stuff?
Is the create method better? Should I try to use it?
Thought I know what I'm doing, now it turns out I don't...
Thank you for helping.
team() is a belongsTo relation, you probably have a team_id col in your user table which you want to associate with the team.
public function store()
{
$this->validate(request(), [
'name' => 'required|min:3|max:25|alpha_num|unique:teams',
]);
// create and save team
$team = new Team([
'name' => request('name'),
'fame' => 0,
]);
$team->save();
// associate current authenticated user with team (set foreign key) and save user
auth()->user()->team()->associate($team)->save();
return redirect()->route('team.index');
}

Showing relation table fields with filters in yii2

I'm showing has many relation table value in my girdview as follows
[
'attribute' => 'Resume Title',
'value' => function($model, $key, $index) {
return implode(\yii\helpers\ArrayHelper::map(
$model->jobSeekerProfiles,
'job_seeker_profile_id',
'resume_title'
));
},
],
my table relation is
public function getJobSeekerProfiles()
{
return $this->hasMany(JobSeekerProfile::className(), ['user_id' => 'user_id']);
}
But how to make this column with filter and sortable ?

Resources