I'm trying to delete a user and automatically all his relations using 'cascade'. Not sure how to do it. I'm using mysql.
So far i've made this:
User Model
class User extends Authenticatable
{
use Notifiable;
//...
public function profile()
{
return $this->hasOne('App\Profile');
}
}
Profile Model
class Profile extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
Profile migration
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->integer('phone');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
And with tinker I'm tryng to do:
$user = App\User::firsts();
$user->delete(); // it deletes only the user
$user->profile->delete(); // it deletes only the profile
You could make use of Model Events:
class User extends Eloquent
{
public static function boot ()
{
parent::boot();
self::deleting(function ($user) {
// This will be executed right before the user is deleted
$user->profile->delete();
});
}
}
This way, whenever you call the delete() method on a User object, Laravel will fire the $user->profile->delete(); right before.
Rather than a database cascade you could delete the related model when the user is deleted by deleting the related model using the deleting event.
Include this in the Boot function of the User Model:
public static function boot ()
{
parent::boot();
self::deleting(function (User $user) {
$user->profile->delete();
});
}
Theres no need to do relationship staff for working with cascade. This code works fine for me -
Migration:
Schema::create('profiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->integer('phone');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
Controller:
Here ->delete() can delete both user and profile row
public function deleteUser(){
Auth::user()->delete();
return redirect()->back();
}
View Delete Link
Delete
Route
Route::get('/delete', 'HomeController#deleteUser')->name('deleteUser');
Related
I have 3 table, table Courses, table Sections, and table Syllabuses. Where table courses relation to table Sections and table Sections relation to table Syllabuses. To make clear below my table look like:
#Table Courses:
public function up()
{
Schema::create('courses', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->unsignedBigInteger('category_id')->default('1');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade')->onUpdate('cascade');
$table->string('title');
$table->string('status')->default('publish');
$table->text('content')->nullable();
$table->timestamps();
});
}
Table Sections:
public function up()
{
Schema::create('sections', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('course_id');
$table->foreign('course_id')->references('id')->on('courses');
$table->string('name');
$table->timestamps();
});
}
and the last table Syllabuses:
public function up()
{
Schema::create('syllabuses', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('section_id');
$table->foreign('section_id')->references('id')->on('sections')->onDelete('cascade')->onUpdate('cascade');
$table->string('title')->nullable();
$table->text('content')->nullable();
$table->text('description')->nullable();
$table->timestamps();
});
}
and now I'm stuck to display data from table syllabuses base on Sections's ID, where the sections display base on Courses's ID, because I don't know how to get the ID from each row which related to Secations's ID to put in Syllabus::where('section_id',???)->get();. Anyone who can help me much much appreciate. Hope u understand what I mean.
Below the image you can see, there I have put some note to make u understand. The problem in the green box one.
enter image description here
Define relations in your models first.
I assume your models are: Course, Section and Syllabus
// Model Course
public function sections()
{
return $this->hasMany(Section::class);
}
// Model Section
public function course()
{
return $this->belongsTo(Course::class);
}
public function syllabuses()
{
return $this->hasMany(Syllabus::class);
}
// Model Syllabus
public function section()
{
return $this->belongsTo(Section::class);
}
Now in your controller you can get your designated course by
// Controller Course
public function show($id)
{
$course = Course::with('sections', 'sections.syllabuses')->where('id', $id)->first();
}
In this query you have a model from "Course" table, related models from "Sections" table and all the related models from "Syllabuses" table. If you are using laravel's blade then you can simply access them by:
// course
{!! $course->your_attribute !!}
// to access sections
#foreach($course->sections as $section)
#endforeach
// to access syllabuses
#foreach($course->sections as $section)
#foreach($section->syllabuses as $syllabus)
// Here you will have syllabuses for individual sections
#endforeach
#endforeach
https://laravel.com/docs/8.x/eloquent-relationships#one-to-many
You need to study laravel relationships in your case you have belongsTo relation.
In your Syllabus model add.
public function section(){
return $this->belongsTo(Section::class, 'section_id');
}
Then you can use this will get all Syllabuses with related to there sections.
Syllabus::with('section')->get();
I use Laravel 8. I have 3 table. Course table, UserCourse, and User table. I want to get user courses. I tried it with tinker: Course::find(1)->user_courses -it works fine and give back me user_course.
UserCourse::find(1)->user_course - the problem is here, this will return me "null"
How can I get the User Courses?
Course table
Schema::create('courses', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->timestamps();
});
UserCourse table
Schema::create('user_courses', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
User table
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->string('username')->unique();
$table->string('password');
$table->timestamp('updated_at')->nullable();
$table->timestamp('created_at')->nullable();
});
Course.php
class Course extends Model
{
use HasFactory;
protected $fillable = [
'title',
];
public function user_courses()
{
return $this->hasMany(UserCourse::class);
}
}
UserCourse.php
class UserCourse extends Model
{
use HasFactory;
protected $fillable = [];
public function user_course()
{
return $this->belongsTo(Course::class);
}
}
Your database structure make it that the relation between course and user is a many to many relation with a pivot table in the middle.
Some correction you need to do for it to work seemingly with laravel conventions.
- The pivot table name should be course_user without a primary key
Schema::create('course_user', function (Blueprint $table) {
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
- Remove the UserCourse.php model since it's a pivot
- Define the relation courses in User model as follow
User.php
public function courses()
{
return $this->belongsToMany(Course::class);
}
- Define the relation users in Course model as follow
Course.php
public function users()
{
return $this->belongsToMany(User::class);
}
Now to get any user courses, just run User::find(1)->courses
Same thing to get the users that belongs to the same couses Course::find(1)->users
get courses that the user has not taken:
$userId = 1;
$courses = Course::whereDoesntHave('users', function($userQB) use($userId) {
$userQB->where('id',$userId);
})->get();
Thank you in advance
I have 2 tables as below
1) users
2) reviews
The schema I have created is like below
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('first_name',100)->nullable();
$table->timestamps();
});
Schema::create('reviews', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id')->unsigned();
$table->string('name',100)->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
When i am deleting the user, it is not deleting reviews belongs to the deleted user
I am deleting user like below
User::where('id',1)->delete();
is there any short and simple and perfect way to do them for all the eloquent models?
you can try this code in your parent model :
public static function boot()
{
parent::boot();
static::deleting(function ($model) {
$model->relations()->delete();
});
}
*update for softDeletes
public static function boot()
{
parent::boot();
static::deleting(function ($model) {
if($model->isForceDeleting()){
$model->relations()->delete();//or forceDelete if child also using softDelete
});
}
}
What I would like to do is every time I delete a ThoughtRecord I want to delete the comments that polymorphically belong to that ThoughtRecord.
ThoughtRecordController
public function destroy(ThoughtRecord $thoughtRecord)
{
$thoughtRecord->delete();
}
ThoughtRecord Model
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
Comment Model
public function commentable()
{
return $this->morphTo();
}
ThoughtRecord Table
$table->bigIncrements('id');
$table->integer('user_id');
$table->boolean('is_authorized')->default(false);
$table->string('title')->nullable();
$table->timestamps();
Comment Table
$table->increments('id');
$table->integer('commentable_id');
$table->string('commentable_type');
$table->integer('user_id');
$table->text('content');
$table->timestamps();
One option:
Manage cascade deletes with this package:
Package for manage cascade deletes
Second Option:
You Could Listen To An Events That Laravel Provide
protected static function boot()
{
parent::boot();
// cause a delete of a poster to cascade
// to children so they are also deleted
static::deleting(function ($poster) {
$photos->photos->delete();
$poster->comments()->delete();
});
}
Third Option:
When you are using a polymorphic relationship you probably also use it a Trait. If that's the case you can delete the relations in the boot method of the trait by hooking in to deleting event.
<?php namespace Company\Package\Traits;
/**
* This file is part of Package.
*
* #license MIT
* #package Company\Package
*/
use Illuminate\Support\Facades\Config;
trait ActionableTrait
{
/**
* Morph Many relation with Task.
*
* #return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function actions()
{
return $this->morphMany(Config::get('crm.action'),'actionable');
}
protected static function bootActionableTrait()
{
self::deleting(function ($model) {
$model->actions()->delete();
});
}
}
Option four:
Just simple code , Override delete method on Your model. If this model is deleted , delete other associated models.
public function delete()
{
$res=parent::delete();
if($res==true)
{
$relations=$this->youRelation; // here get the relation data
// delete Here
}
}
read it https://laravel.com/docs/5.8/eloquent-relationships#querying-polymorphic-relationships
I already have a database setup and I would like to create migration(s) from an empty db to current state.
How do I handle unsupported types (like Point) by Laravel migration?
Only solution I could think of was using DB::statement and writing raw SQL. Is there any better way?
Also, is there any converter from an existing DB to Laravel migration that properly handles these unsupported types?
There is a package that can do this for you: https://github.com/shiftonelabs/laravel-nomad/
It has a function with this signature:
public function passthru($realType, $column, $definition = null)
{
return $this->addColumn('passthru', $column, compact('realType', 'definition'));
}
That is used like
class CreateUsersTable extends Migration {
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->passthru('citext', 'name');
$table->passthru('citext', 'title')->nullable();
$table->passthru('string', 'email', 'varchar(255)')->unique();
$table->passthru('string', 'password')->definition('varchar(60)');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
}
It extends the BaseBlueprint class and uses the function addColumn
https://laravel.com/api/5.2/Illuminate/Database/Schema/Blueprint.html#method_addColumn