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
Related
I'm trying to change the data type (from string to boolean) of 5 columns in my database, but it's showing an error that i have no idea what is the meaning.
My migration is this:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ChangeFieldDataType extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('categoria_pneu')->change();
$table->boolean('categoria_dicas')->change();
$table->boolean('categoria_servicos')->change();
$table->boolean('categoria_dicas_gerais')->change();
$table->boolean('categoria_variados')->change();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('categoria_pneu');
$table->dropColumn('categoria_dicas');
$table->dropColumn('categoria_servicos');
$table->dropColumn('categoria_dicas_gerais');
$table->dropColumn('categoria_variados');
});
}
}
The erros that's showing, is this:
I don't know what is the meaning of the error, since i'm trying to change the type to BOOLEAN and not TINYINT (i don't actually know if it's the same...)
I am trying to make a 3 models relationship in Laravel 6 and Foreign keys won't work, becouse i get this error:
Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'products.product_id' in 'where clause' (SQL: select * from `products` where `products`.`product_id` = 1 and `products`.`product_id` is not null limit 1)'
I have a 3 table (the tables are: users, cartItems, products) relationship . The foreign key that refers user's id into cartItems seamns to work, but the one that refers product's id into cartItems don't .
The cartItems table migration:
Schema::create('cart_items', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('product_id');
$table->timestamps();
$table->foreign('product_id')->references('id')->on('products');
});
The products table migraton:
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('productName');
$table->text('description');
$table->integer('price');
$table->string('image');
$table->timestamps();
});
The cartItem model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class cartItem extends Model
{
public function user() {
return $this->belongsTo(User::class);
}
public function product() {
return $this->hasOne(Product::class, 'product_id');
}
}
The product model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $guarded = [];
public function cartItem() {
return $this->belongsToMany(Product::class);
}
}
The user model:
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function cartItems() {
return $this->hasMany(cartItem::class);
}
}
$table->foreign('product_id')->references('id')->on('products');
expects the products table to be created already. Migrations run in filename order, so make sure your products table migration has an earlier "date" stamp than the cart_items table migration.
If you are specifying xxxxx_id columns in the cartItems table, then cartItem is the child model, not the parent. Otherwise you might need to rethink your relationships.
To fix as-is (and leave the migration the same), change your Eloquent relationships to:
// Product.php
public function cartItems() {
return $this->hasMany(cartItem::class);
}
and its inverse:
// cartItem.php
public function product() {
return $this->belongsTo(Product::class);
}
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');
I'm trying to delete related data that has a many-to-many relationship
My complex model:
/**
* #return \yii\db\ActiveQuery
*/
public function getComplexDocument()
{
return $this->hasMany(ComplexDocument::className(), ['complex_id' => 'id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getDocuments()
{
return $this->hasMany(Documents::className(), ['id' => 'document_id'])
->via('complexDocument');
}
In beforeDelete I do the following:
public function beforeDelete()
{
foreach ($this->documents as $document){
var_dump($document);
}
return parent::beforeDelete();
}
Deletion does not happen, I checked and all hasMany connections return NULL.
In debug I see the following
I did this way:
public function delete()
{
foreach ($this->documents as $document){
$document->delete();
}
return parent::delete(); // TODO: Change the autogenerated stub
}
Everything works, all related documents are deleted, but it seems strange to me. In fact, this should be in beforeDelete (), but why are not links returned and therefore not deleted, so it should be, or is it a shortage of the framework?
I'm having trouble with a Laravel 5 relationship. I have 2 models Crew and Event with the corresponding tables crews and events. Crews have many events, and events have one crew. I set up my models and migration as follows:
Schema:
//Crews
Schema::connection('scheduling')->create('crews', function ($table) {
$table->increments('id');
$table->text('name');
$table->boolean('solo');
$table->boolean('active');
$table->text('phone');
});
//Events
Schema::connection('scheduling')->create('events', function ($table) {
$table->increments('id');
// ...
$table->integer('crew_id')->unsigned();
$table->foreign('crew_id')->references('id')->on('crews');
$table->text('notes');
// ...
$table->timestamps();
});
Models:
namespace App\Models\Scheduling;
use Illuminate\Database\Eloquent\Model;
class Crew extends Model {
public $connection = "scheduling";
public $table = "crews";
public function events() {
return $this->hasMany('App\Models\Scheduling\Event', 'id', 'crew_id');
}
public static function active() {
return Crew::where('active', 1)->get();
}
}
namespace App\Models\Scheduling;
use Illuminate\Database\Eloquent\Model;
class Event extends Model {
public $connection = "scheduling";
public $table = "events";
public function crew() {
return $this->belongsTo('App\Models\Scheduling\Crew', 'crew_id', 'id');
}
}
If I run Crew::find(102)->events; I end up with an empty collection.
If I run Events::where('crew_id', 102)->get(); I end up with the list of events I expected.
Any idea what I'm doing wrong here?
Your definition of events relation is invalid - you pass the arguments in wrong order.
Replace:
return $this->hasMany('App\Models\Scheduling\Event', 'id', 'crew_id');
with
return $this->hasMany('App\Models\Scheduling\Event', 'crew_id', 'id');
or simply
return $this->hasMany('App\Models\Scheduling\Event');
as you are using the default values for the column names, so no need to pass them to the relation definition.