Laravel - model for table with only foreign keys (Pivot Table) - php

I need to implement model for table with only two foreign keys. In my db I have tables like this:
product (id_product, ...)
category_to_product (FK id_category, FK id_product)
category (id_category, ...)
How to manage this connections in Laravel? Should I implement model for merge table and how it may looks? category_to_product table does not represent entity(/model) and have only design-relation property.
Database Migrations
CategoryToProduct
Schema::create('category_to_product', function(Blueprint $table)
{
$table->integer('id_category')->unsigned();
$table->foreign('id_category')
->references('id_category')
->on('categories')
->onDelete('cascade');
$table->integer('id_product')->unsigned();
$table->foreign('id_product')
->references('id_product')
->on('products')
->onDelete('cascade');
});
Products
Schema::create('products', function(Blueprint $table)
{
$table->increments('id_product');
// ...
});
Categories
Schema::create('categories', function(Blueprint $table)
{
$table->increments('id_category');
// ...
});

#pc-shooter is right about creating methods.
But you still have to create the pivot table with your migration first
Schema::create('products', function(Blueprint $table)
{
$table->increments('id')
$table->string('name');
}
Schema::create('categories', function(Blueprint $table)
{
$table->increments('id')
$table->string('name');
}
Then your pivot table
Schema::create('category_product', function(Blueprint $table)
{
$table->integer('category_id')
$table->foreign('category_id')->references('id')->on('categories');
$table->integer('product_id');
$table->foreign('product_id')->references('id')->on('products');
// And finally, the indexes (Better perfs when fetching data on that pivot table)
$table->index(['category_id', 'product_id'])->unique(); // This index has to be unique
}

Do the following:
In the model Category:
public function products(){
return $this->belongsToMany('Category');
}
In the model Product:
public function categories(){
return $this->belongsToMany('Category', 'category_to_product');
}
In the model CategoryToProduct:
public function categories() {
return $this->belongsTo('Category');
}
public function products() {
return $this->belongsTo('Product');
}
Note the naming of these methods!
Those are the same as the DB-table names. See ChainList's
answer.

Related

Laravel 8 relationship of three models which belongs to Parent model

Hello everyone I'm currently working on a laravel project where I have a parent table that has the id's of three tables referenced to it. These table migrations also have their models respectively. Here are the table migrations files respectively:
create_products_table.php
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('product_id', 10);
$table->string('product_name');
$table->string('image');
$table->string('images');
$table->string('product_description');
$table->bigInteger('size_id')->unsigned();
$table->string('color');
$table->string('product_quantity');
$table->string('old_price');
$table->string('discount');
$table->string('product_price');
$table->bigInteger('user_id')->unsigned()->nullable();
$table->bigInteger('category_id')->unsigned();
$table->bigInteger('gender_id')->unsigned();
$table->timestamps();
$table->foreign('size_id')->references('id')->on('sizes')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->foreign('gender_id')->references('id')->on('genders')->onDelete('cascade');
});
create_genders_table.php
Schema::create('genders', function (Blueprint $table) {
$table->id();
$table->string('gender_class');
$table->timestamps();
});
create_categories_table.php
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('cat_name');
$table->timestamps();
});
create_sizes_table.php
Schema::create('sizes', function (Blueprint $table) {
$table->id();
$table->string('sizes');
$table->timestamps();
});
Also this is how I defined the relationships on their models respectively
Product.php
public function category()
{
return $this->belongsTo(Category::class);
}
public function gender()
{
return $this->belongsTo(Gender::class);
}
public function size()
{
return $this->belongsTo(Size::class);
}
Category.php
public function products()
{
return $this->hasMany(Product::class);
}
Gender.php
public function products()
{
return $this->hasMany(Product::class);
}
Size.php
public function products()
{
return $this->hasMany(Product::class);
}
I'm actually a laravel beginner and I studied eloquent model relationships at laravel.com so what I did was just based on my understanding of one to many relationships. When I check all my request with dd($request), category_id, gender_id, size_id all show null and I believe it's because I didn't define the relationship properly. Now this is where I seriously need your assistance.
So please my experienced developers I seriously need your help I'll really be grateful if I get your replies today. Thanks in advance.
=>Everything is right, just make changes in the products migration add this code.
$table->foreign('size_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('gender_id')->references('id')->on('products')->onDelete('cascade');
=>and migrate table

Implementing relationship in models

I have two models: Dish and DishCategory. I decided to implement a "One to many" relationship.
Here's a migration for Dish model:
Schema::create('dishes', function (Blueprint $table) {
$table->increments('id');
$table->string('dish', 50);
$table->string('photo');
$table->double('price', 8, 2);
$table->integer('category_id');
$table->integer('type_id'); /* 1 - menu for delivery; 0 - general menu */
});
And a migration for DishCategory model:
Schema::create('dish_categories', function (Blueprint $table) {
$table->increments('id');
$table->string('category');
});
I've created a method called dish() in DishCategory model:
public function dish()
{
return $this->hasMany('App\Dish');
}
And dish_category() in Dish model:3
public function dish_category()
{
return $this->belongsTo('App\DishCategory', 'category_id');
}
I'm trying to set up a foreign key in my relationship, so it's been set up in dish_category() method as a second parameter of belongsTo(). But it doesn't work. What is the workaround?
Change the dish() relationship definition to:
public function dish()
{
return $this->hasMany('App\Dish', 'category_id');
}
And dish_category() is defined correctly.
If you also want to add a constraint, add this to the dishes table migration:
Schema::table('dishes', function (Blueprint $table) {
$table->foreign('category_id')->references('id')->on('dish_categories');
});

Laravel relationship belongsToMany with composite primary keys

I have 3 tables and I'm trying to make relations between order_products and order_products_status_names. I have transition/pivot table named order_product_statuses. The problem are my PK, becuase I have in table orders 3 Pk, and I don't know how to connect this 3 tables throught relationships.
My migrations are:
Table Order Products:
public function up()
{
Schema::create('order_products', function (Blueprint $table) {
$table->integer('order_id')->unsigned();
$table->integer('product_id')->unsigned();
$table->integer('ordinal')->unsigned();
$table->integer('size');
$table->primary(['order_id', 'product_id', 'ordinal']);
$table->foreign('order_id')->references('id')->on('orders');
$table->foreign('product_id')->references('id')->on('products');
});
}
Table Order Product Statuses - this is my transition/pivot table between order_products and order_product_status_names
public function up()
{
Schema::create('order_product_statuses', function (Blueprint $table) {
$table->integer('order_id')->unsigned();
$table->integer('product_id')->unsigned();
$table->integer('status_id')->unsigned();
$table->integer('ordinal')->unsigned();
$table->dateTime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$table->foreign('order_id')->references('id')->on('orders');
$table->foreign('status_id')->references('id')->on('order_product_status_names');
$table->primary(['order_id', 'product_id', 'ordinal']);
});
}
And the last one is Order Product Status Names
public function up()
{
Schema::create('order_product_status_names', function (Blueprint $table) {
$table->integer('id')->unsigned();
$table->string('name');
$table->string('code');
$table->dateTime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$table->primary('id');
});
}
I know that here is relationship blengsToMany in two ways, but I don't know or can I declarate this relation ( from order_products to order_product_status_names and inverse )?
Ok haven't spent a great amount of time on this, but this is kind of what I would do. Also as #Devon mentioned I would probably add ids to each table seeing as Eloquent isn't really designed for composite keys. As mentioned in one of my comments I usually create startup and update scripts, so the syntax might not be exactly right:
public function up() {
Schema::create('order_products', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->integer('order_id')->unsigned();
$table->integer('product_id')->unsigned();
$table->integer('order_product_statuses_id')->unsigned();
$table->integer('ordinal')->unsigned();
$table->integer('size');
$table->primary('id');
$table->foreign('order_id')->references('id')->on('orders');
$table->foreign('product_id')->references('id')->on('products');
$table->foreign('order_product_statuses_id')->references('id')->on('order_product_statuses');
});
}
public function up() {
Schema::create('order_product_statuses', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->integer('product_id')->unsigned();
$table->integer('status_id')->unsigned();
$table->integer('ordinal')->unsigned();
$table->dateTime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$table->primary('id');
$table->foreign('status_id')->references('id')->on('order_product_status_names');
});
}
public function up() {
Schema::create('order_product_status_names', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->string('name');
$table->string('code');
$table->dateTime('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
$table->primary('id');
});
}
I hope that helps you out a bit.

