Common question I guess, but I can't resolve it despite the informations I found online.
I've a sequence of hasMany relations :
User has many clients has many contracts has many materials.
I did my best but I find myself confronted to this error :
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
(SQL: create table clients (id int unsigned not null, user_id
int unsigne d null, ...) default character set utf8mb4 collate
utf8mb4_unicode_ci engine = InnoDB)
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key
constraint
Migrations :
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->engine = 'InnoDB';
// Keys
$table->increments('id');
// Other
...
$table->timestamps();
});
}
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('clients');
Schema::drop('users');
Schema::enableForeignKeyConstraints();
}
}
class CreateClientsTable extends Migration
{
public function up()
{
Schema::create('clients', function (Blueprint $table) {
$table->engine = 'InnoDB';
// keys
$table->unsignedInteger('id')->unique();
$table->primary('id');
$table->unsignedInteger('user_id')
->nullable();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('cascade');
// others
...
});
}
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('contracts');
Schema::drop('clients');
Schema::enableForeignKeyConstraints();
}
}
class CreateContractsTable extends Migration
{
public function up()
{
Schema::create('contracts', function (Blueprint $table) {
$table->engine = 'InnoDB';
// Keys
$table->increments('id');
$table->string('contract_number')->unique();
$table->unsignedInteger('client_id');
$table->foreign('client_id')->references('id')->on('clients')
->onDelete('cascade');
// Others
...
});
}
public function down()
{
Schema::disableForeignKeyConstraints();
Schema::dropIfExists('materials');
Schema::drop('contracts');
Schema::enableForeignKeyConstraints();
}
}
class CreateMaterialsTable extends Migration
{
public function up()
{
Schema::create('materials', function (Blueprint $table) {
$table->engine = 'InnoDB';
// Keys
$table->increments('id');
$table->string('contract_number')->unique();
$table->unsignedInteger('contract_id');
$table->foreign('contract_id')->references('id')->on('contracts')
->onDelete('cascade');
// Others
...
});
}
public function down()
{
Schema::drop('materials');
}
}
What am I doing wrong ?
You should add ->unsigned() to all your key columns you have.
Please use this instead of unsignedInteger() and set the type to integer()
Are you sure that your migrations are running in the correct order? They should be running in the order you provided in your example code. I can't seem to recreate the error on my end using your exact example migrations.
The order is determined by the date at the beginning of the migration's filename. Alternatively, you could create all these tables in the same migration to force the order that way.
Related
I have a "types" table which contains only ID and Name, the relation works on the first object but returns null on the following objects. Here is what my JSON looks like:
{"id":1,"type_id":1,"name":"test1","enabled":1,"measurement_type":{"id":1,"name":"test"}},
{"id":2,"type_id":2,"name":"test2","enabled":0,"measurement_type":null}]},
{"id":3,"type_id":1,"name":"test3","enabled":1,"measurement_type":null}]}
Here are my relations:
MeasurementFields Model
public function measurement_type() {
return $this->belongsTo(MeasurementType::class, 'type_id');
}
MeasurementTypes Model
public function measurement_type() {
return $this->belongsTo(MeasurementData::class);
}
In this Model I already have a measurement_field function which declares a belongsTo to MeasurementData (different Model) So, how do I name the new function with hasMany for types?
My Controller:
public function index()
{
return JsonResource::collection(MeasurementField::with('measurement_type')->get());
}
They all contain data, as you can see from the JSON, the relation just doesn't do anything with it.
My migrations:
Schema::create('measurement_types', function (Blueprint $table) {
$table->id()->autoincrement();
$table->string('name');
});
Schema::create('measurement_fields', function (Blueprint $table) {
$table->id()->autoincrement();
$table->foreignId('type_id')->constrained('measurement_types');
$table->string('name')->unique();
$table->boolean('enabled');
});
I think your measurement_type has many measurement_field.
and I guess you have to put this in your MeasurementField Model:
public function measurement_type() {
return $this->belongsTo(MeasurementType::class, 'type_id');
}
2019_04_23_164151_create_contacts_table.php migration file
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateContactsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('first_name');
$table->string('last_name');
$table->string('surname');
$table->timestamps();
});
Schema::create('contacts_relations', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('phone_id')->nullable()->default(1);
$table->unsignedInteger('contact_id')->nullable()->default(1);
});
Schema::create('contact_phone', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('phone_number');
$table->unsignedInteger('contacts_relations_id')->nullable()->default(1);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('contacts');
}}
2019_04_24_183110_contacts_relations.php foreign key setter
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class ContactsRelations extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('contacts_relations', function (Blueprint $table) {
$table->foreign('contact_id')->references('id')->on('contacts');
});
Schema::table('contact_phone', function (Blueprint $table) {
$table->foreign('contacts_relations_id')->references('id')->on('contacts_relations');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
}
}
run php artisan migrate: fresh and get
SQLSTATE [HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table contacts_relations add constraintcontacts_relations_contact_id_foreign foreign key (contact_id) referencescontacts (id ) on delete cascade on update cascade)
You should make sure all columns are eact same type. For example in table contacts the id column is unsigned big integer, so when you create contact_id column in contacts_relations instead of:
$table->unsignedInteger('phone_id')->nullable()->default(1);
it should be:
$table->unsignedBigInteger('phone_id')->nullable()->default(1);
Similar thing for contacts_relations_id column
Hi i want to create a foreign key but nothing work and i don't understand whyenter image description here
enter image description here
Please provide more info about table type, for now based on info that you type I can suggest you check are you using InnoDB tables? does FOREIGN KEY in table one corresponding to PK in table 2? are they have same types and length?
articles table
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateArticlesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('title' , 255);
$table->text('content');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('articles');
}
}
category table
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCategoryTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('category', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('category');
}
}
I have two migrations as shown below:
2016_02_03_071404_create_company_users_table.php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCompanyUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('company_users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('company_id')->unsigned();
$table->foreign('company_id')->references('id')->on('companies');
$table->char('role', 20);
$table->text('first_name');
$table->text('last_name');
$table->integer('age');
$table->string('email')->unique();
$table->text('password');
$table->text('login_type');
$table->string('phone_number')->unique();
$table->integer('verified')->default(0);
$table->text('profile_picture');
$table->text('facebook_id');
$table->text('twitter_id');
$table->text('linkedIn_id');
$table->text('google_plus_id');
$table->text('current_location');
$table->text('established_year');
$table->text('device_type');
$table->text('device_token');
$table->text('device_model');
$table->text('device_os_version');
$table->text('last_login');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropifExists('company_users');
}
}
2016_01_28_144808_create_jobs_table.php
<?php
use Carbon\Carbon;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateJobsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('job_title');
$table->text('job_description');
$table->text('job_industry');
$table->text('job_location');
$table->integer('job_experience');
$table->text('employment_type');
$table->bigInteger('recruiter_id')->unsigned();
$table->foreign('recruiter_id')->references('id')->on('company_users');
$table->tinyInteger('status')->default(1);
$table->timestamp('posted_date')->default(Carbon::now()->toDateTimeString());
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropifExists('jobs');
}
}
When I run php artisan migrate I get the following error:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table jobs add constraint jobs_recruiter_id_foreign foreign
key (recruiter_id) references company_users (id))
[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
Please help.
I figured it out... it was basically the order of execution of the migration files. So i changed the timestamps of the migration files to reorder the execution.... Works like charm.
I'm building out my first project in Laravel and have run into a bit of a snag with a one to many relationship between two tables.
Historically, I would have done something like this in SQL to achieve my end goal:
SELECT tag_key.key
FROM tag
LEFT JOIN tag_key
ON tag.tag_key_id = tag_key.id;
With Laravel, I'm trying to do things the ORM way and am getting hung up, probably on a naming thing somewhere down the pipe. Here's the code:
Part 1: Migrations:
"tag_keys" table
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTagKeysTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tag_keys', function (Blueprint $table) {
$table->increments('id');
$table->string('key', 128);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('tag_keys');
}
}
"tags" table
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTagsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('value', 128);
$table->integer('tag_key_id')->unsigned()->index();
$table->foreign('tag_key_id')->references('id')->on('tag_keys')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('tags');
}
}
Part 2: Models:
"TagKey" model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class TagKey extends Model
{
protected $fillable = [
'key'
];
protected $dates = [];
protected $table = 'tag_keys';
/**
* Tag Keys have many Tags
*/
public function values()
{
return $this->hasMany('App\Tag');
}
}
"Tag" model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
protected $fillable = [
'value',
'tag_key_id'
];
protected $dates = [];
/**
* Tag values belong to Tag Keys
*/
public function key()
{
return $this->belongsTo('App\TagKey');
}
}
Independently, they both work just fine. However, when I jump into tinker and try this (given there is a valid row in both the "tag" and "tag_key" tables and given that id 1 in the "tag" has the value of 1 in the "tag_key" table under the "tag_key_id" column):
$tag = App\Tag::first();
$tag->key;
=> null
What am I missing here? How do I build this association?
When the foreign key name doesn't follow Eloquent conventions ("snake case" name of the owning model and suffix it with _id), you should specify it in the relationship:
TagKey object:
return $this->hasMany('App\Tag', 'tag_key_id');
Key object:
return $this->belongsTo('App\TagKey', 'tag_key_id');
More info in the documentation