Laravel 5.6 Many To Many Polymorphic Relations Table Structure - php

I want to built many to many polymorphic relations Table structure. Choosen categorizables table is pivot. I am creating a table like the one below but I can not be sure of the correctness.
blogs
id - integer
name - string
...
videos
id
video_url
categories
category_id - integer
name - string
categorizables
category_id - integer - unsigned
categorizable_id - integer -unsigned
categorizable_type - string - nullable (value likes 'App\Blog' )
Following code belongs to the categorizables table.
public function up()
{
Schema::create('categorizables', function (Blueprint $table) {
$table->unsignedInteger('category_id');
$table->unsignedInteger('categorizable_id');
$table->string('categorizable_type');
$table->timestamps();
$table->index(['category_id', 'categorizable_id']);
$table->index(['categorizable_id', 'category_id']);
$table->index('categorizable_type');
});
}
categories migration file is below
Schema::create('categories', function (Blueprint $table) {
$table->increments('tag_id');
$table->string('name');
$table->string('normalized');
$table->timestamps();
$table->index('normalized');
});
How can I built structure or Am I going to true way?
Best Regards

Related

Problem with making relationships using Laravel migrations

I have problem with Laravel migrations. I want to make a relationship between two tables but
I am getting error General error: 1005 Can't create table
eshopper.prices (errno: 150 "Foreign key constraint is incorrectly
formed") (SQL: alter table prices add constraint pri ces_product_id_foreign foreign key (product_id) references
products (id) .
Here is my code. Tables are prices and products.
Prices
public function up()
{
Schema::create('prices', function (Blueprint $table) {
$table->id();
$table->float('amount');
$table->unsignedBigInteger('product_id')->unsigned()->index();
$table->foreign('product_id')->references('id')->on('products')->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
Products
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string("title",100);
$table->text("description");
$table->timestamps();
});
}
NOTE: In my migrations products table is under prices table, I know that the first created table is prices than products and that is error.
My question is do I have to put products frst or I can keep same layout(prices first, than products) and change something in code?
it happens because the product_id field type is different from the id field in the products table, try this in the products migration file:
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->unsignedBigInteger('id', true); // true here means it's auto incremental
$table->string("title",100);
$table->text("description");
$table->timestamps();
});
}
Instead of putting the constraints inside the migration file of price you can put it inside the migration file of products. Since it will create the prices table first before the products the constraints will not be created because the products table is not yet created.
/**
* This is the prices table
*
* it depends in you if you want to define the column here directly without its constraints
* the commented column is optional
*/
public function up()
{
Schema::create('prices', function (Blueprint $table) {
$table->id();
$table->float('amount');
//$table->unsignedBigInteger('product_id');
$table->timestamps();
});
}
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string("title",100);
$table->text("description");
$table->timestamps();
});
// you can define your constraints here
Schema::table('prices', function(Blueprint $table) {
$table->foreignId('product_id')
->constrained('products')
->cascadeOnDelete()
->cascadeOnUpdate();
// if you uncomment the column commented on the prices table instead of the one at above you can use this instead
$table->foreign('product_id')
->references('id')
->on('products')
->cascadeOnDelete()
->cascadeOnUpdate();
});
}
Short answer is that you MUST put products first before prices. If the whole code is still in development and have yet to get deployed, then the easiest solution is to rename the products table migration so that it has older timestamp than the prices migration has.

Change Primary ID in laravel Migration

I'm creating a table where I want to use the ID from this table "menu_items" to be added in another table
Table one: menu_items
Schema::create('menu_items', function (Blueprint $table) {
$table->id('menu_level_item_id');
$table->timestamps();
$table->string('menu_item_name');
$table->string('menu_item_desc');
Table 2 products
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('product_name');
$table->string('product_desc');
$table->integer('price');
$table->integer('menu_level_item_id');
$table->timestamps();
});
My aim of doing this is that I can then create a relationship between the 2 tables as they have the same key?
Is there a different approach I can take? Should I create a unique key when creating a menu item and then add this to the second table?
Thank you.
Basically Laravel Eloquent do the key handling. When you have two tables which both has as key the name id, this is not a problem. Name the keys in the relation table just like this
table1_id
table2_id
Laravel will handle this in Eloquent. You are also able to name the two columns in the relation table to what ever you want. You could define it for the relation in Eloquent. E.g.
public function otherModel () {
return $this->belongsToMany('App\Models\OtherModel', 'table_name', 'this_model_id', 'other_model_id');
}
Please have a look into:
Laravel Relationship Documentation
Schema::create('menu_items', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('menu_item_name');
$table->string('menu_item_desc');
table->timestamp();
});
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('product_name');
$table->string('product_desc');
$table->integer('price');
$table->unsignedBigInteger('menu_level_item_id');
$table->timestamps();
$table->foreign('menu_level_item_id')->references('id')->on('menu_items');
});

Increase the value of count in laravel 5.6

