Re: [PHP-DEV] [RFC] Object Initializer

  107084
September 14, 2019 08:47 mike@newclarity.net (Mike Schinkel)
> On Sep 13, 2019, at 3:18 AM, Rasmus Schultz <rasmus@mindplay.dk <mailto:rasmus@mindplay.dk>> wrote: > > Assuming the fields of this entity are required, you would probably prefer > to add a constructor - but then property initializers aren't really useful > anymore.
I think this is a false dichotomy; I can see benefit to having initializers in addition to constructors, even for the same classes. However, Object Initializers might be best when paired with a new magic method which let us call __init(), and a required modifier for properties. Using your Customer example, the __init() would be automatically called after __construct(): class Customer { private string $name = ''; required protected ?string $email = null; public function __construct(string $name, ?string $email = null) { $this->name = $name; $this->email = $email; } public function __init() { $this->name = ucwords($this->name); $this->email = sanitize_email($this->email); } } With __init() a developer could separate capturing construct parameters from initializing required fields, but the required modifier would allow developers to indicate which properties should be required. And it might even make sense to throw an error if an object initializer does not have an __init() method. Requiring __init() would ensure that classes not designed to work with initializers would never be initialized without required fields set. When creating an object using object initialization I think it should just bypass and only call __init(). PHP could generate an error if any required fields are not set. $customer = new Customer{ name => 'mike schinkel', email => 'mike@newclarity.net <mailto:mike@newclarity.net>' } echo $customer->name; // Prints "Mike Schinkel" Actually, a required modifier would not be required to implement object initializers (no pun intended) but it would enable IDEs, PHP and other tools validate whether or not a required fields has been set. As an aside, it would be interesting if there were a __validate() magic method although it might harm performance too much. OTOH, it should not harm performance unless you actually use it: public function __validate(string $field):bool { switch ($field) { case 'name': return !empty( $this->name ) && strlen($this->name) >= 3; case 'email': return validate_email($this->email); } return true; }
> a desire to use this language feature will drive architecture. ... this will > provide the wrong kind of motivation to make what are, effectively, > architectural decisions.
The reason I badly want object initializers is to empower architectures that currently are not possible in PHP. So I see this as a positive. I see architectures used in other languages that reduce tedium and enhance reusability that we cannot implement in PHP because of lack of an object initializer. But maybe I do not realize what you are seeing? Can you please elaborate on the architectures you fear will emerge, ideally with examples and reasons why they should be avoided? -Mike
  107086
September 14, 2019 08:50 ocramius@gmail.com (Marco Pivetta)
On Sat, Sep 14, 2019 at 10:47 AM Mike Schinkel <mike@newclarity.net> wrote:

> > On Sep 13, 2019, at 3:18 AM, Rasmus Schultz <rasmus@mindplay.dk rasmus@mindplay.dk>> wrote: > > > > Assuming the fields of this entity are required, you would probably > prefer > > to add a constructor - but then property initializers aren't really > useful > > anymore. > > I think this is a false dichotomy; I can see benefit to having > initializers in addition to constructors, even for the same classes. > > However, Object Initializers might be best when paired with a new magic > method which let us call __init(), and a required modifier for properties. > > Using your Customer example, the __init() would be automatically called > after __construct(): > > class Customer > { > private string $name = ''; > required protected ?string $email = null; > > public function __construct(string $name, ?string $email = null) > { > $this->name = $name; > $this->email = $email; > } > > public function __init() > { > $this->name = ucwords($this->name); > $this->email = sanitize_email($this->email); > } > } > > With __init() a developer could separate capturing construct parameters > from initializing required fields, but the required modifier would allow > developers to indicate which properties should be required. > > And it might even make sense to throw an error if an object initializer > does not have an __init() method. Requiring __init() would ensure that > classes not designed to work with initializers would never be initialized > without required fields set. > > When creating an object using object initialization I think it should just > bypass and only call __init(). PHP could generate an error if any required > fields are not set. > > $customer = new Customer{ > name => 'mike schinkel', > email => 'mike@newclarity.net <mailto:mike@newclarity.net>' > } > echo $customer->name; // Prints "Mike Schinkel" > > Actually, a required modifier would not be required to implement object > initializers (no pun intended) but it would enable IDEs, PHP and other > tools validate whether or not a required fields has been set. > > As an aside, it would be interesting if there were a __validate() magic > method although it might harm performance too much. OTOH, it should not > harm performance unless you actually use it: > > public function __validate(string $field):bool > { > switch ($field) { > case 'name': > return !empty( $this->name ) && strlen($this->name) >= 3; > case 'email': > return validate_email($this->email); > } > return true; > } > > > a desire to use this language feature will drive architecture. ... this > will > > provide the wrong kind of motivation to make what are, effectively, > > architectural decisions. > > The reason I badly want object initializers is to empower architectures > that currently are not possible in PHP. So I see this as a positive. > > I see architectures used in other languages that reduce tedium and enhance > reusability that we cannot implement in PHP because of lack of an object > initializer. > > But maybe I do not realize what you are seeing? Can you please elaborate > on the architectures you fear will emerge, ideally with examples and > reasons why they should be avoided? > > > -Mike > > Hey Mike,
lazy initialisation is already possible in userland: adding more magic to the language for a use-case that is already implemented seems problematic to me. Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/