Laravel 5.1 manyToMany with two classes and third in common - many-to-many

Here is the example:
Two classes: chairs and tables. Both of those classes are connected with third class colours with ManyToMany relations.
Let's say I have element of chairs class with two colours: red and blue.
How do I get matching tables, the tables that also belong to red and blue?
EDIT:
Chair model:
class Chair extends Model
{
public function colours()
{
return $this->belongsToMany('App\Colour')->withTimestamps();
}
}
Table model:
class Table extends Model
{
public function colours()
{
return $this->belongsToMany('App\Colour')->withTimestamps();
}
}
Colors model:
class Colour extends Model
{
public function chairs()
{
return $this->belongsToMany('App\Chair')->withTimestamps();
}
public function tables()
{
return $this->belongsToMany('App\Tables')->withTimestamps();
}
}
Chair migration's up function:
public function up()
{
Schema::create('chairs', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('name');
});
}
Chair-Colour pivot table:
public function up()
{
Schema::create('chair_colour', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->integer('chair_id')->unsigned();
// $table->foreign('chair_id')->references('id')->on('chairs')->onDelete('cascade');
$table->integer('colour_id')->unsigned();
// $table->foreign('colour_id')->references('id')->on('colours')->onDelete('cascade');
});
}
Remaining migrations (tables, chair_table, colours) are the same.
Foreign key constrains are commented out because I had problems when refreshing migrations with them included.
This is just manyToMany relation but I hope it helps. I just made this up since my code is more complicated so if You see any typos feel free to correct them or notify me in comments.
Thank You!

Related

How to Display Data from Table relationship base on ID come from first table LARAVEL

I have 3 table, table Courses, table Sections, and table Syllabuses. Where table courses relation to table Sections and table Sections relation to table Syllabuses. To make clear below my table look like:
#Table Courses:
public function up()
{
Schema::create('courses', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->unsignedBigInteger('category_id')->default('1');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade')->onUpdate('cascade');
$table->string('title');
$table->string('status')->default('publish');
$table->text('content')->nullable();
$table->timestamps();
});
}
Table Sections:
public function up()
{
Schema::create('sections', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('course_id');
$table->foreign('course_id')->references('id')->on('courses');
$table->string('name');
$table->timestamps();
});
}
and the last table Syllabuses:
public function up()
{
Schema::create('syllabuses', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('section_id');
$table->foreign('section_id')->references('id')->on('sections')->onDelete('cascade')->onUpdate('cascade');
$table->string('title')->nullable();
$table->text('content')->nullable();
$table->text('description')->nullable();
$table->timestamps();
});
}
and now I'm stuck to display data from table syllabuses base on Sections's ID, where the sections display base on Courses's ID, because I don't know how to get the ID from each row which related to Secations's ID to put in Syllabus::where('section_id',???)->get();. Anyone who can help me much much appreciate. Hope u understand what I mean.
Below the image you can see, there I have put some note to make u understand. The problem in the green box one.
enter image description here
Define relations in your models first.
I assume your models are: Course, Section and Syllabus
// Model Course
public function sections()
{
return $this->hasMany(Section::class);
}
// Model Section
public function course()
{
return $this->belongsTo(Course::class);
}
public function syllabuses()
{
return $this->hasMany(Syllabus::class);
}
// Model Syllabus
public function section()
{
return $this->belongsTo(Section::class);
}
Now in your controller you can get your designated course by
// Controller Course
public function show($id)
{
$course = Course::with('sections', 'sections.syllabuses')->where('id', $id)->first();
}
In this query you have a model from "Course" table, related models from "Sections" table and all the related models from "Syllabuses" table. If you are using laravel's blade then you can simply access them by:
// course
{!! $course->your_attribute !!}
// to access sections
#foreach($course->sections as $section)
#endforeach
// to access syllabuses
#foreach($course->sections as $section)
#foreach($section->syllabuses as $syllabus)
// Here you will have syllabuses for individual sections
#endforeach
#endforeach
https://laravel.com/docs/8.x/eloquent-relationships#one-to-many
You need to study laravel relationships in your case you have belongsTo relation.
In your Syllabus model add.
public function section(){
return $this->belongsTo(Section::class, 'section_id');
}
Then you can use this will get all Syllabuses with related to there sections.
Syllabus::with('section')->get();

Laravel One To Many (Inverse) / Belongs To return null

