Doctrine ORM vs phpmysql 6th edition

According to doctrine documentation am reading, it says concerning using

Entity classes

that all of the fields should be protected or private (not public) and this is the quote.

When creating entity classes, all of the fields should be protected or private (not public ), with getter and setter methods for each one (except $id ). The use of mutators allows Doctrine to hook into calls which manipulate the entities in ways that it could not if you just directly set the values with entity#field = foo;

While the 6th edition of phpmysql says this on page 553/554

In most cases, private properties are strongly preferred over public ones.
However, in the case of entity classes, you should use public properties.
The sole purpose of an entity class is to make some data available. It’s no good
having a class representing an author if you can’t even read the author’s name!

I understand that the pattern used by doctrine might slightly be different from the book approach but when you see statements like this, you get to wonder which is which. Which of the statement is wrong and which of the statement is right
@TomB and the entire house, please enlighten me

This is more of a philosphical debate. Keep in mind that doctrine encourages automatic generation of getters and setters. The properties are still basically public.

Personally I would not use Doctrine as an example of good design (it mixes all kinds of concerns together and has several layers of complexity that just add bloat) but that’s a long post for another day.

From a practical perspective you should differentiate between a data structure and an object. An entity is a data structure it’s only purpose is to move data around the application and can be (for the most part) substituted with an array. You need to be able to read data from an entity and display it somehow.

I’m surprised, that in a world of microservices where everything uses internal REST APIs this isn’t clearer.

If I can replace your entire ORM stack with json_decode(file_get_contents('database.json')) then I consider your ORM well designed. Incidentally, this is the primary philosophy behind Maphper: https://github.com/Level-2/Maphper

Thanks sir for the reply, I will go through those links and do more research on it while I await the reply of others as well

Doctrine uses your get methods to implement lazy loading. Assume, for example, you have a Book entity with a relation to an Author. When you first load the Book entity from the database, the Author will not be loaded. Instead, calling $book->getAuthor() will actually query the database and load the Author entity.

Doctrine accomplishes this by automatically generating a Book proxy class in which the getAuthor method is overridden. In most cases, you never even know a proxy is being used.

The whole process is know as lazy loading. Obviously if author is a public property there is no place to hook in the lazy loading stuff. Hence the Doctrine “requirement” that properties be either private or protected with a getter function.

As this point we can move into the land of opinion and personal preferences. For me at least, lazy loading is one of those things that sound really cool until you actually start using it. At the point, all the extra queries that get kicked off and not knowing exactly what information you have at any given point starts to have a negative impact.

Fortunately, Doctrine also support eager loading in which loading a book will also load the author at the same time. And with eager loading, public properties work just fine for Doctrine entities.

And as @TomB has suggested there are many other implications of either using or not using getters/setters. I’m firmly in the anti-accessor camp but overall I suspect that us anti folks are a minority. There is just something about generating huge numbers of boilerplate methods that seem to appeal to the OOP folks.

And by the way, you should probably delete your identical stackoverflow question. Big picture questions like this are a poor fit for stackoverflow. You might try the Software Engineering community but not many php folks hang out there.

When I was working with php I enjoyed using Doctrine for large applications. Having said that Doctrine not unlike all robust ORMs have very large, complicated code bases that can be difficult to use. I much prefer using Doctrine over Eloquent / ActiveRecord. It seems much easier to organize things when the repository (business logic) is separate from the entity (domain object). This is especially true as the application grows in size.

You definitely don’t need methods to achieve lazy loading with proxy objects.

Consider this:

class Book {

	public $title;
	public $author;

	public function __construct(array $bookData, $authorMapper) {
		$this->title = $bookData['title'];
		$this->author = new Proxy($authorMapper, $bookData['authorId']);
	}

}



class Proxy {
	private $relatedMapper;
	private $lookupVal;
	private $cachedresult;

	public function __construct($relatedMapper, $lookupVal) {
		$this->relatedMapper = $relatedMapper;
		$this->lookupVal = $lookupVal;
	}

	public function __get($property) {
		if (!$this->cachedResult) $this->fetch();

		return $this->cachedResult->$property;
	}

	private function fetch() {
		$this->cachedResult = $this->relatedMapper->findById($lookupVal);
	}

}

Then you can just chain the calls:

echo $book->author->name;

The author will only be queried from the database when a property on the author proxy object is read.

You can even chain the proxies and do something like this:

echo $book->publisher->address->town;

I could be wrong but I think we were discussing why Doctrine requires private/protected properties with getters.

I will diplomatically avoid expressing my opinion of the quality of your posted code.

But there’s no reason it needs to use private properties to do this. The code is only intended to be a simple example. You’d really want the mapper to create the proxy object and populate the other public properties when it creates the Book instance.

Never noticed that there was a time limit on editing posts before.

My original post about Doctrine needing private/protected properties to support lazy loading was wrong. Not sure when they implemented this but but the proxy actually unsets any public property the needs lazy loading and then uses __get to add it back when accessed. Not sure I like unsetting properties but it works.

So the bottom line is that there does not seem to be any technical requirement for keeping Doctrine properties private/protected. It is more of a question of if you consider Doctrine entities to be data transfer objects or actual business objects with domain logic in them.

1 Like

For those interested in the difference I can recommend this talk: https://www.youtube.com/watch?v=ajhqScWECMo

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.