I have two tables rta_list and rta_reg_company. I have a column count in rta_list table.
Schema::create('rta_list', function (Blueprint $table) {
$table->increments('rta_id');
$table->string('rta_name');
$table->string('rta_address');
$table->string('rta_phone');
$table->string('rta_email')->unique();
$table->integer('count');
$table->timestamps();
});
Schema::create('rta_reg_company', function (Blueprint $table) {
$table->increments('company_id');
$table->integer('rta_id')->unsigned();
$table->foreign('rta_id')
->references('id')
->on('rta_lists')
->onDelete('cascade');
$table->string('company_name');
$table->string('company_isin');
$table->string('company_script');
$table->string('company_address');
$table->string('company_phone');
$table->string('company_email');
$table->timestamps();
});
I want to increase the value of count of rta_list table by rta_id when I add new RTA Registered Company. For eg: if i add one company then, The value must be added in rta_reg_company table and count must be 1 in count column in rta_list table.
Also also how to show the count value by rta_id in view..
Help Needed.....
you can use laravel Observer to raise an event on a model creation.then you can update as below on model Observer:
public function created(Company $company)
{
DB::table('rta_list')->increment('count');
}

Laravel - A show can have multiple providers

So I am trying to figure a solution to this but not sure exactly how to do this. I have a table that stores all the shows that happen. In a given show I can have multiple providers attend that show. A provider could also attend many shows as well. So how do I store this in the DB and do the eloquent relationship?
Show Schema
Schema::create('shows', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('number')->unsigned();
$table->dateTime('airDate');
$table->string('podcastUrl')->nullable();
$table->timestamps();
});
Provider Schema
Schema::create('providers', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('shortName')->nullable();
$table->string('image')->nullable();
$table->string('social')->nullable();
$table->timestamps();
});
Would I store the provider_id in the shows schema?
Update 1
So I created a new migration for a pivot table
Schema::create('provider_show', function (Blueprint $table) {
$table->integer('provider_id')->unsigned()->index();
$table->foreign('provider_id')->references('id')->on('providers')->onDelete('cascade');
$table->integer('show_id')->unsigned()->index();
$table->foreign('show_id')->references('id')->on('shows')->onDelete('cascade');
$table->primary(['provider_id', 'show_id']);
});
Then in the show model I created the following
public function providers()
{
return $this->belongsToMany(Provider::class);
}
Now when I am saving a new show I added a multiselect to select the providers I want
$show = new Show;
$show->name = $request->name;
$show->number = $request->number;
$show->airDate = $request->airDate;
$show->podcastUrl = $request->podcastUrl;
$show->providers()->attach($request->providerList);
$show->save();
Session::flash('message', "Created Successfully!");
return back();
Then when I save I get the following error
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: provider_show.show_id (SQL: insert into "provider_show" ("provider_id", "show_id") select 1 as "provider_id", as "show_id" union all select 2 as "provider_id", as "show_id")
Create a provider_show migration which will act as your pivot table.
This table would contain both provider_id and show_id which will provide the many-to-many relationship between those entities.
Then on your Provider model you can provide a shows() method which returns a BelongsToMany relationship.
// In your Provider model
public function shows()
{
return $this->belongsToMany('App\Show');
}
Note that Laravel by default looks for a pivot table name based alphabetically on the two relationships.
You can also add the inverse on your Show model by providing a providers() method that also returns a BelongsToMany relationship.

laravel making categories for a post (normalizing table)

Laravel normalizing relationship in DB.
So I've jobs table that contains job. And categories table that contains category.
job can have multiple categories.
Is there a laravely way of normalizing the relationship?
Schema::create('jobs', function($table)
{
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('slug');
$table->string('title');
$table->string('excerpt')->nullable();
$table->text('content');
$table->integer('delivery');
$table->integer('price');
$table->unique(array('user_id', 'slug'));
$table->timestamps();
});
Schema::create('categories', function(Blueprint $table)
{
// These columns are needed for Baum's Nested Set implementation to work.
// Column names may be changed, but they *must* all exist and be modified
// in the model.
// Take a look at the model scaffold comments for details.
// We add indexes on parent_id, lft, rgt columns by default.
$table->increments('id');
$table->integer('parent_id')->nullable()->index();
$table->integer('lft')->nullable()->index();
$table->integer('rgt')->nullable()->index();
$table->integer('depth')->nullable();
// Add additional columns here (f.ex: name, slug, path, etc.)
$table->string('name')->unique();
$table->string('slug')->unique();
$table->string('description')->nullable();
});
My first instinct is to create an intermediary table that holds relationship:
Schema::create('jobs_categories', function($table)
{
$table->increments('id');
$table->integer('job_id')->unsigned();
$table->integer('category_id')->unsigned();
$table->unique(array('job_id', 'category_id'));
});
But I'm not sure how to proceede, what would I do if I want to get categories along with all $jobs?
What do I do if I want to get $job category?
Is hasOne, hasMany a better suited for this?
What you're describing is a many-to-many relationship. And yes, a pivot table like jobs_categories is needed. Here's how you do it following Laravels naming convention and making use of relationships:
Pivot table
jobs_categories is fine but Laravel likes category_job (singular and alphabetical order) (This way you don't have to specify the table name in your relation)
Schema::create('category_job', function($table){
$table->increments('id');
$table->integer('job_id')->unsigned();
$table->integer('category_id')->unsigned();
$table->unique(array('job_id', 'category_id'));
// foreign key constraints are optional (but pretty useful, especially with cascade delete
$table->foreign('job_id')->references('id')->on('jobs')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
});
Relationships
Job model
public function categories(){
return $this->belongsToMany('Category');
}
Category model
public function jobs(){
return $this->belongsToMany('Job');
}
Usage
Jobs with categories eager loaded
$jobs = Job::with('categories')->get();
Access categories of a job
$job = Job::find(1);
$categories = $job->categories;
Visit the Laravel docs for more information on Eloquent relationships

Categories