email as a foreign key in larave - laravel

Can I make email as a foreign key ? $table->foreignId('email')->constrained('users')->onDelete('CASCADE'); . I wrote a seeder and is for an integer value for emai. I need to make email unique
This is my users table
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});

To create an Foreign Key association with email column of users table, you cannot use foreignId method as it creates unsignedBigInteger equivalent column.
You can create the foreign key association as
//Some other table - for eg lets say posts
Schema::create('posts', function(Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->string('author_email');
$table->foreign('author_email') // a column on posts table
->references('email') //name of the column on users (referenced) table
->on('users') //name of the referenced table
->onDelete('cascade'); //constrain
});
Then using this foreign key association you can define the author relation in Post model linking it to the User model
//Post.php - eloquent model class
public function author()
{
return $this->belongsTo(User::class, 'author_email', 'email');
}
Note: For this to work as expected, email column on users table must contain unique values i.e have a unique index (as you have in the migration of users table)
Laravel Docs - Migrations - Foreign Key Constraints

Related

Cannot add foreign key constraint - Laravel 9

I have posts table:
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('imid');
$table->string('name');
$table->text('body');
$table->timestamps();
});
and
images table:
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('imid');
$table->string('name')->nullable();
$table->longText('image_path')->nullable();
$table->timestamps();
});
I am trying to add a foreign field to existing posts table in a separate migration:
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->foreign('imid')->references('imid')->on('images')->onDelete('cascade');
});
}
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('imid');
});
}
But when I run
php artisan migrate
I get error:
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `posts` add constraint `posts_imid_foreign` foreign key (`imid`) references `images` (`imid`) on delete cascade)
It seems I do it right. What am I missing here?
Check that both your tables have the columns for which you create the foreign key (imid) and that these columns have the same types. You can use the following commands to do this:
DESCRIBE posts;
DESCRIBE images;
Next, check if posts table has no imid values which point to non-existing records in the images table (If they are - connect them to existing ones or remove them)
SELECT posts.id, posts.imid FROM posts
LEFT JOIN images ON posts.imid = images.imid
WHERE images.id IS NULL;
Make sure your tables are using InnoDB engine
SHOW TABLE STATUS WHERE name = 'posts';
if Engine != InnoDB then run:
ALTER TABLE posts ENGINE = InnoDB;
Finally, I suggest that you change the down method of your migration so that it does the reverse of the up method:
Schema::table('posts', function (Blueprint $table) {
$table->dropForeign('posts_imid_foreign');
});

Laravel Eloquent: Multiple Foreign Keys from One Primary Key

I am in-progress to create a project in Laravel.
I have two Database Table, which is created by migrations:
I want to setup multiple foreign key in database schema.
Table User
Schema::create('tr_users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email');
$table->timestamp('email_verified_at')->nullable();
$table->rememberToken();
$table->string('password');
$table->unsignedBigInteger('departement_id')->nullable();
$table->foreign('departement_id')
->references('id_departement')->on('tr_departements')
->onUpdate('cascade')
->onDelete('cascade');
});
Table Departrements
Schema::create('tr_departements', function (Blueprint $table) {
$table->bigIncrements('id_departement');
$table->string('name');
$table->timestamps();
$table->unsignedBigInteger('created_by')->nullable();
$table->foreign('created_by')
->references('id')->on('tr_users')
->onDelete('cascade');
$table->unsignedBigInteger('updated_by')->nullable();
$table->foreign('updated_by')
->references('id')->on('tr_users')
->onDelete('cascade');
});
What I want to know is how to describe relation in Models?
Edit:
My plan to use this relation is every users is belongs to departement, and any departement has many users, and every users has only one departement
If you are seeking One-to-One relationship from user to department then relation would be like this:
In your User model code would be like this:
public function department()
{
return $this->hasOne('App\Department');
}
And in your department model:
public function user()
{
return $this->belongsTo('App\User');
}
For multiple relationship you can refer laravel documentation

Cannot delete or update a parent row: Laravel

