Skip to content

Instantly share code, notes, and snippets.

@marlenesco
Last active October 8, 2022 22:41
Show Gist options
  • Save marlenesco/6e31ebc12f78583a9ae417ac0f6647e3 to your computer and use it in GitHub Desktop.
Save marlenesco/6e31ebc12f78583a9ae417ac0f6647e3 to your computer and use it in GitHub Desktop.
Terminology in Symfony and Doctrine. Record vs Entity vs Document vs Model

I was just asked to write a small summary about the difference between a model and an entity. As I am too lazy to think up another topic for today I will just jump on that. And actually I wrote about this before as it can be quite irritating to see model folders in some bundles and entity folders in others. So what is what?

Before Doctrine 2.0 we were used to the ActiveRecord pattern in the symfony world. So let’s start from there.

The Record

is an object representation of a thing in the real world. It has some attributes that the real thing has as well (i.e. age, size, color, ..) and some methods the real thing can perform as well (i.e. walk, run, bark, ..).

The record in an ActiveRecord pattern also knows how to be persisted as it has a save() method and some other persistence related functionalities. To avoid duplicated code all this persistence code is written in a generic way and inherited by all record classes.

This makes record classes and eventually record objects very heavy and it doesn’t really follow the separations of concerns principle as it mixes domain logic (the thing) with database logic.

The Entity

is used by the UnitOfWork pattern in Doctrine 2.0 ORM (and in Hibernate in the Java world) and is also an object representation of a thing in the real world. It has the same attributes and methods as the record would have but it does not know about its persistence. It’s basically a POPO (plain old PHP object). This allows these classes and objects to be very lightweight.

The persistence is handled by an EntityManager instead.

The Document

is yet another object representation used for document centric databases like MongoDB, CouchDB or other NoSQL implementations. In Doctrine 2.0 ODM its implementation is very similar to an entity but as the data of NoSQL databases is handled very different from relational databases like MySQL and others it makes sense to use a different terminology.

This differently handled data also affects the document as that has to access its own data differently than an entity would.

The Model

is a conceptual object representation of a thing. This term could be used for all the above. A record is a model just as an entity is or a document. The term describes an object representation of a thing.

So if you want to create a bundle with some models in it and you want your bundle to be independent of any persistence layer you would create model classes and interfaces that define the thing.

You would define and / or implement everything in there that is not specific to any persistence implementation and you would use a related entity or document class via delegation to handle the specific stuff.

This is done for example in the FOSUserBundle which defines a User model. This User model is used throughout the bundle but doesn’t have a complete implementation to access its own data (I didn’t look but I think it could be an interface only). The final implementation is done in an entity class and another in a document class so no matter whether you use MySQL or MongoDB you can still work with the same User model. You can even switch from one to the other without changing your code as it always uses the model which is independent from the entity or document.

Do You have to follow this?

In an ideal world almost every bundle should come with a model abstraction and related entity and document implementations. In the real world though it doesn’t make sense to implement something that you have no use case for yet. So if you use a relational database you will only need an entity and should not care about any document implementation.

However the model class is easy to create and use and I think it could be considered best practice to always have a model abstraction even if you have only one specific implementation underneath. This way you or anyone else can easily add another implementation to your bundle without having to refactor a lot of code.

But if you think that won’t ever be necessary I don’t think it’s an evil sin to go with just the entity or just the document. :)

Note

The original article was found in WebArchive via a StackOverflow question

Author

Christian Schaefer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment