Laravel relationship belongsToMany with composite primary keys - php

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.

Related

How to pass foreign key laravel

I'm trying to pass the foreign key but am stuck with this error Base table or view already exists: 1050 Table 'favorites' already exists"
how can I pass them all the foreign keys and the normal id like $table->bigInteger('user_id')->unsigned();
tables
public function up()
{
Schema::create('favorites', function (Blueprint $table) {
$table->Increments('id');
$table->bigInteger('user_id')->unsigned();
$table->bigInteger('product_id')->unsigned();
$table->timestamps();
});
Schema::create('favorites', function (Blueprint $table){
$table->bigInteger('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users');
$table->bigInteger('product_id')->unsigned()->index();
$table->foreign('product_id')->references('id')->on('products');
});
}
public function down()
{
Schema::dropIfExists('favorites');
}
You're migrating the table twice, pass the foreign keys in the same migration
public function up()
{
Schema::create('favorites', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->bigInteger('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('favorites');
}
Hope this helps
Other answers are correct. If ever you've missed the needed tasks before doing it, kindly try this one
1) Remove or delete the table you've migrated
2) In migrations table, delete the record which consists the name "favorites"
3) Copy and paste thi code inside the "up" function with this one
Schema::create('favorites', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id')->unsigned();
$table->bigInteger('product_id')->unsigned();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('product_id')->references('id')->on('products');
});
4) Run this command again
php artisan migrate

can not add foreign key

