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.
Related
I'm try to create many-to-many that link with customer and shop in laravel but stuck in this error (errno: 150 "Foreign key constraint is incorrectly formed") and still, not figure it out.
Here my customers table
Schema::create('customers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('shop_id');
$table->string('name');
$table->string('email');
$table->string('phone');
$table->timestamps();
$table->foreign('shop_id')->references('id')->on('shop');
});
Here my shops table
Schema::create('shops', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('customer_id');
$table->string('name');
$table->timestamps();
$table->foreign('customer_id')->references('id')->on('customer');
});
My Shop Model
protected $fillable = ['name'];
public function customer()
{
return $this->belongsToMany(\App\Customer::class);
}
My Customer Model
protected $fillable = ['name', 'email', 'phone'];
public function shop()
{
return $this->belongsToMany(\App\Shop::class);
}
Any Help? Thanks in advances....
Check your Schema -
Its should be shops not shop...
$table->foreign('shop_id')->references('id')->on('shops');
and similarly customers not customer...
$table->foreign('customer_id')->references('id')->on('customers');
Note for you. Don't use foreign command in table create command together.
Make sure always new migration file for adding foreign key's inside table.
Cause sometime its generate Errors while migrating ..
open your bash shell or PHP Storm Terminal or CMD
php artisan make:migration foreign_customer_id_at_table_shops --table=shops //you Can use your own migration name what you want
at foreign_customer_id_at_table_shops migration file
UP
$table->foreign('customer_id')->references('id')->on('customers');
DOWN
$table->dropForeign(['customer_id']);
Put the foreign key in relationship rather than in migration.
public function customer()
{
return $this->belongsToMany('\App\Customer::class','id','shop_id');
}
public function shop()
{
return $this->belongsToMany('\App\Shop::class','id','customer_id');
}
The relation of many-to-many need third table pivot table which you miss it.
for do that create new migration.
php artisan make:migration create_customer_shop
there is no need create model for pivot table
then you Schema pivot table something like this.
Pivot table
Schema::create('cutomer_shop', function (Blueprint $table) {
$table->increments('id');
$table->integer('customer_id')->unsigned();
$table->integer('shop_id')->unsigned();
$table->timestamps();
$table->foreign('customer_id')->references('id')->on('customers');
$table->foreign('shop_id')->references('id')->on('shops');
});
The two table shops and customers doesn't have any direct relations they have relation by just pivot table.
Note: make sure all three table id type increments('id') and all foreign key are $table->integer('shop_id')->unsigned(); otherwise give you incorrect format error.
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');
}
im having a error with my app, it looks averything fine, but is creating a wrong query, but i have my tables and models right, basically i have a registration of a user that can select more than one regions and industry/area. My error is:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'hjobs.region_user' doesn't exist (SQL: select `region_id` from `region_user` where `user_id` is null)
Model User:
public function regionsToWork(){
return $this->belongsToMany(Region::class);
}
public function industriesToWork(){
return $this->belongsToMany(Industry::class);
}
AuthController:
$user = new User();
$user->name = $data['name'];
...
$user->regionsToWork()->sync($data['region'], false);
$user->industriesToWork()->sync($data['industry'], false);
$user->save();
Tables DB: USER:
-id;
-email
...
user_industry:
id;
user_id;
industry_id;
user_region:
id;
user_id;
region_id;
Migrations user_region_table_creation
Schema::create('user_region', function($table){
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('region_id')->unsigned();
$table->foreign('region_id')->references('id')->on('regions');
});
user_industry_table_creation
Schema::create('user_industry', function($table){
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('industry_id')->unsigned();
$table->foreign('industry_id')->references('id')->on('industries');
});
It looks like the pivot table name is different than what it's expecting, region_user as opposed to user_region.
You can manually specify the pivot table name in your belongsToMany method like this:
return $this->belongsToMany(Region::class, 'user_region');
I have 2 models and both they aren't using the ID from the table, but the field internal_id. So i customized my pivot schema but i got stuck on connecting them. Im getting the error:
General error: 1215 Cannot add foreign key constraint (SQL: alter table `seoshop_category_product` add constraint seoshop_category_product_category_id_foreign foreign key
(`category_id`) references `seoshop_categories` (`internal_id`) on delete cascade)
The code for the migration is:
Schema::create('seoshop_category_product', function(Blueprint $table)
{
$table->increments('id');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('internal_id')->on('seoshop_categories')->onDelete('cascade');
$table->integer('product_id')->unsigned()->index();
$table->foreign('product_id')->references('internal_id')->on('seoshop_products')->onDelete('cascade');
$table->timestamps();
});
Both fields as seoshop_products.internal_id as seoshop_categories.internal_id are existing, column types are both int(11).
Can someone tell me what is going wrong?
Migrations for the tables seoshop_categories and seoshop_products
//seoshop_products
public function up()
{
Schema::create('seoshop_products', function(Blueprint $table)
{
$table->increments('id');
$table->integer('shop_id');
$table->integer('internal_id')->signed()->index();
$table->integer('internal_variant_id');
$table->string('visible');
$table->string('tags');
$table->timestamps();
});
}
//Table seoshop_categories
public function up()
{
Schema::create('seoshop_categories', function(Blueprint $table)
{
$table->increments('id');
$table->integer('internal_id')->signed()->index();
$table->datetime('seoshop_created_at');
$table->datetime('seoshop_updated_at');
$table->text('full_description');
$table->timestamps();
});
}
Okay so now i've create my table, and its working as how it should. I need to get my product with categories (many-2-many). So i use
SEOshopProduct::find(1)->with('categories')->get();
After a dd() the categories are empty and i've looked into my query how it is called:
[8] array(3) {
["query"] "select `seoshop_categories`.*, `seoshop_category_product`.`product_id` as `pivot_product_id`, `seoshop_category_product`.`category_id` as `pivot_category_id` from `seoshop_categories` inner join `seoshop_category_product` on `seoshop_categories`.`id` = `seoshop_category_product`.`category_id` where `seoshop_category_product`.`product_id` in (?)"
["bindings"] array(1) {
[0] 8
}
["time"] 0.37
}
The internal_id's of both products and categories is greater then 10.000 and i dont see it back in the query.
My models:
Product:
public function categories(){
return $this->belongsToMany('SEOshopCategory', 'seoshop_category_product', 'product_id', 'category_id');
}
Categories:
public function products(){
return $this->belongsToMany('SEOshopCategory', 'seoshop_category_product', 'category_id', 'product_id');
}
To setup the foreign key constraint, the field definitions need to match exactly. In this case, however, the seoshop_category_product.category_id field is defined as an UNSIGNED INT, but the referenced seoshop_categories.internal_id field is defined as a SIGNED INT. The same is true for the foreign key for your products.
So, you can either update the internal_id fields on your categories and products tables to be unsigned, or you can update your foreign key fields on your pivot table to be signed.
You can tell Laravel what the local and foreign keys are when you define the relationship in your model...
class Product extends Eloquent
{
public function categories() {
return $this->hasMany('Category', 'internal_id', 'id');
}
}
class Category extends Eloquent
{
public function products() {
return $this->hasMany('Product', 'internal_id', 'id');
}
}
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