I use Laravel 8. I have 3 table. Course table, UserCourse, and User table. I want to get user courses. I tried it with tinker: Course::find(1)->user_courses -it works fine and give back me user_course.
UserCourse::find(1)->user_course - the problem is here, this will return me "null"
How can I get the User Courses?
Course table
Schema::create('courses', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->timestamps();
});
UserCourse table
Schema::create('user_courses', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
User table
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->string('username')->unique();
$table->string('password');
$table->timestamp('updated_at')->nullable();
$table->timestamp('created_at')->nullable();
});
Course.php
class Course extends Model
{
use HasFactory;
protected $fillable = [
'title',
];
public function user_courses()
{
return $this->hasMany(UserCourse::class);
}
}
UserCourse.php
class UserCourse extends Model
{
use HasFactory;
protected $fillable = [];
public function user_course()
{
return $this->belongsTo(Course::class);
}
}
Your database structure make it that the relation between course and user is a many to many relation with a pivot table in the middle.
Some correction you need to do for it to work seemingly with laravel conventions.
- The pivot table name should be course_user without a primary key
Schema::create('course_user', function (Blueprint $table) {
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
- Remove the UserCourse.php model since it's a pivot
- Define the relation courses in User model as follow
User.php
public function courses()
{
return $this->belongsToMany(Course::class);
}
- Define the relation users in Course model as follow
Course.php
public function users()
{
return $this->belongsToMany(User::class);
}
Now to get any user courses, just run User::find(1)->courses
Same thing to get the users that belongs to the same couses Course::find(1)->users
get courses that the user has not taken:
$userId = 1;
$courses = Course::whereDoesntHave('users', function($userQB) use($userId) {
$userQB->where('id',$userId);
})->get();

How to connect via an eloquent relation in the Laravel table Type_Vehicle, Mark, Model table

I need to make 3 dropdowns. When selecting Vehicle_Type, only the Car will get it. When Vehicle_type = Car is selected, Mark is chosen for example Audi, Bmw, Mercedes. When Mark is selected, the model is chosen, but the model must be, for example, if I selected Audi to get A3, A4, A5. If the user chooses BMW gets it as a model X5, X6 and so on. Look at my tables below. QUESTION I need to connect models and get the queries?
There is also a car table that should not be mentioned with these tables, at least I think.
Vehicle_type or car_type table:
Schema::create('car_types', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Mark table:
Schema::create('marks', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('car_type_id');
$table->timestamps();
});
car_models table:
Schema::create('car_models', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('car_type_id');
$table->integer('mark_id');
$table->timestamps();
});
Car_type model:
class Car_type extends Model
{
??????
}
Mark model:
class Mark extends Model
{
??????
}
CarModel model:
class CarModel extends Model
{
??????
}
You probably don't need car_type_id on your car_models table:
Schema::create('car_models', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('mark_id');
$table->timestamps();
});
Should be sufficient.
Car_type model:
class Car_type extends Model
{
public function marks() {
return $this->hasMany(Mark::class);
}
}
Mark model:
class Mark extends Model
{
public function car_type() {
return $this->belongsTo(Car_type::class);
}
public function models() {
return $this->hasMany(CarModel::class);
}
}
CarModel model:
class CarModel extends Model
{
public function mark()
{
return $this->belongsTo(Mark::class);
}
}

GroupBy results from a HasManyThrough a ManyToMany relationship in Laravel 5.5

I have a complex relationship like a ManyToMany relationship between Category and Products and a Product can have many Inventory listings from different Shops(user). A Shop can have multiple listing of the same Product as a variant(color/size).
Everything is fine till now!
The issue begins when showing the listing to the visitors. I want to show all listings under a category but don't want to show multiple listings of the same product from the same shop. Instead, want to pick the lowest sale_price listing from the shop.
I have three models and relations are like:
class Category extends Model
{
public function products()
{
return $this->belongsToMany(Product::class);
}
}
class Product extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
public function inventories()
{
return $this->hasMany(Inventory::class);
}
}
class Inventory extends Model
{
public function product()
{
return $this->belongsTo(Product::class);
}
}
Tables:
//Categories
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
});
//Products
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
});
//Pivot table
Schema::create('category_product', function (Blueprint $table) {
$table->integer('category_id');
$table->integer('product_id');
});
//Inventories
Schema::create('inventories', function (Blueprint $table) {
$table->increments('id');
$table->integer('shop_id');
$table->integer('product_id');
$table->string('sku', 200);
$table->string('title');
$table->decimal('sale_price', 10, 2);
});
As Laravel doesn't provide any manyToManyThough() relationship. I have added a listings method in the Category model. This method returns all listings:
public function listings()
{
$product_ids = $this->products()->pluck('products.id')->all();
return Inventory::whereIn('product_id', $product_ids)->paginate(20);
}
Then I tried this:
public function listings()
{
$product_ids = $this->products()->pluck('products.id')->all();
return Inventory::whereIn('product_id', $product_ids)->groupBy('shop_id','product_id')->paginate(20);
}
These methods produce MySQL GroupBy Error. Yes, I can filter the result after taking all result but that'll affect the pagination. How to get the sorted results and also keep the pagination ability. Thanks and day by day I got more indebted to the community. :)
You can create a direct relationship by "skipping" the products table:
public function listings() {
return $this->belongsToMany(
Inventory::class,
'category_product',
null,
'product_id',
null,
'product_id'
);
}

Eloquent - Many To Many, users-topics delete all topics by user id

Given Eloquent Many To Many relationship:
Migration:
class Topics extends Migration
{
public function up()
{
Schema::create('topics', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
});
Schema::create('topic_user', function(Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('topic_id')->unsigned();
$table->foreign('topic_id')->references('id')->on('topics');
});
}
}
Model:
class User extends Model
{
public function topics()
{
return $this->belongsToMany('App\Topic', 'topic_user');
}
}
I'm wondering how can I delete all topics by given user, currently my code looks like this:
Auth::user()->topics()->delete();
But I'm getting exception:
ERROR: missing FROM-clause entry for table "topic_user" LINE 1: delete
from "topics" where "topic_user"."user_id" = $1 ^ (SQL: delete from
"topics" where "topic_user"."user_id" = 6)
What I'm doing wrong?
That's pretty simple:
Auth::user()->topics()->detach();