Question

Suppose I have an Asset entity that itself has multiple relations to others, e.g Category and Labels and Tag. If certain conditions are met, the Asset should be in a state, let's call it quarantine.

Let's say the Asset is in quarantine when it has no Category. How should I check for this condition?

I could add a flag in its entity isInQurantine and store it on persist/update. This will make querying cheap.

I could fiter the ArrayCollection via its filter method, yet this would mean loading all the results and then reducing the resultset. This might be a simpler approach, but I suspect it would bite me in the long run if the ArrayCollection would become large.

Finally, I stumbled across doctrine filters where it seems (haven't checked, might be completely wrong about it) I could also do filtering without the need for a db-flag the constraint will be applied before hydration.

I am unsure how to proceed.

I want a solution that keeps both performance (which I think excludes ArrayCollection-filtering) and maintainability in mind. As in the future, the requirements might change to include more than just the lack of Categories.

As for maintainability, I think it seems good that I can add and remove filters for Doctrine filters.

I would like some advise which up- and downsides the solutions have or if there is a way I have missed entirely.

Was it helpful?

Solution

You basically have 3 options:

  1. fetch the whole collection and filter afterwards (terribly slow = smell)
  2. fetch only the entries you need by checking the actual relations (pretty slow)
  3. store the relation-count and fetch by checking for the count (still slow + complex = smell)

Option 1 obviously doesn't make sense at all. Using option 3 you can easily end up in a corrupted application-state (the count/state-flag not matching the real state/count).

Now what's the solution? You should cache the result of option 2.

Create a postPersist / postUpdate / postRemove doctrine subscriber that triggers the renewal of the result-cache without letting the client wait.

Either perform the cache-warming inside a subscriber to the kernel.terminate event (after the response has been sent) ... or inside a periodically executed cronjob ( i.e. at a time where there is less user-activity ).

This way you ensure the result is definitely matching a real database state, have the best performance (no database-query the client has to wait for) ... and there is no unnecessary code bloating your entity + adding complexity.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top