I wrote some migration but the foreign key's will not be added and give me the low error.
I dont see everything is suspicious.
General error : 1251 cannot add foreign key constraint (SQL:alter table 'advertising' add constraint 'advertising_category_id_foreign' foreign key ('category_id')refrences 'category' ('id') on delete restrict on update cascade)
I change id type in related migration's,but it didn't work.
I turned the id in related migration's to index(),but agane didn't work.
public function up()
{
Schema::create('advertising', function (Blueprint $table){
$table->increments('id')->index();
$table->integer('user_id')->unsigned()->index();
$table->string('ranking')->nullable();
$table->string('status')->nullable();
$table->string('name')->nullable();
$table->string('family')->nullable();
$table->string('advertising_name')->nullable();
$table->string('phone')->nullable();
$table->string('email')->nullable();
$table->string('address')->nullable();
$table->string('country-city')->nullable();
$table->integer('category_id')->unsigned()->nullable();
$table->string('week_days')->nullable();
$table->string('time_open')->nullable();
$table->string('time_close')->nullable();
$table->string('body')->nullable();
$table->string('facebook')->nullable();
$table->string('twitter')->nullable();
$table->string('instagram')->nullable();
$table->integer('service_garanti_id')->unsigned()->nullable();
$table->integer('professional_id')->unsigned()->nullable();
$table->integer('insurance_Limit_id')->unsigned()->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('cascade')->onUpdate('cascade');
$table->foreign('category_id')->references('id')->on('category')
->onDelete('restrict')->onUpdate('cascade');
$table->foreign('service_garanti_id')->references('id')
->on('service_garanti')
->onDelete('restrict')->onUpdate('cascade');
$table->foreign('professional_id')->references('id')
->on('professional')->onDelete('restrict')->onUpdate('cascade');
$table->foreign('insurance_Limit_id')->references('id')
->on('insurance_limit')
->onDelete('restrict')->onUpdate('cascade');
});
The related migration's :
public function up()
{
Schema::create('category', function (Blueprint $table){
$table->increments('id');
$table->string('body')->nullable();
$table->timestamps();
});
public function up()
{
Schema::create('service_garanti', function (Blueprint $table){
$table->increments('id')->index();
$table->string('body')->nullable();
$table->timestamps();
});
public function up()
{
Schema::create('Professional', function (Blueprint $table){
$table->increments('id')->index;
$table->string('body')->nullable();
$table->timestamps();
});
}
public function up()
{
Schema::create('Insurance_Limit', function (Blueprint $table){
$table->increments('id')->index();
$table->string('body')->nullable();
$table->timestamps();
});
}
Try changing the order of your migrations so that the tables containing the foreign values are created first (category, service_garanti, etc.) and then create the advertising table and make the key connections. The tables and columns must already exist in order for the migration to succeed.
The other option if you know the keys are correct and will be created, it to just disable the key checking at runtime by adding this to the top of your migration.
public function up(){
Schema::disableForeignKeyConstraints();
Schema::create('advertising', function (Blueprint $table){
...
}
}

Laravel migration foreign keys references to a primary key with two columns?

I am using Laravel 5.3 and MySQL.
How can I add in Laravel foreign keys references to a primary key with two columns?
Below are my migration scripts (under the database/migrations/ directory):
primary key with two columns
public function up()
{
Schema::create('X', function (Blueprint $table) {
$table->integer('a')->unsigned();
$table->integer('b')->unsigned();
$table->primary(['a', 'b']);
$table->timestamps();
});
}
and in another,
public function up()
{
Schema::create('Y', function (Blueprint $table) {
$table->increments('k');
$table->foreign('c')->references(['a', 'b'])->on('X')->onDelete('cascade');
$table->timestamps();
});
}
However, it doesn't work so: how can I achieve that?
Use Schema::table() instead of Schema::create() when adding foreign key constraints to your database.
Below, snippets illustrating the fix:
// File name: 2016_09_28_create_x_table.php
public function up()
{
// Create table X
Schema::create('X', function (Blueprint $table) {
$table->integer('a')->unsigned();
$table->integer('b')->unsigned();
$table->primary(['a', 'b']);
$table->timestamps();
});
}
// File name: 2016_09_28_create_y_with_foreignkey_table.php
public function up()
{
// Create table Y
Schema::create('Y', function (Blueprint $table) {
$table->increments('k');
$table->integer('c')->unsigned();
$table->timestamps();
});
// Add Foreign key
Schema::table('Y', function (Blueprint $table) {
$table->foreign('c')->references('a')->on('X')->onDelete('cascade');
});
}
Remember unsigned() should be applied on the c.
This is the only way that I found to simulate composite keys and FK pointing to composite keys working in Laravel 5.3 - I miss a more compacted solution in Laravel.
Anyway, here is my code
// File name: 2016_09_28_create_x_table.php
public function up()
{
// Create table X
Schema::create('X', function (Blueprint $table) {
$table->increments('j');
$table->integer('a')->unsigned();
$table->integer('b')->unsigned();
$table->unique(['a', 'b']);
$table->timestamps();
});
}
// File name: 2016_09_28_create_y_with_foreignkey_table.php
public function up()
{
// Create table Y
Schema::create('Y', function (Blueprint $table) {
$table->increments('k');
$table->integer('c')->unsigned();
$table->timestamps();
});
// Add Foreign key
Schema::table('Y', function (Blueprint $table) {
$table->foreign('c')->references('j')->on('X')->onDelete('cascade');
});
}
Foreign key should be set for 2 columns. foreign() should get also array
public function up()
{
Schema::create('X', function (Blueprint $table) {
$table->integer('a')->unsigned();
$table->integer('b')->unsigned();
$table->primary(['a', 'b']);
$table->timestamps();
});
}
public function up()
{
Schema::create('Y', function (Blueprint $table) {
$table->increments('k');
$table->integer('a');
$table->integer('b');
$table->foreign(['a', 'b'])->references(['a', 'b'])->on('X')->onDelete('cascade');
$table->timestamps();
});
}`

Calculate sum using eloquent ORM?

I was wondering how to calculate revenues using eloquent ORM.
The challenge:
Calculate the planned revenue for each clients. Each clients has many projects.
Question:
How can I make operations such as "budget-cost" outside SQL. Can i put this into my model or somewhere else to access these "special" attributes in my view?
This code is working, but not very elegant, I guess.
$planned_clients = DB::table('clients')
->join('projects', 'clients.id', '=', 'projects.client_id')
->select('projects.*', 'clients.title as client_title',
DB::raw('SUM(projects.planned_budget) as planned_budget'),
DB::raw('SUM(projects.planned_costs) as planned_costs'),
DB::raw('SUM(projects.planned_budget) - SUM(projects.planned_costs) as total_revenue')
)
->where('projects.commitment', '=', Project::PLANNED)
->whereNotIn('projects.status', [Project::CANCELED])
->groupBy('projects.client_id')
->get();
Here are the schemas
class CreateClientsTable extends Migration {
public function up()
{
Schema::create('clients', function(Blueprint $table) {
$table->increments('id');
$table->string('client_id')->unique();
$table->string('title')->unique();
$table->boolean('is_keyclient')->default(0);
$table->text('comment');
$table->timestamps();
});
}
}
class CreateProjectsTable extends Migration {
public function up()
{
Schema::create('projects', function(Blueprint $table) {
$table->increments('id');
$table->string('project_id')->unique();
$table->string('title');
$table->integer('client_id')->unsigned();
$table->enum('commitment', array('save', 'planned'));
$table->enum('status', array('waiting', 'running', 'done', 'canceled', 'cleared'));
$table->string('comment');
$table->integer('planned_budget');
$table->integer('planned_costs');
$table->integer('actual_budget');
$table->integer('actual_costs');
$table->timestamps();
});
Schema::table('projects', function(Blueprint $table) {
$table->foreign('client_id')->references('id')->on('clients');
});
}

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

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.

Categories