I want to delete a record in category table wherein it will also delete the subcategory record which has a the foreign key of category. How can I do this?
Also, an explanation would help as why it has happened. Thank you!
Controller
public function destroy(Category $category)
{
// return $category;
Category::where('id', $category->id)->delete();
Subcategory::where('category_id', $category->id)->delete();
return back();
}
Category migration
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Sub-category mgiration
Schema::create('subcategories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('category_id')->unsigned();
$table->string('subcatname');
$table->string('name');
$table->timestamps();
$table->foreign('category_id')->references('id')->on('categories');
});
this is simple because of the default delete: Restrict option in foreign key.
1.Add on delete cascade option to foreign key. This option will automatically remove any associated records from the subcategoires table when you delete the category record.
The modified fk statement looks like as follows:
ADD CONSTRAINT `category_subcategory_foreign` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE;
or you can go through
Laravel also provides support for creating foreign key constraints, which are used to force referential integrity at the database level. For example, let's define a user_id column on the posts table that references the id column on a users table:
Schema::table('posts', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
You may also specify the desired action for the "on delete" and "on update" properties of the constraint:
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
You need onDelete method. Just from Docs
$table->foreign('category_id')
->references('id')->on('categories')
->onDelete('cascade');

How to create foreign key by Laravel migration?

How can we make a referenced key and foreign key in laravel by migrations.
Think I have two migration files in database directory in laravel, both of them create a different table in my database.
the first migration creates a table that is for posts which has a column in the name of Id.
the second migration create comments table that has a column in the name of post_id. Now the Id column in posts table is referenced key and the post_id in comments table is foreign key, how can I connect these two columns together?
It would be better to set unsignedInteger for foreign key type
$table->unsignedInteger('category_id')->nullable();
$table->foreign('category_id')
->references('id')
->on('categories')
->onUpdate('cascade')
->onDelete('some action');;
Take the example where you have a users table and a user_address table. A user can have many addresses and an address belongs to a user.
Default user table
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
user_addresses table with user_id as the foreign key
Schema::create('user_addresses', function (Blueprint $table) {
$table->bigIncrements('id'); // by default the primary key is set to unsigned big integer
$table->unsignedBigInteger('user_id'); //associate the address with a user
$table->text('address');
$table->string('city');
$table->string('country');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
After defining the migrations, next step is to define the relationship in their respective model classes
In the User Model, add
public function address(){
return $this->hasMany(UserAddress::class );
}
And in the UserAddress Model, add
public function user(){
return $this->belongsTo(User::class, 'user_id');
}
you use like this.
$table->integer('userId')->unsigned();
$table->foreign('userId')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
If you're trying to create a foreign key constraint for a table that references the 'id' column on a 'users' table for example. For a better developer experience, you can write it in this way:
$table->foreignId('user_id')
->constrained('users')
->onUpdate('cascade')
->onDelete('cascade');
Schema::table('posts', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});

Many to Many on Laravel migration

I have 3 tables to connect each other. Tables name's roles, role_user, and users. I want to make migration on laravel and adding some constraint. and here's what in my role tables migration:
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('description');
$table->timestamps();
});
and here's my Users table migration:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('username')->unique();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->boolean('active')->default(0);
$table->softDeletes();
$table->rememberToken();
$table->timestamps();
});
and here's my role_user table migration:
Schema::create('role_user', function (Blueprint $table) {
$table->integer('role_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->unique(['role_id', 'user_id']);
$table->foreign('role_id')->references('id')->on('roles')
->onDelete('cascade')->onUpdate('cascade');
$table->foreign('user_id')->references('id')->on('users')
->onDelete('cascade')->onUpdate('cascade');
});
in my Migration order i put roles table on top of users already but i got this kind of errors:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `role_user` add constraint `role_user_role_id_foreign` foreign key (`role_id
`) references `roles` (`id`) on delete cascade on update cascade)
[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
Probably your problem was with the order of creation of migrations.
Laravel runs the migrations in order of creation using the timestamp in the file name , because of that, if you created them in the following order:
roles in 2018_06_02_023539_create_roles_table
role_user in 2018_06_02_023800_create_role_user_table
users in 2018_06_02_023815_create_users_table
The table users would not exist when referenced in the table role_user, thus causing an SQL error.
The most simple fix that you could do is renaming the role_user migration file in this way:
2018_06_02_023800_create_role_user_table => 2018_06_02_023820_create_role_user_table
Try this one on the pivot table
public function up()
{
Schema::create('role_user', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('role_id');
$table->unsignedBigInteger('user_id');
$table->timestamps();
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
I delete all my table and left just 4 tables :
create_user_table,
create_password_reset,
create_roles_table,
create_role_user
and everything works fine.
Till now I don't understand what makes these errors although I already put the same orders.
in table "role_user" replace columns type from integer to bigIncrements

Resources