onDelete('cascade') not deleting data on pivot table

I have the following migration:
public function up()
{
Schema::create('topics_to_subscriptions', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->integer('topic_id')->unsigned();
$table->integer('subscription_id')->unsigned();
$table->foreign('topic_id')->references('id')->on('topics')->onDelete('cascade');
$table->foreign('subscription_id')->references('id')->on('subscriptions')->onDelete('cascade');
});
}
My undersatnding is that when using onDelete('cascade'), if I delete a subscription, then all associated TopicsToSubscriptions will be delete.
When I run App\Subscription::truncate(); all the subscriptions are deleted correctly from subscriptions table but no data is deleted from topics_to_subscriptions. what am I doing wrong?
You shouldn't be able to truncate a table referenced by foreign keys. I suspect your foreign keys never got applied correctly.
https://laravel.com/docs/5.4/migrations#foreign-key-constraints
public function up()
{
Schema::create('youtube_topics_to_subscriptions', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->integer('topic_id')->unsigned();
$table->integer('youtube_subscription_id')->unsigned();
$table->foreign('topic_id')->references('id')->on('youtube_topics')->onDelete('cascade');
$table->foreign('youtube_subscription_id')->references('id')->on('youtube_subscriptions')->onDelete('cascade');
});
}

Automaticlly attach to pivot table in Laravel 5

I currently have a Users to Groups Relationship (ManyToMany) with a pivot table group_user. I want the user to be able to create a group but once creating the group, how do I make it, that the creator becomes member of this group?
Currently I have
My Pivot Table (group_user):
Schema::create('group_user', function(Blueprint $table)
{
$table->integer('group_id')->unsigned()->index();
$table->foreign('group_id')->references('id')->on('groups')->onDelete('cascade');
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
My Groups table (groups):
Schema::create('groups', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->timestamps();
});
My Users table (users):
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('name');
$table->string('lastname');
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
My models ofcourse have the following: User.php
public function groups()
{
return $this->belongsToMany('App\Group');
}
Group.php
public function users()
{
return $this->belongsToMany('App\User');
}
What create function should I write in my controller so that when a User creates a Group, that he automaticly becomes member of this group (automaticlly make the pivot relationship)?
This should work, make sure you implement validation, ect.
public function store(Request $request)
{
$group = Group::create([ // <-- if names are unique. if not, then create is fine
'name' => $request->get('name')
]);
auth()->user()->groups()->attach([$group->id]);
return view('your.view');
}
Also make sure to add:
use App\Group;
See attach() and detach().
$user = User::find(1);
$user->groups()->attach(10); // pivot relationship of this user to group of id 1.
OR
$group = Group::find(10);
$user->groups()->save($group);
For many groups of this user:
$user->groups()->sync(array(1, 2, 3));

Categories