Should 'Cascade on Delete' be Done via Hook or Model?

Here is the scenario: let’s say that we have a Blog, where at the end of each Article we can have an optional list of ‘Related Articles’. The ‘Related Articles’ are implemented in the Panel as a TAGS field: the field lists other articles’ titles, but stores their ID.

Now, whenever an existing article is DELETED from the site, we must do a check to see whether that article is listed as a ‘related article’ in any article pages - and if so, that reference must be deleted, before the actual article itself is deleted - akin to a ‘cascade delete’ on a database. So, how do we do this the most ‘elegant, Kirby 3’ way? More specifically: do we use a hook or a model?

The obvious way to implement this would be to write a function in the 'page.delete:before' hook. But that hook would trigger on the deletion of every page, not just article pages, so we’d have to start the function by doing a check - not very optimal.

The more “OOP”-ish way to handle CRUD functions on data is to put all those functions in the model - e.g., create an ArticlePage model class that extends the parent’s “delete” method to add additional checking operations it will do on ‘delete’. That ‘feels’ like the ‘proper’ way to do it, as the method would then only be called when Article pages are deleted - not all pages - and keeps all data-management operations inside the model. However, there is very little documentation in the Guide about extending the default CRUD functions, and even a warning about being careful when overriding the Page class - so I’m not sure whether this is actually the best way to go about it…

Any guidance from the Kirby Gods would be appreciated! :slight_smile:

Two options that i can think of:

  1. I would probably make a route that rips through all the pages and lists out the related pages that do not exist in a table, and which page(s) is linking to them. Then i can hunt them down manually.
  2. Use the related plugin which uses the tags field you already have, but doesn’t store them, it just gives you back what they are in a collection. This way avoids the deletion problem you describe.

The easiest way would indeed be to use the Related or Similar plugins to find related pages automatically.

What you have to keep in mind when overriding methods in a model is to make sure you use all same parameters and return types.

I’m not sure this is the best way though, and would probably prefer a hook that does it’s job in the background without interfering with the method even if it needs that little if-statement.

Thank you for the guidance, guys! I hadn’t thought of using a plugin to do the search.

Is there a way to quickly update the values of a field, programatically, once I find the pages I need? Example: I have a collection of pages now, all of which have a ‘tag’ in a tags field, which I need to remove. So, I don’t need to delete the pages, I just need to remove one value from their tags field. I thought there would be a built-in Kirby field method to do it, but can’t find it…

You can use $page->update() to change the values of fields individually.