Preventing removal of entity - symfony

I have an entity (eg Image) which is related to many other entities (eg Product or Category). I would like to know which is the best way to prevent the removal of an entity if a relation exists somewhere else (eg I should not be able to delete an Image if it is related to a product). My thoughts are either searching for relations in a repository class and returning results, or doing 'something' at the preRemove lifecycle event of the entity. Which is the best Symfony2 way for preventing removal of related entities?

As long as cascade delete is not set, any directionally entity will prevent delete of the related entity. If your associations are not birectional, you'll have to query form the backside as well.
To expand upon CJ's answer, you may remove delete links, but you will also have to check the entity in controller as well, because any url hacker can delete an object if its id is known.

What I would suggest is you can better of disabled the form delete link when there is a relationship between entities. In that way you can even make the customer understand that there is related entity and he should not remove it before removing the relationship.
You can always check the entity before deleting it and when you actually call certain process in symfony on an entity you actually work on the entire object of that particular entity which gives access to all the values of that entity. So you can check it at that particular point and make conditional statement.
It my personal believe that you should not try to import excess library functions for minor things which can be achieved by you without them. this would make you code easier to understand and even lighter as the prospect for including extra libraries which will most likely have more than what you need

Related

EF Core audits for cascade deleted values

I have an audit mechanism for a project built with ef-core code first approach. I've set the "DeleteBehavior" property to cascade for some tables in "OnModelCreating" function. When I delete an entity, the other one deleted automaticly by cascade delete behavior. That's all good for now and I need to get all deleted entities, but I cannot. The ChangeTracker doesn't contain the cascade deleted entities. How can I get the cascade deleted values? Is there any way to do this?
Cascade Delete happen on the database side. Entity Framework doesn't need to be aware which entity will be deleted.
Entity Framework only tracks changes and delete the base object.
Edit: Answer subquestions
You are right. I'm the owner of EF+.
Technically, a library could handle this, but this will come with a severe performance drawback. I'm not aware of any feature or library which handle the cascade delete scenario for auditing.
Suggestion?
There is some suggestion, but I'm pretty sure you will not like any of them, and I don't either recommend them for performance reason:
Do not use cascade delete (force you also retrieving/deleting related entities)
Create ON DELETE Trigger and Log at database side.
I don't think a good solution exists for this scenario.

Is this a good practice to use one entity in two different entities in a oneToMany Relationship?

I'm actually having 3 entities: Bounty, Document, and Comment. When i first made the Comment entity, it was to serve the document Commentary purpose. Later i have added a newer entity called "Bounty", and i was expecting to use the same Comment entity that i was already using in the Document entity.
I wish to avoid having one DocumentComment entity, and another BountyComment entity.
Is having one Comment Entity is a good way to procede, or should i rather separate them in two different entities ?
If grouping entites is a good practice, how can i make them fit when there can be duplicate entry ?
If both identities have the exact same structure and this fact is never going to change, you could group them together. However, every comment belongs to some other entity, so if it belongs to a Document, it needs a property "document". If it belongs to a Bounty, it needs a property "bounty". So the two are not the same.
If you are using ORM (e.g Doctrine), you can use a shared base class and extend from it. Doctrine will create seperate tables for each type, but you can share functionality between the entity classes. See http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html

Doctrine - Creating and mapping an entity based on a SQL query?

Would it be possible to create a similar entity based on another one? For example, what if I'd like to have user specific tables that are based on one entity. Without any ORM I would just create the same table with a different prefix and do the queries on the table with the specific prefix.
Not sure how to tackle the problem with Symfony 2.5 and Doctrine and I just can't find a concrete example anywhere around, but seems like the solution might be around the Doctrine Event Manager and the Load ClassMetadata event. I just can't make sense out of the documentation.
Without exactly knowing how your schema looks or what you're trying to achieve, it's hard to give a precise answer. But let's try:
If you have two entities which share a common set of properties, but differ in others, you basically do the typical OOP inheritance thing, you create an abstract parent class with the common stuff, and two children with their specific properties.
In Doctrine, there are different inheritance strageties. Read about them at http://doctrine-orm.readthedocs.org/en/latest/reference/inheritance-mapping.html
Each of them has their pros and cons. Basically, you can select if you want everything to be in one or in two tables. Set up a test case and check what works better for you.
Note: The class properties in an abstract superclass (no matter which strategy) must always be private.

Associated entity being persisted but no cascade option setted

In doctrine documentation I found: "By default, no operations are cascaded." (here http://bit.ly/1frPyLH)
But still one of my database entities is persisting it's associated objects, besides the fact that it has no cascade option in the association.
How can I prevent it from persisting the associated entities ?
It is true and the documentation is still not wrong. =P
Without going deeper on your problem, you need to be aware that by default Doctrine applies a concept called "persistence by reachability". This means that if you are creating a new entity and one of your associations is already managed by UnitOfWork (already known by Doctrine), it will "cascade" the operation.
The problem here is how you read about cascading. In reality, it's not the cascading factor that is updating the associated entity, but it's because it's already managed by Doctrine.
To solve this "problem", you need to modify the way you want Doctrine to deal with your entities by altering the Change Tracking Policy.
I hope this gives you enough information to solve your issue.

Updating comment count of the article on comment prepersist properly, with services

I have an Article and Comment entity (oneToMany)
On Comment prepersist lifecycle event I would like to count how many comments there are for this article and update Article's comment_count field.
If I understand symfony2 approach correctly, I need to write a service for this. Let's call it CommentCountManager.
My question is: How exactly do I make container available in entity so that I can get the CommentCountManager and triger the funciton that count comment for given article, and how do I access Doctrine's entity manager in my CommentCountManager so that I can actually run queries there?
Am I on the right path?
Your help is greatly appreciated.
You don't need to store the comments count in a separate column — you can count them on output. What you are trying to do is denormalization and I recommend avoiding it unless you absolutely need it for performance reasons — and only when you are sure that that part is causing the problems. But even then, query optimization and caching are much better alternatives to denormalization.
Making entities aware of the container is a bad idea too. If you need this, then you are doing something wrong.
To access an entity manager in a service, you need to inject it.

Resources