When I run doctrine orm:validate-schema
, it pops up a bunch of warnings about my mapped columns being public and not using getter/setter methods to wrap them. It says that they "break lazy loading". I can understand how making associated collections public could be problematic (I do make these private and wrap them), but how is this an issue for fields on the object? Fields are loaded in full, to my knowledge.

- 65,519
- 58
- 198
- 260
-
5Honestly, I couldn't believe this either until I realised: Doctrine is a Java library. If they concentrated on making the best possible use of PHP idioms rather than forcing you into "best-practices" designed with another language in mind, perhaps the performance wouldn't be so abysmal. I agree in principle with the argument for getters and setters, but in an interpreted language where all they do is proxy a public field, they're a needless waste of resources. – Shabbyrobe Jan 20 '11 at 00:54
-
2@Shabbyrobe: Thank you. You've basically said what I've been thinking this whole time. Doctrine is basically a clone of Hibernate. What PHP needs is something that is more of a clone of Active Record. – ryeguy Jan 20 '11 at 15:23
-
8Doctrine 2 and Hibernate are both implementations of the platform agnostic data mapper pattern, but I reckon the way Doctrine 2 have implemented it uses too many Java idioms, like "getters and setters for absolutely everything, no questions asked". PHP is an interpreted language - why add methods that essentially do nothing when they have a measurable negative impact on performance? I've outlined some of my arguments against the "getters and setters for everything" position [here](http://stackoverflow.com/questions/808348/is-it-really-that-wrong-not-using-setters-and-getters/813099#813099). – Shabbyrobe Jan 21 '11 at 00:48
-
1If you're after a PHP implementation of active record, you could try [this](http://www.phpactiverecord.org/). I personally prefer the data mapper pattern to active record, but I would rather use an active record library written in idiomatic PHP than a data mapper library written in idiomatic Java masquerading as PHP, so I'm going to take a look at that library this afternoon. – Shabbyrobe Jan 21 '11 at 00:49
-
If you want an ORM with active record pattern just use Doctrine1 or Propel. – Hubert Perron Apr 06 '13 at 19:35
2 Answers
I'll give a shot at this although I'm certainly not a Doctrine2 expert.
From my (limited) usage and testing it seems Doctrine may give you a related object without loading the data for that object. At that point public properties will break lazy loading.
Doctrine is lazy loading at the point where the persisted data is requested, not when the object that contains persisted data is requested.
Update: I took a look at the actual proxy code and it seems my original understanding was mostly correct. The proxy object doesn't load itself until a method of the object is called. So any request to a public property would not load the data.

- 17,549
- 10
- 60
- 91
-
-
2
-
1@ryeguy Maybe, but seems a better method then some alternatives. If you implement lazy loading when the persisted object is requested (instead of when it's *used*), somehow the ORM has to put code between the property that contains the related object and any code that might try to use that property (including the entity object itself). That would make lazy loading far less transparent. – Tim Lytle Nov 04 '10 at 01:06
-
1You can verify that it doesnt work by simply calling: $entity = $em->getReference('EntityName'); echo $entity->publicField; It will always return NULL. – beberlei Nov 16 '10 at 12:47
-
Thanks for the great answer - helped me come to grips with this. There's a [section in their docs](http://www.doctrine-project.org/docs/orm/2.0/en/tutorials/getting-started-xml-edition.html#find-by-primary-key) that outlines their "rationale" for this "feature" and shows some of the proxy code mentioned in the answer up close. Summary: answer was bang on the money. – Shabbyrobe Jan 20 '11 at 00:57
Note that Doctrine 2.4 now supports proxy objects for entites with public properties.
Marco Pivetta's website explains how it works:
class Customer {
public $name;
public $surname;
}
class CustomerProxy extends Customer {
public function __construct(Customer $customer) {
unset($this->name, $this->surname);
$this->customer = $customer;
}
public function __set($name, $value) {
$this->customer->$name = $value;
}
public function __get($name) {
return $this->customer->$name;
}
// __isset, __unset, __clone, __sleep, __wakeup (or serialize/unserialize)
}

- 34,448
- 50
- 182
- 322
-
1So does this mean we can ignore `vendor/bin/doctrine orm:validate-schema` complaining about public properties? – Erik van Velzen Jan 28 '15 at 15:49
-
@ErikvanVelzen I guess so, I didn't know that this tool complained about public properties, maybe you should file an issue asking for this outdated feature to be removed! – BenMorel Jan 28 '15 at 15:55
-
@ErikvanVelzen You can simply set your properties to `protected` and they will still be accessible as if they were public because of the magic `__get` and `__set` methods. – Wilt Mar 07 '15 at 15:29