I have 4 tables. Two of them are monomorphic and two of them are polymorphic.
Monomorphic:
Templates, Modules
Polymorphic:
Documents, Images
Now, templates and modules have both documents and images and each Template has many Modules and modules have foreign key that is set to cascade on deletion of templates.
Now, if I delete a Template the associated Modules will be deleted but the associated polymorphic relations of Module will stay in Database. I haven't tried anything because I am completely clueless.
Anything I could do to automatically delete associations of Module when Template is deleted? I think the deletion here in this is being handled by Database itself and Eloquent doesn't have anything to do with it.
Because it is a polymorphic relationship, the cascading delete cannot be handled by a foreign key.
If you still want the deletes to be handled at the database level, you will need to write some type of database trigger functionality.
There are also a couple options if you want to handle this at the application level.
One option is to update your code so that everywhere you delete your Template, you also make sure to delete all of it's polymorphic relations.
Another option would be to create an event handler for the deleting event. The deleting event is fired by Eloquent whenever you delete an Eloquent model. Inside this deleting event, you can access the polymorphic relationship and delete them, as well.
If the deleting event method sounds okay, there is a package that implements all of this for you, and makes it very easy to setup for your models: shiftonelabs/laravel-cascade-deletes. Full disclosure: I wrote the package.
With this package, you just add the CascadesDeletes trait to your Template model, and then add a $cascadeDeletes property that contains an array of all the relationships to delete when a Template instance is deleted.
It's not fully automatic, but I handle it very easy with the destroy() Eloquent method. https://laravel.com/docs/8.x/eloquent#deleting-an-existing-model-by-key In addition, when you will use it with Laravel Queues, it works like a charm...
Example:
$template = Template::find(1);
Module::destroy($template->modules);
$template->delete();
You can actually use delete method on both types of relationship:
$template = Template::find(1);
$template->modules()->delete();
$template->images()->delete();
$template->delete();
Key note here is that $template->modules returns a collection instance while $template->modules() return an eloquent relationship where you can chain delete() method.
Related
I've been having this question for quite a long time. I guess it's more of a design problem. So I need to create a User with a mentor role that has many tutorships, but in the create user view I want to be able to add as many tutorships as I want. Once the tutorships are created, I want to be able to perform CRUD operations on them.
However, I want to be able to do this before actually saving its parent model (User) in the database. What is the common approach here? Am I supposed to create and then persist each Tutorship with an empty foreign key until I save the user? Or is it better if all the Tutorships are "floating around" until I save my user?
I worked through this earlier. I had created a trait I used on my models to allow setting relations and then I had to override the save and push on the model to work properly.
Set hasOne relation to new instance of child model
So I have a lot of controllers that will be created by one user. So on every save/create/update I want the user's ID to be saved the resource's user_id column in the database.
I know that before the actual database update I could go like
$resource->user_id = Auth::user()->id;
but this seems pretty unclean and I don't wanna do this for all the create/update actions I have spread across multiple controllers.
What would be the best and cleanest way to approach this issue?
If you are using Eloquent ORM to define $resource you can define Events for that model, that will be executed (if you wish) after or before every create, update, save, delete or restore action on that model. You can see the documentation here: Laravel 5.1 Model Events Documentation
Create a trait that hooks into the model’s saving event, and set the user ID there.
I used to work on Yii and now I'm building a new project on Yii2.
On Yii there was the function beforeDelete() and afterDelete() which allowed me to add the code there and delete related rows from junction tables etc..
My question is: On Yii2, is there another way to do this through an event or the database its self(on delete event on indexes)? What is considered to be good practice for these procedures?
Thanks!
Usually it's handled with foreign keys and cascade deletion. In this case you don't have to write any additional code in deletion event handlers.
But, for more complex situations you can use the same ActiveRecord event handlers beforeDelete() and afterDelete(). It's better to delete related records in afterDelete() event after deletion of main model.
Official docs:
beforeDelete()
afterDelete()
I have my models setup as a many-to-many using through with a pivot table. However, I would like to add some extra data into the pivot table.
In the past (kohana 3.0) I was able to provide extra data with the add method
$obj->add('alias', $related, array('extra'=>'data'))
But its seems in Kohana 3.3 that the add method does not provide the third parameter for extra data, and I cannot seem to find how to do this short of after saving, adding more data then re-saving.
This isn't supported anymore since Kohana 3.1.
The reason they removed it (Source: http://dev.kohanaframework.org/issues/3754):
We decided to remove this because it's better to use a through model
if you need to put data in your pivot table. Inserting the data
directly in the add() method bypasses validation and filtering that
would normally be in your model. Use a model if you need data in your
through table. We won't be changing this.
You now have to make a model for the pivot table and place the additional information in that model.
Then instead of using has_many "through" (n:n) you should use has_many (1:n) relationship for both tables to the pivot table.
I hope this answers your question.
What is the method to save and update Many to Many relationship in Yii framework?
There is a better implementation as behavior.
http://www.yiiframework.com/forum/index.php?/topic/6905-please-test-my-ar-enhancement-automatically-sync-many-many-table-when-calling-save/
Unless you create a model for the table between the two main tables, your only option is to use DAO (Database Access Object) and specify SQLs with it.
Have a look at how blog demo accomplishes this task.
use MANY_MANY relationship type to setup many to many connection between Models (An associative table is needed to break a many-to-many relationship into one-to-many relationships)
And now you can use all relational functions of Active Records
Yii Framework - The Definitive Guide to Yii: Working with Databases-Relational Active Record
The following extension does what you want...
Yii Framework - Extension: cadvancedbehavior
An important thing to note: On each update, the extension clears all previous records and creates new ones. So I wouldn't use it when the intermediatry table contains extra data other than the foreign keys.
you could set that up in mysql level..by going to relational view under each table in phpmyadmin and provide necessary relational condition..and use MANY_MANY in the model class inside relations..
The question is too common.
Usually data components with MANY to MANY relationships appear sequentially and independently. So you just need to do one insert action after another.
If your relationship needs dependent update you should user SQL triggers on the DataBase level. That'll ensure integrity of data and give a quite good separation in business logic of the application.
CREATE TRIGGER some_trigger
AFTER UPDATE ON some_table
...
END IF;
A similar way is to incapsulate relational data in one logical model on PHP level (and e.g. manipulate with 2-3 AR models there) and emulate SQL triggers logic in it.