问题
I remember reading that in Doctrine 2 models, I should not set properties/fields public. How then would you expose these fields? The sandbox used get*()
& set*()
methods. Is that the best idea? Its very cumbersome. Using magic methods __get()
__set()
will make things similar to setting fields public?
Whats your recommendation?
回答1:
Here's why you can't use public properties: How can public fields “break lazy loading” in Doctrine 2?
You are correct that __get()
and __set()
can make accessing the protected
/private
fields easier.
Here's a simple example:
public function __get($name)
{
if(property_exists($this, $name)){
return $this->$name;
}
}
Of course that gives access to all the properties. You could put that in a class that all your entities extended, then define non-assessable fields as private
. Or you could use an array to determine which properties should be accessible:$this->accessable = array('name', 'age')
There are plenty of ways to keep all properties protected and still have a reasonably easy way to get/set them.
回答2:
Personally, I don't like boilerplate code with trivial purpose - it makes the code ugly and tiresome to read. Therefore, I strongly prefer __get
/__set
. That said, they do have a few drawbacks:
- they are significantly slower than normal function calls, though not so much that it should make a difference in practice, as database access is several orders of magnitude slower
__get
/__set
only gets called when the field is not visible; if you access properties in the code of the entity class, they do not get called, and the proxy has no chance to load itself. (Doctrine tries to avoid this by instantly loading the proxy as soon as one of its public methods are called, but there are some exceptions such as__construct
or__wake
where that would not make sense, so you can get into trouble by e.g. reading a field in the constructor.)- PHP has some confusing behaviors related to magic methods - e. g.
empty($entity->field)
will not invoke__get
(and thus it will break proxy behavior if used)
回答3:
If some info should be made public, define a getter for it. If it's modifiable, add a setter (even better, add a fluent setter!).
API's are cleaner this way, with no magic involved. I don't like magic in my code.
Just my two cents :)
By "fluent setter" I meant one implementing the fluent interface pattern.
回答4:
Yes getter and setter methods are the way to access your data. They are a little cumbersome which is why some people do not like doctrine2 or hibernate. But you only need to do it once for each entity and then they are very flexible to produce the output formatting you are hoping for. You can use the cli to do some of this for you. But when you get them rolling I don't find it to big a deal. Especially since you only do this to the properties you need.
Cheers
回答5:
Rather than having seperate getter and setters, or even using the magic functions.. Is there problem with having something like this in the class
public function Set($attrib, $value)
{
$this->$attrib = $value;
}
public function Get($attrib)
{
return $this->$attrib;
}
It makes it much easy to access the attributes and means they be dynamically set from key-pair arrays.. any comments? or alternative suggestions?
回答6:
Doctine 2 provides a [command line tool][1] to generate basic entity classes
use the following to get a basic Entity class definition from your mapping, complete with getter/setter functions for each property:
path/to/doctrine_cli orm:generate-entities --generate-methods=true path/to/entities/
You're still responsible for modifying each getter/setter to ensure that they are the proper datatype, as the getter/setter methods generated for the Entity don't do any type casting/converting.
来源:https://stackoverflow.com/questions/4461296/doctrine-2-whats-the-recommended-way-to-access-properties