# [RFC] Propety Accessors v1.1

- Thread: https://externals.io/message/63278
- Original archive: https://news-web.php.net/php.internals/63278
- Started by Clint Priest on 2012-10-08T11:52:44+00:00
- Messages: 65
- Page 1 of 3: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/63278.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #63278 — Clint Priest — 2012-10-08T11:52:44+00:00

URL: https://externals.io/message/63278#63278

It's been a while since I posted any updates about this, a few individuals have been asking about it privately and wanting me to get it out the door for PHP 5.5 release.  It's come a long way since the last time I posted about it.

RFC Document: https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented

Example Usage:

class TimePeriod {
    private $Seconds = 3600;

    public $Hours {
        get { return $this->Seconds / 3600; }
        set { $this->Seconds = $value; }
        isset<http://www.php.net/isset> { return isset<http://www.php.net/isset>($this->Seconds); }
        unset<http://www.php.net/unset> { unset<http://www.php.net/unset>($this->Seconds); }
    }
}

Changes / Updates

*         isset/unset accessor functions now implemented (object & static context, auto implementations, etc)

*         static accessor now fully functional

*         Reference functionality validated, tests written

*         All operators have been tested, tests written

*         read-only and write-only keywords: Added explanation of reasons for inclusion at the top of the appropriate RFC section

*         Tested for speed, approaches or meets __get() speed.

Internally things have changed quite a bit

*         cleaned up and simplified

*         had been using 4 to 5 additional fn_flag slots, now down to two (READ_ONLY and WRITE_ONLY)

*         the automatic implementations now compiled internal php code, this greatly simplified that part of the code and future proofed it.

The code is available at the url below and is up to date with master, all tests pass.
https://github.com/cpriest/php-src

I'd like to get this project wrapped up in time to make it to the 5.5 release, only a few things remain to be completed/updated:

*         Check on reflection code written prior to major changes (tests still pass)

*         Add a few more reflection functions that were requested

In total there are 79 tests for this new functionality, if there are any others that I have missed, please let me know.

-Clint

---

## #63279 — Clint Priest — 2012-10-08T12:42:24+00:00

URL: https://externals.io/message/63278#63279 · In reply to: #63278

As an update, just ran some performance testing:

master
		 			Cycles		Direct		Getter		__get
	v1.4 @ 10/8/2012		1m		.05s		.21s		.20s

php 5.5.0-dev
		 			Cycles		Direct		Getter		__get
	v1.4 @ 10/8/2012		1m		.04s		n/a		.21s

Performance of property accessors was important to me as I'm sure it will be to many, on one million cycles of a simple getter, it's <.01s difference.  Depending on the run it is sometimes exactly the same performance.

> -----Original Message-----
> From: Clint Priest [mailto:cpriest@zerocue.com]
> Sent: Monday, October 08, 2012 6:53 AM
> To: internals@lists.php.net
> Subject: [PHP-DEV] [RFC] Propety Accessors v1.1
> 
> It's been a while since I posted any updates about this, a few individuals have been asking about it privately and wanting me to get it
> out the door for PHP 5.5 release.  It's come a long way since the last time I posted about it.
> 
> RFC Document: https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented
> 
> Example Usage:
> 
> class TimePeriod {
>     private $Seconds = 3600;
> 
>     public $Hours {
>         get { return $this->Seconds / 3600; }
>         set { $this->Seconds = $value; }
>         isset<http://www.php.net/isset> { return isset<http://www.php.net/isset>($this->Seconds); }
>         unset<http://www.php.net/unset> { unset<http://www.php.net/unset>($this->Seconds); }
>     }
> }
> 
> Changes / Updates
> 
> *         isset/unset accessor functions now implemented (object & static context, auto implementations, etc)
> 
> *         static accessor now fully functional
> 
> *         Reference functionality validated, tests written
> 
> *         All operators have been tested, tests written
> 
> *         read-only and write-only keywords: Added explanation of reasons for inclusion at the top of the appropriate RFC section
> 
> *         Tested for speed, approaches or meets __get() speed.
> 
> Internally things have changed quite a bit
> 
> *         cleaned up and simplified
> 
> *         had been using 4 to 5 additional fn_flag slots, now down to two (READ_ONLY and WRITE_ONLY)
> 
> *         the automatic implementations now compiled internal php code, this greatly simplified that part of the code and future proofed
> it.
> 
> The code is available at the url below and is up to date with master, all tests pass.
> https://github.com/cpriest/php-src
> 
> I'd like to get this project wrapped up in time to make it to the 5.5 release, only a few things remain to be completed/updated:
> 
> *         Check on reflection code written prior to major changes (tests still pass)
> 
> *         Add a few more reflection functions that were requested
> 
> In total there are 79 tests for this new functionality, if there are any others that I have missed, please let me know.
> 
> -Clint

---

## #63280 — Paul Dragoonis — 2012-10-08T12:50:14+00:00

URL: https://externals.io/message/63278#63280 · In reply to: #63279

Good work Clint!

Performance is probably one of the things people will complain about
so it's good that your benchmark is proving that it's merely identical
to the old __get() approach.

What remains on your TODO list for this functionality?
When are you planning to run an RFC vote on this?

I think this would be a valuable addition to PHP 5.5.

Cheers,
Paul.


> As an update, just ran some performance testing:
>
> master
>                                         Cycles          Direct          Getter          __get
>         v1.4 @ 10/8/2012                1m              .05s            .21s            .20s
>
> php 5.5.0-dev
>                                         Cycles          Direct          Getter          __get
>         v1.4 @ 10/8/2012                1m              .04s            n/a             .21s
>
> Performance of property accessors was important to me as I'm sure it will be to many, on one million cycles of a simple getter, it's <.01s difference.  Depending on the run it is sometimes exactly the same performance.
>
> > […]

---

## #63282 — Amaury Bouchard — 2012-10-08T13:27:26+00:00

URL: https://externals.io/message/63278#63282 · In reply to: #63278

Hi,

This summer (july 15) I did another proposal, which has some connections
with yours.

For the main usage of getters/setters, my guess is that we need separate
read/write visibilities. Your RFC goes beyond that, but I think both are
complementary.
Most of the time, we write getters/setters to ensure that a private
attribute can be read but not modified (or modified only as we want to).
Your RFC is pretty powerful in some use cases. Like your example, which is
a "virtual" attribute, created from some processing. But create a new
"read-only" keyword is not a good idea for me: introduce a new keyword
should be avoided when it's not absolutely necessary, and it lacks meaning
(exact visibility information).

Correct me if I'm wrong, but your syntax is similar to the one used in C#.
Not a bad idea, but I think we can imagine for PHP somethink a little more
concise for the general usage.

My idea was to write attribute's visibility like
"read_visiblity:write_visibility $attr;"
  public:protected $foo; // public reading, protected writing
  public:private $bar; // public reading, private writing
  protected:private $aaa; // protected reading, private writing
  protected:const $bbb; // protected reading, no writing

With your RFC it will be:
  public $foo { get; protected set; }
  public $bar { get; private set; }
  protected $aaa { get; private set; }
  protected read-only $bbb;

When I did my proposal on the internals mailing-list, I got some pretty bad
feedbacks, and some very good ones.
So, maybe we can try to merge some ideas?

My patch: http://github.com/Amaury/php-src

Regards,

Amaury


2012/10/8 Clint Priest <cpriest@zerocue.com>

> It's been a while since I posted any updates about this, a few individuals
> have been asking about it privately and wanting me to get it out the door
> for PHP 5.5 release.  It's come a long way since the last time I posted
> about it.
>
> RFC Document: https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented
>
> Example Usage:
>
> class TimePeriod {
>     private $Seconds = 3600;
>
>     public $Hours {
>         get { return $this->Seconds / 3600; }
>         set { $this->Seconds = $value; }
>         isset<http://www.php.net/isset> { return isset<
> http://www.php.net/isset>($this->Seconds); }
>         unset<http://www.php.net/unset> { unset<http://www.php.net/unset>($this->Seconds);
> }
>     }
> }
>
> Changes / Updates
>
> *         isset/unset accessor functions now implemented (object & static
> context, auto implementations, etc)
>
> *         static accessor now fully functional
>
> *         Reference functionality validated, tests written
>
> *         All operators have been tested, tests written
>
> *         read-only and write-only keywords: Added explanation of reasons
> for inclusion at the top of the appropriate RFC section
>
> *         Tested for speed, approaches or meets __get() speed.
>
> Internally things have changed quite a bit
>
> *         cleaned up and simplified
>
> *         had been using 4 to 5 additional fn_flag slots, now down to two
> (READ_ONLY and WRITE_ONLY)
>
> *         the automatic implementations now compiled internal php code,
> this greatly simplified that part of the code and future proofed it.
>
> The code is available at the url below and is up to date with master, all
> tests pass.
> https://github.com/cpriest/php-src
>
> I'd like to get this project wrapped up in time to make it to the 5.5
> release, only a few things remain to be completed/updated:
>
> *         Check on reflection code written prior to major changes (tests
> still pass)
>
> *         Add a few more reflection functions that were requested
>
> In total there are 79 tests for this new functionality, if there are any
> others that I have missed, please let me know.
>
> -Clint

---

## #63286 — Benjamin Eberlei — 2012-10-08T22:26:59+00:00

URL: https://externals.io/message/63278#63286

The set() one is really nice with the typehints.



> 
>
> > […]
> for object prototypes:
> http://ejohn.org/blog/**javascript-getters-and-**setters/<http://ejohn.org/blog/javascript-getters-and-setters/>
>
>
> > […]

---

## #63287 — Jazzer Dane — 2012-10-08T22:31:48+00:00

URL: https://externals.io/message/63278#63287 · In reply to: #63286

I agree.
It's more consistent than the $Hours solution and we don't have to add
another superglobal or magic constant, which is quite nice. The typehinting
is a big plus as well.

On Mon, Oct 8, 2012 at 3:26 PM, Benjamin Eberlei <kontakt@beberlei.de>wrote:

> The set() one is really nice with the typehints.
>
> On Tue, Oct 9, 2012 at 12:19 AM, Aaron Holmes <aaron@aaronholmes.net>
> wrote:
>
> > […]
> this
> > […]
> http://ejohn.org/blog/javascript-getters-and-setters/>
> > […]

---

## #63288 — Clint Priest — 2012-10-09T01:10:43+00:00

URL: https://externals.io/message/63278#63288 · In reply to: #63287

Seems a fair amount of people would like it with a definable parameter name, though the original RFC I based mine off of is more than 4 years old (mine is over a year old already).

The $value is precisely chosen because it is exactly the way C# operates and the original author thought to keep it the same as another well-known language (why re-invent new syntax for no reason).

That being said, javascript does indeed allow it, my concern then would be would we have the parameterized syntax only for set() and not get, isset or unset?

If we do have them for all of them, it's a lot of extra characters with no real need.

I definitely favor set($value) over a magic $Hours for the $Hours property, but I personally see no problem with the $value, it's not magic it's a locally defined variable.

Internally, this: 
   public $Hours {
      get { ... }
      set { ... }
   }

Is implemented as standard functions, while they are hidden through reflection, these functions exist (as a result of the above example):

public __getHours() { ... }
public __setHours($value) { ... }

Lastly, with regards to JavaScript style getters/setters, I don't think I've ever cared what the variable name was, I typically just do something like:

set blah(x) { ... } <-- x is fairly irrelevant and similarly the use of $value is fairly irrelevant.   Thoughts?

> -----Original Message-----
> From: Jazzer Dane [mailto:tbprogrammer@gmail.com]
> Sent: Monday, October 08, 2012 5:32 PM
> To: Benjamin Eberlei
> Cc: Aaron Holmes; internals@lists.php.net
> Subject: Re: [PHP-DEV] [RFC] Propety Accessors v1.1
> 
> I agree.
> It's more consistent than the $Hours solution and we don't have to add another superglobal or magic constant, which is quite nice. The
> typehinting is a big plus as well.
> 
> On Mon, Oct 8, 2012 at 3:26 PM, Benjamin Eberlei <kontakt@beberlei.de>wrote:
> 
> > […]

---

## #63290 — Jazzer Dane — 2012-10-09T03:08:24+00:00

URL: https://externals.io/message/63278#63290 · In reply to: #63288

While I understand your concern with set being the only keyword using (),
and even agree it's a bit problematic, I see a big problem with using
$value.

Even if $value internally makes sense due to something along the lines of *
__setHours($value)* {} being equal to *set {}*, I think using $value
without it ever being defined in the developer's code is not at all a good
idea.
If I see $value in the code, I'll logically look for where it was defined,
and when I don't see it anywhere else in the code, things are going to very
quickly get confusing.
Our best option to combat this confusion is, in my eyes, putting a note in
the documentation. That's not enough.

A similar alternative to using $value that I'd argue would be much more
sensible would be to, as Denis mentioned, use either a magic constant or a
superglobal.

As I mentioned previously, I would rather go with the set($value) {} syntax.

Now, back to the part where I agree with you - the inconsistency wherein
set has () that denote it is a method but get, isset, and unset do not. I
see this inconsistency as something problematic enough to warrant a
solution.

We could go with the following:
public $Hours {
  get() { ... }
  set($value) { ... }
  isset() { ... }
  unset() { ... }
}

Yes, we now have a little bit more meat on the syntax, but in this case, I
don't think that it's all that bad. Here's two reasons why:
1) Adding parenthesis denotes that they are all functions - which they are!
If anything, adding parenthesis to all of them makes the implementation *
more* sensible.
2) It's *only* two more characters per function. On top of that, in my
opinion, this syntax is not "ugly". In fact, as I just mentioned - this
implementation is arguably *more* consistent with the rest of PHP.



> Seems a fair amount of people would like it with a definable parameter
> name, though the original RFC I based mine off of is more than 4 years old
> (mine is over a year old already).
>
> The $value is precisely chosen because it is exactly the way C# operates
> and the original author thought to keep it the same as another well-known
> language (why re-invent new syntax for no reason).
>
> That being said, javascript does indeed allow it, my concern then would be
> would we have the parameterized syntax only for set() and not get, isset or
> unset?
>
> If we do have them for all of them, it's a lot of extra characters with no
> real need.
>
> I definitely favor set($value) over a magic $Hours for the $Hours
> property, but I personally see no problem with the $value, it's not magic
> it's a locally defined variable.
>
> Internally, this:
>    public $Hours {
>       get { ... }
>       set { ... }
>    }
>
> Is implemented as standard functions, while they are hidden through
> reflection, these functions exist (as a result of the above example):
>
> public __getHours() { ... }
> public __setHours($value) { ... }
>
> Lastly, with regards to JavaScript style getters/setters, I don't think
> I've ever cared what the variable name was, I typically just do something
> like:
>
> set blah(x) { ... } <-- x is fairly irrelevant and similarly the use of
> $value is fairly irrelevant.   Thoughts?
>
> > […]
> another superglobal or magic constant, which is quite nice. The
> > […]

---

## #63291 — Clint Priest — 2012-10-09T04:24:12+00:00

URL: https://externals.io/message/63278#63291 · In reply to: #63290

Great arguments for, anyone against this being the new way?  If not then I’ll begin work on this change as well.   I would like to keep this discussion going so that at the end of this two week discussion period I can submit it for voting.

Jazzer, your points make a lot of sense in terms of making it clear that they are all functions, I’m all game.  If it’s not difficult I may just make it compatible in both ways (auto-define $value) if parenthesized option is not specified.  Flexibility is at the heart of php.

-Clint

From: Jazzer Dane [mailto:tbprogrammer@gmail.com]
Sent: Monday, October 08, 2012 10:08 PM
To: Clint Priest
Cc: internals@lists.php.net; Aaron Holmes; Benjamin Eberlei
Subject: Re: [PHP-DEV] [RFC] Propety Accessors v1.1

While I understand your concern with set being the only keyword using (), and even agree it's a bit problematic, I see a big problem with using $value.

Even if $value internally makes sense due to something along the lines of __setHours($value) {} being equal to set {}, I think using $value without it ever being defined in the developer's code is not at all a good idea.
If I see $value in the code, I'll logically look for where it was defined, and when I don't see it anywhere else in the code, things are going to very quickly get confusing.
Our best option to combat this confusion is, in my eyes, putting a note in the documentation. That's not enough.

A similar alternative to using $value that I'd argue would be much more sensible would be to, as Denis mentioned, use either a magic constant or a superglobal.

As I mentioned previously, I would rather go with the set($value) {} syntax.

Now, back to the part where I agree with you - the inconsistency wherein set has () that denote it is a method but get, isset, and unset do not. I see this inconsistency as something problematic enough to warrant a solution.

We could go with the following:
public $Hours {
  get() { ... }
  set($value) { ... }
  isset() { ... }
  unset() { ... }
}

Yes, we now have a little bit more meat on the syntax, but in this case, I don't think that it's all that bad. Here's two reasons why:
1) Adding parenthesis denotes that they are all functions - which they are! If anything, adding parenthesis to all of them makes the implementation more sensible.
2) It's only two more characters per function. On top of that, in my opinion, this syntax is not "ugly". In fact, as I just mentioned - this implementation is arguably more consistent with the rest of PHP.

Seems a fair amount of people would like it with a definable parameter name, though the original RFC I based mine off of is more than 4 years old (mine is over a year old already).

The $value is precisely chosen because it is exactly the way C# operates and the original author thought to keep it the same as another well-known language (why re-invent new syntax for no reason).

That being said, javascript does indeed allow it, my concern then would be would we have the parameterized syntax only for set() and not get, isset or unset?

If we do have them for all of them, it's a lot of extra characters with no real need.

I definitely favor set($value) over a magic $Hours for the $Hours property, but I personally see no problem with the $value, it's not magic it's a locally defined variable.

Internally, this:
   public $Hours {
      get { ... }
      set { ... }
   }

Is implemented as standard functions, while they are hidden through reflection, these functions exist (as a result of the above example):

public __getHours() { ... }
public __setHours($value) { ... }

Lastly, with regards to JavaScript style getters/setters, I don't think I've ever cared what the variable name was, I typically just do something like:

set blah(x) { ... } <-- x is fairly irrelevant and similarly the use of $value is fairly irrelevant.   Thoughts?

> -----Original Message-----
> From: Jazzer Dane [mailto:tbprogrammer@gmail.com<mailto:tbprogrammer@gmail.com>]
> Sent: Monday, October 08, 2012 5:32 PM
> To: Benjamin Eberlei
> Cc: Aaron Holmes; internals@lists.php.net<mailto:internals@lists.php.net>
> Subject: Re: [PHP-DEV] [RFC] Propety Accessors v1.1
>
> I agree.
> It's more consistent than the $Hours solution and we don't have to add another superglobal or magic constant, which is quite nice. The
> typehinting is a big plus as well.
>
> On Mon, Oct 8, 2012 at 3:26 PM, Benjamin Eberlei <kontakt@beberlei.de<mailto:kontakt@beberlei.de>>wrote:
>
> > […]

---

## #63293 — Christian Stoller — 2012-10-09T06:38:14+00:00

URL: https://externals.io/message/63278#63293 · In reply to: #63290

I personally like the idea by Denis Portnov with the magic constant __VALUE__ which goes along with other magic constants documented here http://www.php.net/manual/en/language.constants.predefined.php

But the advantage of the "type hinting" in the setter when we use "set($value)" should be weighted stronger. This is a great plus!
I would vote for Jazzer's 
> public $Hours {
>     get() { ... }
>     set($value) { ... }
>     isset() { ... }
>     unset() { ... }
> }

Best regards
Christian Stoller


-----Original Message-----
From: Jazzer Dane [mailto:tbprogrammer@gmail.com] 
Sent: Tuesday, October 09, 2012 5:08 AM
To: Clint Priest
Cc: internals@lists.php.net; Aaron Holmes; Benjamin Eberlei
Subject: Re: [PHP-DEV] [RFC] Propety Accessors v1.1

While I understand your concern with set being the only keyword using (),
and even agree it's a bit problematic, I see a big problem with using
$value.

Even if $value internally makes sense due to something along the lines of *
__setHours($value)* {} being equal to *set {}*, I think using $value
without it ever being defined in the developer's code is not at all a good
idea.
If I see $value in the code, I'll logically look for where it was defined,
and when I don't see it anywhere else in the code, things are going to very
quickly get confusing.
Our best option to combat this confusion is, in my eyes, putting a note in
the documentation. That's not enough.

A similar alternative to using $value that I'd argue would be much more
sensible would be to, as Denis mentioned, use either a magic constant or a
superglobal.

As I mentioned previously, I would rather go with the set($value) {} syntax.

Now, back to the part where I agree with you - the inconsistency wherein
set has () that denote it is a method but get, isset, and unset do not. I
see this inconsistency as something problematic enough to warrant a
solution.

We could go with the following:
public $Hours {
  get() { ... }
  set($value) { ... }
  isset() { ... }
  unset() { ... }
}

Yes, we now have a little bit more meat on the syntax, but in this case, I
don't think that it's all that bad. Here's two reasons why:
1) Adding parenthesis denotes that they are all functions - which they are!
If anything, adding parenthesis to all of them makes the implementation *
more* sensible.
2) It's *only* two more characters per function. On top of that, in my
opinion, this syntax is not "ugly". In fact, as I just mentioned - this
implementation is arguably *more* consistent with the rest of PHP.



> Seems a fair amount of people would like it with a definable parameter
> name, though the original RFC I based mine off of is more than 4 years old
> (mine is over a year old already).
>
> The $value is precisely chosen because it is exactly the way C# operates
> and the original author thought to keep it the same as another well-known
> language (why re-invent new syntax for no reason).
>
> That being said, javascript does indeed allow it, my concern then would be
> would we have the parameterized syntax only for set() and not get, isset or
> unset?
>
> If we do have them for all of them, it's a lot of extra characters with no
> real need.
>
> I definitely favor set($value) over a magic $Hours for the $Hours
> property, but I personally see no problem with the $value, it's not magic
> it's a locally defined variable.
>
> Internally, this:
>    public $Hours {
>       get { ... }
>       set { ... }
>    }
>
> Is implemented as standard functions, while they are hidden through
> reflection, these functions exist (as a result of the above example):
>
> public __getHours() { ... }
> public __setHours($value) { ... }
>
> Lastly, with regards to JavaScript style getters/setters, I don't think
> I've ever cared what the variable name was, I typically just do something
> like:
>
> set blah(x) { ... } <-- x is fairly irrelevant and similarly the use of
> $value is fairly irrelevant.   Thoughts?
>
> > […]
> another superglobal or magic constant, which is quite nice. The
> > […]

---

## #63294 — Christian Kaps — 2012-10-09T07:46:32+00:00

URL: https://externals.io/message/63278#63294 · In reply to: #63290

Hi,

typehinting should definitely be available for this feature. But I have 
another question. Why not go more consistent with the rest of the 
language? I have mentioned this previously as the first proposal comes 
up on the list. In my opinion the AS3 getter and setter 
syntax(http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f30.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7fcb) 
fits more into the language as the proposed one.

Here are my concerns:
- I do not like the extra indentation level and it's ugly to document 
(OK, this is a personal preference)
- It isn't possible to declare a private setter and a public getter, as 
it is possible with methods
- If we ever get return type hinting/checks then we needn't consider 
how the syntax has to look
- We must deal with two different syntaxes for the same thing, because 
both are methods
- IDE's, documentation tools, static analyses tools or similar tools 
have a huge effort to implement this syntax. With the method syntax it's 
only a small effort
- We have to create new rules about how the documentation for this 
syntax should look like

For me the following syntax seems more consistent with the rest of PHP:

public get hours() {}
public set hours(DateTime $dateTime) {}
public isset hours() {}
public unset hours() {}

Or:

public function get hours() {}
public function set hours(DateTime $dateTime) {}
public function isset hours() {}
public function unset hours() {}

Or:

public function get $hours() {}
public function set $hours(DateTime $dateTime) {}
public function isset $hours() {}
public function unset $hours() {}

Cheers,
Christian

Am 09.10.2012 05:08, schrieb Jazzer Dane:
> While I understand your concern with set being the only keyword using 
> (),
> and even agree it's a bit problematic, I see a big problem with using
> $value.
>
> Even if $value internally makes sense due to something along the 
> lines of *
> __setHours($value)* {} being equal to *set {}*, I think using $value
> without it ever being defined in the developer's code is not at all a 
> good
> idea.
> If I see $value in the code, I'll logically look for where it was 
> defined,
> and when I don't see it anywhere else in the code, things are going 
> to very
> quickly get confusing.
> Our best option to combat this confusion is, in my eyes, putting a 
> note in
> the documentation. That's not enough.
>
> A similar alternative to using $value that I'd argue would be much 
> more
> sensible would be to, as Denis mentioned, use either a magic constant 
> or a
> superglobal.
>
> As I mentioned previously, I would rather go with the set($value) {} 
> syntax.
>
> Now, back to the part where I agree with you - the inconsistency 
> wherein
> set has () that denote it is a method but get, isset, and unset do 
> not. I
> see this inconsistency as something problematic enough to warrant a
> solution.
>
> We could go with the following:
> public $Hours {
>   get() { ... }
>   set($value) { ... }
>   isset() { ... }
>   unset() { ... }
> }
>
> Yes, we now have a little bit more meat on the syntax, but in this 
> case, I
> don't think that it's all that bad. Here's two reasons why:
> 1) Adding parenthesis denotes that they are all functions - which 
> they are!
> If anything, adding parenthesis to all of them makes the 
> implementation *
> more* sensible.
> 2) It's *only* two more characters per function. On top of that, in 
> my
> opinion, this syntax is not "ugly". In fact, as I just mentioned - 
> this
> implementation is arguably *more* consistent with the rest of PHP.
>
> On Mon, Oct 8, 2012 at 6:10 PM, Clint Priest <cpriest@zerocue.com> 
> wrote:
>
> > […]

---

## #63295 — Sebastian Krebs — 2012-10-09T08:17:27+00:00

URL: https://externals.io/message/63278#63295 · In reply to: #63294

2012/10/9 Christian Kaps <christian.kaps@mohiva.com>

> Hi,
>
> typehinting should definitely be available for this feature. But I have
> another question. Why not go more consistent with the rest of the language?
> I have mentioned this previously as the first proposal comes up on the
> list. In my opinion the AS3 getter and setter syntax(
> http://help.adobe.com/**en_US/ActionScript/3.0_**ProgrammingAS3/**
> WS5b3ccc516d4fbf351e63e3d118a9**b90204-7f30.html#**
> WS5b3ccc516d4fbf351e63e3d118a9**b90204-7fcb<http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f30.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7fcb>)
> fits more into the language as the proposed one.
>
> Here are my concerns:
> - I do not like the extra indentation level and it's ugly to document (OK,
> this is a personal preference)
>

I guess it's more useful to document the property as a whole and not every
single accessor on it's own.


> - It isn't possible to declare a private setter and a public getter, as it
> is possible with methods
>

As far as I understand it it is possible.


> - If we ever get return type hinting/checks then we needn't consider how
> the syntax has to look
>
- We must deal with two different syntaxes for the same thing, because both
> are methods
>

For now it seems the only bigger difference is, that the keyword 'function'
is omitted. You can propose to add it :)


> - IDE's, documentation tools, static analyses tools or similar tools have
> a huge effort to implement this syntax. With the method syntax it's only a
> small effort
>

The tools should not decide how the language should look like, just because
it makes their life easier ;)


> - We have to create new rules about how the documentation for this syntax
> should look like
>

Why should the documentation differ from the documentation for regular
properties?


>
> For me the following syntax seems more consistent with the rest of PHP:
>
> public get hours() {}
> public set hours(DateTime $dateTime) {}
> public isset hours() {}
> public unset hours() {}
>
> Or:
>
> public function get hours() {}
> public function set hours(DateTime $dateTime) {}
> public function isset hours() {}
> public function unset hours() {}
>
> Or:
>
> public function get $hours() {}
> public function set $hours(DateTime $dateTime) {}
> public function isset $hours() {}
> public function unset $hours() {}
>

I don't like how it separate the single accessors from each other. The
benefit from this RFC (imo) -- especially compared to __get()/__set() --
is, that every accessors is directly and obviously bound to the (single)
property: You have a single block with all the corresponding accessors in
it and not several (on the first glance: different) methods, that could be
spread over the whole class.

Maybe it's just me, but I really would like to see this feature in 5.5. As
far as I remember it was first proposed for 5.3 and now (years after)
seeing it delayed, because the syntax "looks ugly (just my opinion)" makes
me feel a little bit ... ehm ... sad. I think the syntax is fine and it
seems it covers the most important points (even not all). There is a
property and "the value" of the property are the accessors. I bet we could
find an infinite number of different syntax, that provides exactly the same
functionality, but why?

Regards,
Sebastian


>
> Cheers,
> Christian
>
> Am 09.10.2012 05:08, schrieb Jazzer Dane:
>
>  While I understand your concern with set being the only keyword using (),
> > […]
>
> --
> 
> 
>
>


-- 
github.com/KingCrunch

---

## #63296 — Jazzer Dane — 2012-10-09T08:20:17+00:00

URL: https://externals.io/message/63278#63296 · In reply to: #63294

Christian, I think a majority of your concerns are all for none.
From top to bottom:

- Extra indention: This is definitely a bias and is only moderately
relevant while documenting this feature.

- You *can* declare a public getter and private setter, or vice versa, or
whatever you want. This is in the RFC. See "Asymmetric Accessor
Accessibility."

- "If we ever get return type hinting/checks then we needn't consider how
the syntax has to look" From what I know, this isn't planned for PHP 5.5
and any proposals for it have been largely ignored. Return type hinting
won't help when setting either, although it would help with getting. All
that being said, type hinting aside, the syntax I proposed is, in my
opinion, the most consistent out of any other proposal thus far (arguably
aside from yours, I'll go over that momentarily).

- "We must deal with two different syntaxes for the same thing" I don't
quite understand what you mean here, unless you're talking about braces
inside braces. It seems your code examples make your intended point here a
bit clearer, though.

- "IDE's, documentation tools, static analyses tools or similar tools have
a huge effort to implement this syntax. With the method syntax it's only a
small effort" While we want to strive to keep a clean and consistent
syntax, I don't think molding to whatever is easiest for IDE's is a good
idea.

- "We have to create new rules about how the documentation for this syntax
should look like" From my point of view, this isn't so much a concern as a
to-do item later on.


On to your proposal:

I'm not a fan of this:

> public function get hours() {}
>
This is adding another keyword after function, which is arguably more
inconsistent than some previous proposals.

I'm sort of okay with this:

> public get hours() {}
>
Replacing function with get/set/isset/unset... but it still seems a bit too
inconsistent and insensible. Replacing the function keyword with the name
of a preexisting function? I also do not like how the accessors are
separated from one another, which is not the case with the previous
proposals.

All in all, I still prefer my previous proposal to this.

On Tue, Oct 9, 2012 at 12:46 AM, Christian Kaps
<christian.kaps@mohiva.com>wrote:

> Hi,
>
> typehinting should definitely be available for this feature. But I have
> another question. Why not go more consistent with the rest of the language?
> I have mentioned this previously as the first proposal comes up on the
> list. In my opinion the AS3 getter and setter syntax(
> http://help.adobe.com/**en_US/ActionScript/3.0_**ProgrammingAS3/**
> WS5b3ccc516d4fbf351e63e3d118a9**b90204-7f30.html#**
> WS5b3ccc516d4fbf351e63e3d118a9**b90204-7fcb<http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f30.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7fcb>)
> fits more into the language as the proposed one.
>
> Here are my concerns:
> - I do not like the extra indentation level and it's ugly to document (OK,
> this is a personal preference)
> - It isn't possible to declare a private setter and a public getter, as it
> is possible with methods
> - If we ever get return type hinting/checks then we needn't consider how
> the syntax has to look
> - We must deal with two different syntaxes for the same thing, because
> both are methods
> - IDE's, documentation tools, static analyses tools or similar tools have
> a huge effort to implement this syntax. With the method syntax it's only a
> small effort
> - We have to create new rules about how the documentation for this syntax
> should look like
>
> For me the following syntax seems more consistent with the rest of PHP:
>
> public get hours() {}
> public set hours(DateTime $dateTime) {}
> public isset hours() {}
> public unset hours() {}
>
> Or:
>
> public function get hours() {}
> public function set hours(DateTime $dateTime) {}
> public function isset hours() {}
> public function unset hours() {}
>
> Or:
>
> public function get $hours() {}
> public function set $hours(DateTime $dateTime) {}
> public function isset $hours() {}
> public function unset $hours() {}
>
> Cheers,
> Christian
>
> Am 09.10.2012 05:08, schrieb Jazzer Dane:
>
> > […]

---

## #63303 — Nikita Popov — 2012-10-09T13:01:05+00:00

URL: https://externals.io/message/63278#63303 · In reply to: #63278

> It's been a while since I posted any updates about this, a few individuals have been asking about it privately and wanting me to get it out the door for PHP 5.5 release.  It's come a long way since the last time I posted about it.
>
> RFC Document: https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented
>
> Example Usage:
>
> class TimePeriod {
>     private $Seconds = 3600;
>
>     public $Hours {
>         get { return $this->Seconds / 3600; }
>         set { $this->Seconds = $value; }
>         isset<http://www.php.net/isset> { return isset<http://www.php.net/isset>($this->Seconds); }
>         unset<http://www.php.net/unset> { unset<http://www.php.net/unset>($this->Seconds); }
>     }
> }
>
> Changes / Updates
>
> *         isset/unset accessor functions now implemented (object & static context, auto implementations, etc)
>
> *         static accessor now fully functional
>
> *         Reference functionality validated, tests written
>
> *         All operators have been tested, tests written
>
> *         read-only and write-only keywords: Added explanation of reasons for inclusion at the top of the appropriate RFC section
>
> *         Tested for speed, approaches or meets __get() speed.
>
> Internally things have changed quite a bit
>
> *         cleaned up and simplified
>
> *         had been using 4 to 5 additional fn_flag slots, now down to two (READ_ONLY and WRITE_ONLY)
>
> *         the automatic implementations now compiled internal php code, this greatly simplified that part of the code and future proofed it.
>
> The code is available at the url below and is up to date with master, all tests pass.
> https://github.com/cpriest/php-src
>
> I'd like to get this project wrapped up in time to make it to the 5.5 release, only a few things remain to be completed/updated:
>
> *         Check on reflection code written prior to major changes (tests still pass)
>
> *         Add a few more reflection functions that were requested
>
> In total there are 79 tests for this new functionality, if there are any others that I have missed, please let me know.

What concerns me with the current implementation is that it leaks many
implementation details, in particular the fact that the accessors are
implemented as *real* __getXYZ methods and automatic implementations
also use *real* $__XYZ properties.

A few examples:

## 1 - __getProperty() method directly callable

class Test {
    public $property {
        get { return 123; }
    }
}

$test = new Test;
var_dump($test->property); // int(123)
var_dump($test->__getProperty()); // int(123)

## 2 - __getProperty() method exposed via exception

class Test {
    public $throwingProperty {
        get { throw new Exception; }
    }
}

(new Test)->throwingProperty;

exception 'Exception' in /home/nikic/dev/php-src/t29.php:9
Stack trace:
#0 /home/nikic/dev/php-src/t29.php(31): Test->__getthrowingProperty()
#1 {main}

## 3 - Can directly access $__automaticProperty and even unset it
(causing notices in the internal code)

class Test {
    public $automaticProperty {
        get; set;
    }

    public function getAutomaticProperty() {
        return $this->__automaticProperty;
    }

    public function unsetAutomaticProperty() {
        unset($this->__automaticProperty);
    }
}

$test->automaticProperty = 'foo';
var_dump($test->getAutomaticProperty());
$test->unsetAutomaticProperty();
var_dump($test->automaticProperty);

string(3) "foo"

Notice: Undefined property: Test::$__automaticProperty in
/home/nikic/dev/php-src/t29.php on line 13
 `NULL` 

=====

I feel like this approach to the implementation will be a big can of
worms. Sure, it works, but it is rather fragile and the enduser ends
up dealing with internal stuff which he ought not care about. I think
it would be better to cleanly separate out the accessor
implementation. It might require more code now, but will be better in
the long run.

Nikita

---

## #63304 — Etienne Kneuss — 2012-10-09T13:15:01+00:00

URL: https://externals.io/message/63278#63304 · In reply to: #63303

Hi,



> 
> > […]
>
> What concerns me with the current implementation is that it leaks many
> implementation details, in particular the fact that the accessors are
> implemented as *real* __getXYZ methods and automatic implementations
> also use *real* $__XYZ properties.
>
> A few examples:
>
> ## 1 - __getProperty() method directly callable
>
> class Test {
>     public $property {
>         get { return 123; }
>     }
> }
>
> $test = new Test;
> var_dump($test->property); // int(123)
> var_dump($test->__getProperty()); // int(123)
>
> ## 2 - __getProperty() method exposed via exception
>
> class Test {
>     public $throwingProperty {
>         get { throw new Exception; }
>     }
> }
>
> (new Test)->throwingProperty;
>
> exception 'Exception' in /home/nikic/dev/php-src/t29.php:9
> Stack trace:
> #0 /home/nikic/dev/php-src/t29.php(31): Test->__getthrowingProperty()
> #1 {main}
>
> ## 3 - Can directly access $__automaticProperty and even unset it
> (causing notices in the internal code)
>
> class Test {
>     public $automaticProperty {
>         get; set;
>     }
>
>     public function getAutomaticProperty() {
>         return $this->__automaticProperty;
>     }
>
>     public function unsetAutomaticProperty() {
>         unset($this->__automaticProperty);
>     }
> }
>
> $test->automaticProperty = 'foo';
> var_dump($test->getAutomaticProperty());
> $test->unsetAutomaticProperty();
> var_dump($test->automaticProperty);
>
> string(3) "foo"
>
> Notice: Undefined property: Test::$__automaticProperty in
> /home/nikic/dev/php-src/t29.php on line 13
> `NULL` 
>
> =====
>
> I feel like this approach to the implementation will be a big can of
> worms. Sure, it works, but it is rather fragile and the enduser ends
> up dealing with internal stuff which he ought not care about. I think
> it would be better to cleanly separate out the accessor
> implementation. It might require more code now, but will be better in
> the long run.
>

I disagree, to me that this feature is all about syntactic sugar, as
such it does what it expected: it generates concrete properties and
methods that are somewhat hidden to the end-user.

I feel that any implementation that do not rely on proper
properties/methods would be a big hack.

Best,

> Nikita
>
> --
> 
> 
>



-- 
Etienne Kneuss
http://www.colder.ch

---

## #63305 — Leigh — 2012-10-09T13:41:25+00:00

URL: https://externals.io/message/63278#63305 · In reply to: #63303

> What concerns me with the current implementation is that it leaks many
> implementation details, in particular the fact that the accessors are
> implemented as *real* __getXYZ methods and automatic implementations
> also use *real* $__XYZ properties.

Further to this, take the following example.

public $_state {
    set { ... }
}

This automatically generates a "hidden" function __set_state(), which
is a magic method already (and should be declared static, and take an
array as it's only parameter)

Another fine example of how automatically generating *real*
implementations can potentially break things.

---

## #63306 — Nathan Bruer — 2012-10-09T14:56:22+00:00

URL: https://externals.io/message/63278#63306 · In reply to: #63304

Is there a reason why we cannot implement this using PHP's already widely used function syntax:

class TimePeriod {
    private $Seconds = 3600;

    public $Hours {
        public function get() { return $this->Seconds / 3600; }
        private function set($value) { $this->Seconds = $value; }
        /*public implied */function isset(){ return isset ($this->Seconds); }
        private function unset() { unset ($this->Seconds); }
    }
}

This would be much less confusing as it follows other PHP standards for creating functions and such. I know C# has a similar syntax to what is proposed, but we are not developing for C# we are developing for PHP which has its own syntax rules that differ from C#'s and my vote is to follow PHP's already in existent syntax format.

---
-Nathan Bruer

-----Original Message-----
From: ekneuss@gmail.com [mailto:ekneuss@gmail.com] On Behalf Of Etienne Kneuss
Sent: Tuesday, October 09, 2012 8:15 AM
To: Nikita Popov
Cc: Clint Priest; internals@lists.php.net
Subject: Re: [PHP-DEV] [RFC] Propety Accessors v1.1

Hi,



> 
> > […]
>
> What concerns me with the current implementation is that it leaks many 
> implementation details, in particular the fact that the accessors are 
> implemented as *real* __getXYZ methods and automatic implementations 
> also use *real* $__XYZ properties.
>
> A few examples:
>
> ## 1 - __getProperty() method directly callable
>
> class Test {
>     public $property {
>         get { return 123; }
>     }
> }
>
> $test = new Test;
> var_dump($test->property); // int(123) 
> var_dump($test->__getProperty()); // int(123)
>
> ## 2 - __getProperty() method exposed via exception
>
> class Test {
>     public $throwingProperty {
>         get { throw new Exception; }
>     }
> }
>
> (new Test)->throwingProperty;
>
> exception 'Exception' in /home/nikic/dev/php-src/t29.php:9 Stack 
> trace:
> #0 /home/nikic/dev/php-src/t29.php(31): Test->__getthrowingProperty()
> #1 {main}
>
> ## 3 - Can directly access $__automaticProperty and even unset it 
> (causing notices in the internal code)
>
> class Test {
>     public $automaticProperty {
>         get; set;
>     }
>
>     public function getAutomaticProperty() {
>         return $this->__automaticProperty;
>     }
>
>     public function unsetAutomaticProperty() {
>         unset($this->__automaticProperty);
>     }
> }
>
> $test->automaticProperty = 'foo';
> var_dump($test->getAutomaticProperty());
> $test->unsetAutomaticProperty();
> var_dump($test->automaticProperty);
>
> string(3) "foo"
>
> Notice: Undefined property: Test::$__automaticProperty in 
> /home/nikic/dev/php-src/t29.php on line 13 `NULL` 
>
> =====
>
> I feel like this approach to the implementation will be a big can of 
> worms. Sure, it works, but it is rather fragile and the enduser ends 
> up dealing with internal stuff which he ought not care about. I think 
> it would be better to cleanly separate out the accessor 
> implementation. It might require more code now, but will be better in 
> the long run.
>

I disagree, to me that this feature is all about syntactic sugar, as such it does what it expected: it generates concrete properties and methods that are somewhat hidden to the end-user.

I feel that any implementation that do not rely on proper properties/methods would be a big hack.

Best,

> Nikita
>
> --
>  To unsubscribe, 
> visit: http://www.php.net/unsub.php
>



--
Etienne Kneuss
http://www.colder.ch

---

## #63307 — Leigh — 2012-10-09T17:19:46+00:00

URL: https://externals.io/message/63278#63307 · In reply to: #63278

> RFC Document: https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented

public $property {
set { $this->property = ($this->property*2)+$value }
get;
}

How do I reference the property being set from within the function? The way
I have done it in the example will cause recursion? How can I assign to
"self"?

How do I set the default value of $property when the object is created?
Surely I don't have to reverse the set accessors logic and set the inverse
in __construct?

---

## #63309 — johannes@schlueters.de — 2012-10-10T00:16:22+00:00

URL: https://externals.io/message/63278#63309 · In reply to: #63278

> It's been a while since I posted any updates about this, a few individuals have been asking about it privately and wanting me to get it out the door for PHP 5.5 release.  It's come a long way since the last time I posted about it.
> 
> RFC Document: https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented

About the items in regards to reflection in there:

The RFC states
        ReflectionClass::getMethods() will not return accessor functions
        (hides implementation detail).
Up until now reflection is leaky and is telling the truth. We should
either keep that or completely clean up reflection. (mind also
 `get_class_methods()` and such)

The RFC also introduces a new class ReflectionPropertyAccessor and has
methods returning ReflectionProperty and ReflectionPropertyAccessor.
there should either be a common base class or interface (see i.e.
ReflectionFunctionAbstract)

What will  ReflectionPropertyAccessor->getGetter()->getName() return? I
guess reflection will be leaky there? (see first item)

johannes

---

## #63310 — Jazzer Dane — 2012-10-10T02:33:20+00:00

URL: https://externals.io/message/63278#63310 · In reply to: #63307

I think Leigh brings up some important flaws to in the current RFC. What
Leigh is asking for does not appear to be possible, and in my opinion, it
should be.

I also agree with Rasmus, to a certain extent.
By putting only a getter/setter, the developer essentially sets the
property as read or write only. At first glance, there is no need for the
read-only or write-only keyword. Except... subclassing may or may not be an
issue.

By setting a property to read-only, it ensures that 'set' can never be set
by a subclass. Unless I redefine the entire property... or is that not even
possible? *The RFC isn't very clear but it appears that there is no way to
redefine the entire property, as if you define it in the subclass with only
get, then it will take set, isset, and unset from the parent class, correct?
* Though, that can be outright stopped by making the property final. But
then there is no point in having read/write-only.

From what I can tell, read-only becomes useful if I extend the class and
want to partially modify the property.
Example:

> class A {
>   public $seconds = 3600;
>
>   public $hours {
>     get() { return $this->seconds / 3600 };
>   }
> }
>
> class B extends A {
>   public $hours { // Maintains 'get' from class A
>     set($value) { $this->seconds = $value; }
>   }
> }
>

^There's no way to stop the developer from doing that without read-only.

Also, if the property is public, what if an outside class tries to do this:

> class A {
>   public $seconds = 3600;
>
>   public $hours {
>     get() { return $this->seconds / 3600 };
>   }
> }
>
> $object = new A();
> $object->hours = 100;
>
What happens then?

And similarly, how do we set a public property as a property accessor, hmm?

class A {
>   public $hours = 1;
> }
>
> $seconds = 20;
>
> $object = new A();
> $object->hours = { // Does this work?
>   get() { return $seconds; }
> };
>


There's definitely still some questions to answer before this RFC is ready.



> > […]
> https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented
>
> public $property {
> set { $this->property = ($this->property*2)+$value }
> get;
> }
>
> How do I reference the property being set from within the function? The way
> I have done it in the example will cause recursion? How can I assign to
> "self"?
>
> How do I set the default value of $property when the object is created?
> Surely I don't have to reverse the set accessors logic and set the inverse
> in __construct?

---

## #63311 — David Muir — 2012-10-10T03:28:47+00:00

URL: https://externals.io/message/63278#63311 · In reply to: #63296

> - "If we ever get return type hinting/checks then we needn't consider how
> the syntax has to look" From what I know, this isn't planned for PHP 5.5
> and any proposals for it have been largely ignored. Return type hinting
> won't help when setting either, although it would help with getting. All
> that being said, type hinting aside, the syntax I proposed is, in my
> opinion, the most consistent out of any other proposal thus far (arguably
> aside from yours, I'll go over that momentarily).

Excellent point. Return type-hints only affect the getter, and even then 
it could be a moot point if the property itself could be bound to a 
particular type. It would actually be a much cleaner solution, and 
wouldn't require any superfluous parens in the declaration:

class MyClass{

     public SomeClass $property {
         get {...}
         set {...}
     }
}

$foo = new MyClass;
$bar = new SomeClass;
$foo->property = $bar; //ok
$foo->property = new StdClass; //type mismatch

Heck, half the time setters and getters are implemented specifically for 
this purpose. If the property itself could be typed, then 90% of the 
time we wouldn't even need to specify get/set. Just give the property a 
type and be done with it.

That said, it wouldn't help for scalar values, and that leads to a 
problem with the current syntax (AFAICS). You can't specify the initial 
value for a property:

eg:
class MyClass{

     public $property = 5    //?can we do this?
     {
         set($value){
             if(!is_int($value)){
                 throw new InvalidArgumentException('value of wrong type');
             }
             $this->__property = $value;
         }
     }
}

Or would that have to happen in the constructor?

class MyClass{

     public $property
     {
         set($value){
             if(!is_int($value)){
                 throw new InvalidArgumentException('value of wrong type');
             }
             $this->__property = $value;
         }
     }

     public function __construct(){
         $this->property = 5;
     }
}


Cheers,
David

---

## #63312 — Clint Priest — 2012-10-10T03:51:48+00:00

URL: https://externals.io/message/63278#63312 · In reply to: #63310

Wow, I'm surprised by all the talk about this RFC this time around.  I posted this numerous times in the past trying to elicit feedback and got little to none, so I took the time to write it as I thought it should be written.  Some of these things will take considerable effort to fix/correct/change.



I'll try to address everyone's comments/questions in one post:



________________________________

Nikita:

> What concerns me with the current implementation is that it leaks many implementation details, in particular the fact that the accessors are implemented as *real* __getXYZ methods and automatic implementations also use *real* $__XYZ properties.

>

> A few examples:

>

> ## 1 - __getProperty() method directly callable

>

> class Test {

>     public $property {

>         get { return 123; }

>     }

> }

>

> $test = new Test;

> var_dump($test->property); // int(123)

> var_dump($test->__getProperty()); // int(123)

>



I don't particularly see this as a problem (the ability to use it as a getter or call it as a function), but see my comments at the end.  I also don't particularly see the point of auto implemented getters/setters ( public $h { get; set; } )



> ## 2 - __getProperty() method exposed via exception

>

> class Test {

>     public $throwingProperty {

>         get { throw new Exception; }

>     }

> }

>

> (new Test)->throwingProperty;

>

> exception 'Exception' in /home/nikic/dev/php-src/t29.php:9 Stack trace:

> #0 /home/nikic/dev/php-src/t29.php(31): Test->__getthrowingProperty()

> #1 {main}

>



I have gone to great lengths to shield the implementation details from users, this one slipped past me.  Nearly all errors that are shown reference a property rather than a function name and this could also be cleaned up.



> ## 3 - Can directly access $__automaticProperty and even unset it (causing notices in the internal code)

>

> class Test {

>     public $automaticProperty {

>         get; set;

>     }

>

>     public function getAutomaticProperty() {

>         return $this->__automaticProperty;

>     }

>

>     public function unsetAutomaticProperty() {

>         unset($this->__automaticProperty);

>     }

> }

>

> $test->automaticProperty = 'foo';

> var_dump($test->getAutomaticProperty());

> $test->unsetAutomaticProperty();

> var_dump($test->automaticProperty);

>

> string(3) "foo"

>

> Notice: Undefined property: Test::$__automaticProperty in /home/nikic/dev/php-src/t29.php on line 13 `NULL` 



I'm not even sure that automatic backing fields are even desired, I never felt the need to have them in C# and the only reason they were included is because they were a part of Dennis's original proposal.  Eliminating them would eliminate this as an issue.



>

> =====

>

> I feel like this approach to the implementation will be a big can of worms. Sure, it works, but it is rather fragile and the enduser ends up dealing with internal stuff which he ought not care about. I think it would be better to cleanly separate out the accessor implementation. It might require more code now, but will be better in the long run.



All three of these issues, could be addressed I believe by not having the functions and/or properties a part of the ordinary HashTables, or to have flags set on them.  I believe there is already a SHADOW flag type defined which may be able to be used for this type of functionality.



________________________________

Leigh:

> Further to this, take the following example.

>

> public $_state {

>     set { ... }

> }

>

> This automatically generates a "hidden" function __set_state(), which is a magic method already (and should be declared static, and take an array as it's only parameter)

>

> Another fine example of how automatically generating *real* implementations can potentially break things.



This would clearly cause problems, again this could possibly be addressed by not having the accessor functions be a part of the standard Functions HashTable, the functions would not even need to have names at that point if they are not intended to be accessible directly.



> public $property {

> set { $this->property = ($this->property*2)+$value } get; }

>

> How do I reference the property being set from within the function? The way I have done it in the example will cause recursion? How can I assign to "self"?

>

> How do I set the default value of $property when the object is created?

> Surely I don't have to reverse the set accessors logic and set the inverse in __construct?



Generally speaking, I don't know why you would use an automatic backing getter with a separate setter, but if you wanted to do that, at present you would access the automatic backing field by $this->__property.



The above will not cause recursion, it is protected from recursion by the same mechanism that __get() and __set() are protected.  In fact, the above code would set an actual property named $property on the object which would then side-step the accessor entirely (true properties take precedence over accessors, though they may only be "set" from within the setter of the accessor.  This may be a bit confusing, but I specifically wrote it this way for the purpose of lazy-loading.



For example:



public $objList {

   get { return $this->objList = new myList(); }

   set { $this->objList = $value; }
}



The first access of the $objList property getter would create the object and attempt to set its-self which would be passed to the setter, the setter (now guarded) will directly set the property on the object, further calls to $objList would retrieve the already created object (bypassing the accessor).  To get out of that situation, you would simply unset($objList) and the accessor would take over again.



Please keep in mind that this is only possible from within the setter of the property, nothing outside the setter of the property can create a real property named the same as the accessor, except the setter of the accessor.



________________________________

Nathan:

> This would be much less confusing as it follows other PHP standards for creating functions and such. I know C# has a similar syntax to what is proposed, but we are not developing for C# we are developing for PHP which has its own syntax rules that differ from C#'s and my vote is to follow PHP's already in existent syntax format.



I think having the function keyword there is superfluous, it adds more code to be read, while accessors have the powers of a function, they are quite different from a function.  You would probably never have a 35 line getter, for example.



________________________________

Rasmus:

> My only remaining comment is on the read-only and write-only keywords...

> this seems really superfluous and strange to me - the syntax (using a hyphenated keyword) and the feature itself, is way off the grid as compared to other languages.



There is an important distinction with the read-only and write-only keywords and they are analogous to the final keyword.  The final keyword prevents any subclasses from over-riding something declared as final.  Final is supported for a property as well.  The difference here is that a read-only property is semi-final.  Subclasses may redefine a get declared as read-only but may not declare a setter.  Personally I am not a fan of the concepts of final, read-only or write-only.  They were included only because I thought the original RFC for which I was implementing had been ratified and the feature was desired.



________________________________

Johannes:

> About the items in regards to reflection in there:

>

> The RFC states

>         ReflectionClass::getMethods() will not return accessor functions

>         (hides implementation detail).

> Up until now reflection is leaky and is telling the truth. We should either keep that or completely clean up reflection. (mind also

> `get_class_methods()` and such)



I have not done anything with `get_class_methods()` but I certainly could.  Probably a better solution would be to have `get_class_methods()` use Reflection to do its work, so that there is not duplicate code in the core?



I see no reason to continue leaking new code, if someone wants to head up an effort to make the rest of Reflection not leak implementation details then great, but to purposely leak implementation details for new features just doesn't make sense to me.



> The RFC also introduces a new class ReflectionPropertyAccessor and has methods returning ReflectionProperty and ReflectionPropertyAccessor.

> there should either be a common base class or interface (see i.e.

> ReflectionFunctionAbstract)

>



I'm not certain there is a point to having a new base class, I would need to look at the code but I would bet that ReflectionPropertyAccessor is a sub-class of ReflectionProperty.  In any case, we have the instanceof operator which can be used to distinguish between the results, no?



> What will  ReflectionPropertyAccessor->getGetter()->getName() return? I guess reflection will be leaky there? (see first item)



I wrote the reflection additions very early on so I would need to look at the code, but I am pretty certain that the above would return the name of the property, not the function.



________________________________

Jazzer:

> I think Leigh brings up some important flaws to in the current RFC. What Leigh is asking for does not appear to be possible, and in my opinion, it should be.



I'm really not quite clear on what Leigh was going for with the code she indicated, I think she was trying to demonstrate infinite recursion which is not possible due to guards.



> I also agree with Rasmus, to a certain extent.

> By putting only a getter/setter, the developer essentially sets the property as read or write only. At first glance, there is no need for the read-only or write-only keyword. Except... subclassing may or may not be an issue.

>

> By setting a property to read-only, it ensures that 'set' can never be set by a subclass. Unless I redefine the entire property... or is that not even possible? The RFC isn't very clear but it appears that there is no way to redefine the entire property, as if you define it in the subclass with only get, then it will take set, isset, and unset from the parent class, correct? Though, that can be outright stopped by making the property final. But then there is no point in having read/write-only.

>



I tried to be clear about this at the top of the section on read-only and write-only keywords...  There are three possible states:



/* read-only by virtue of the fact that there is no setter, any sub-class may define a setter and/or redefine the getter */

public $Hours {

                get { ... }

}



/* final, no sub-class may redefine any aspect of this accessor */

public final $Hours {

                get { ... }

}



/* Explicitly read-only, sub-classes may redefine the getter but may not define a setter */

public read-only $Hours {

                get { ... }

}



As I mentioned earlier, I'm not a fan of the concept of final, read-only or write-only, they were only included because the original RFC indicated that was what the community had decided on.



> From what I can tell, read-only becomes useful if I extend the class and want to partially modify the property.

> Example:

> class A {

>   public $seconds = 3600;

>

>   public $hours {

>     get() { return $this->seconds / 3600 };

>   }

> }

>

> class B extends A {

>   public $hours { // Maintains 'get' from class A

>     set($value) { $this->seconds = $value; }

>   }

> }

>

> ^There's no way to stop the developer from doing that without read-only.



That is correct



>

> Also, if the property is public, what if an outside class tries to do this:

> class A {

>   public $seconds = 3600;

>

>   public $hours {

>     get() { return $this->seconds / 3600 };

>   }

> }

>

> $object = new A();

> $object->hours = 100;

> What happens then?



A fatal error occurs as there is no setter for hours.  It is a read only property by virtue of the fact that it has no setter.  A sub-class could define a setter for $hours if it so desired (due to the lack of a final or read-only keyword in the declaration).



>

> And similarly, how do we set a public property as a property accessor, hmm?

> class A {

>   public $hours = 1;

> }

>

> $seconds = 20;

>

> $object = new A();

> $object->hours = { // Does this work?

>   get() { return $seconds; }

> };



I'm not quite sure what you mean here, are you asking if you can dynamically define a property?  The answer is no, though I think that would be cool it is likely well beyond my ability to accomplish being that this is my first contribution to the php project.



________________________________

David:

> class MyClass{

>

>      public $property = 5    //?can we do this?

>      {

>          set($value){

>              if(!is_int($value)){

>                  throw new InvalidArgumentException('value of wrong type');

>              }

>              $this->__property = $value;

>          }

>      }

> }

>

> Or would that have to happen in the constructor?

>

> class MyClass{

>

>      public $property

>      {

>          set($value){

>              if(!is_int($value)){

>                  throw new InvalidArgumentException('value of wrong type');

>              }

>              $this->__property = $value;

>          }

>      }

>

>      public function __construct(){

>          $this->property = 5;

>      }

> }



I think there is some wide-spread confusion over what an accessor is.  An accessor does not store its own value, there is no "memory space" allocated for an accessor unless you use the automatic implementation ( public $h { get; set; } ) but if you're going to do that, you may as well just reduce it to ( private $__h ) which is all the previous "accessor" would have done for you.



Accessors, in my own use, are nearly always used for convenience aliases with conversions ( $Hours calculated based on a real stored $Seconds value) or as an alias to access a value from another class, they are generally not used to simply store or retrieve values, that's what a property is for, an accessor is for executing code with the syntactic sugar of making it seem like it's a variable.



________________________________



In closing for all of this, I really wish that this type of discourse could have happened long ago when I was requesting it, because many, many hours have been put into the current incarnation.   I would like to put together a "vote grid" or something on all that has been discussed here and come to a consensus before I go and re-do any further work.  Does the php community have any voting facilities or is it still done via the wiki pages?  How should I decide who gets a vote and who doesn't?  Should I even be handling the voting myself?

---

## #63313 — Bernhard Schussek — 2012-10-10T07:46:32+00:00

URL: https://externals.io/message/63278#63313 · In reply to: #63312

Hi Clint,

In order to achieve read-only and write-only, we could do something
similar to this:

/* Explicitly read-only, sub-classes may redefine the getter but may
not define a setter */
public $Hours {
    get() { ... }
    final private set() {}
}

This would make the additional keyword superfluous. It's very similar
to what is currently done in Singleton classes that usually have
private constructors.

Second, I'd like to throw in the idea of array accessors. I mentioned
this before, but did not get any response.

public $Addresses {
    offsetSet($offset, $value) { ... }
    offsetGet() { ... }
    offsetUnset($offset) { ... }
    offsetExists($offset) { ... }
}

The reasoning for this feature is that in object-oriented design you
have to process logic when establishing bidirectional associations
between objects. For example, adding an Address to a Contact instance
would require Address::$Contact to be set as well if the association
is bidirectional.

public $Addresses {
    offsetSet($offset, $address) {
        $address->Contact = $this;
    }
}

$contact->Addresses[] = new Address();

What do you think about supporting this?

Cheers,
Bernhard

---

## #63314 — Leigh — 2012-10-10T09:25:24+00:00

URL: https://externals.io/message/63278#63314 · In reply to: #63311

> Up until now reflection is leaky and is telling the truth. We should
> either keep that or completely clean up reflection.

Reflection should always tell the truth, or there is no point in it.


> That said, it wouldn't help for scalar values, and that leads to a problem
> with the current syntax (AFAICS). You can't specify the initial value for a
> property:

This is one of the points I was trying to get across, there is
currently no way to set the default value*. If your setter performs
some sort of calculation on the value, then you're going to have to
reverse that process in order to set the initial value constructor.

*Unless you use the following highly confusing approach.

class MyClass {
    protected $__property = 'default';

    public $property {
        get;
    }
}

---

## #63315 — Leigh — 2012-10-10T09:28:29+00:00

URL: https://externals.io/message/63278#63315 · In reply to: #63312

> Wow, I'm surprised by all the talk about this RFC this time around.  I
> posted this numerous times in the past trying to elicit feedback and got
> little to none, so I took the time to write it as I thought it should be
> written.  Some of these things will take considerable effort to
> fix/correct/change.

Sometimes things get overlooked. Lots of suggestions make their way to
the list, usually by people who have no way to implement the feature
and they disappear as quickly as they are suggested. Be happy you ARE
getting feedback now. The fact people now see this as something that
may be implemented as it is (in a way they don't necessarily like) is
prompting them to speak up about their concerns.

> > […]

> I don't particularly see this as a problem (the ability to use it as a
> getter or call it as a function), but see my comments at the end.  I also
> don’t particularly see the point of auto implemented getters/setters (
> public $h { get; set; } )

For me the problem is simply that you can call the accessor functions
directly. I don't like it.

I don't like the fact that accessors and their associated properties
are implemented as direct (yet slightly obfuscated/hidden) elements of
the containing class. It's unintuitive (I'd even go as far as saying
confusing)

A property should be a property, not a collection of hidden methods
and variables. If it needs to be seen whether a property implements
accessors, this should be done through reflection.


> > […]

> I'm not even sure that automatic backing fields are even desired

See above I guess, I agree that these "hidden" properties should not
exist in the first place.

> > […]

> All three of these issues, could be addressed I believe by not having the
> functions and/or properties a part of the ordinary HashTables, or to have
> flags set on them.  I believe there is already a SHADOW flag type defined
> which may be able to be used for this type of functionality.

Nikita do you have any other proposals for how this should be
addressed? I think most of my concerns with this revolve around the
implementation not being cleanly separated as you put it. I believe
that setters/getters would be a tremendously powerful and useful
addition to the language, just not quite like this, so lets here your
proposal please :)

> > […]

> > […]

> Generally speaking, I don't know why you would use an automatic backing
> getter with a separate setter, but if you wanted to do that, at present you
> would access the automatic backing field by $this->__property.

Kind of confusing. We have to think of the users who just want to pick
this up and run with it. You can't say "I don't know why you would",
because people will do strange things, and you have to make it so that
the behaviour is predictable, and intuitive.

> The above will not cause recursion, it is protected from recursion by the
> same mechanism that __get() and __set() are protected.

Good, thanks. I didn't get to test it since I was on a bus at the time :)

> In fact, the above
> code would set an actual property named $property on the object which would
> then side-step the accessor entirely (true properties take precedence over
> accessors, though they may only be "set" from within the setter of the
> accessor.  This may be a bit confusing, but I specifically wrote it this way
> for the purpose of lazy-loading.

Yep, confusing!

> The first access of the $objList property getter would create the object and
> attempt to set its-self which would be passed to the setter, the setter (now
> guarded) will directly set the property on the object, further calls to
> $objList would retrieve the already created object (bypassing the accessor).
> To get out of that situation, you would simply unset($objList) and the
> accessor would take over again.

Also confusing. (Think of the users!)

> > […]

> I'm really not quite clear on what Leigh was going for with the code she
> indicated, I think she was trying to demonstrate infinite recursion which is
> not possible due to guards.

She? Only when I go shoe shopping with Nikita at the weekends...

Actually the recursion thing was just a query I hadn't tested, and you
have answered. The other question I asked was "How do you set the
default value of the property with the accessor syntax?"

> I think there is some wide-spread confusion over what an accessor is.  An
> accessor does not store its own value, there is no “memory space” allocated
> for an accessor unless you use the automatic implementation ( public $h {
> get; set; } ) but if you’re going to do that, you may as well just reduce it
> to ( private $__h ) which is all the previous “accessor” would have done for
> you.

> Accessors, in my own use, are nearly always used for convenience aliases
> with conversions ( $Hours calculated based on a real stored $Seconds value)
> or as an alias to access a value from another class, they are generally not
> used to simply store or retrieve values, that’s what a property is for, an
> accessor is for executing code with the syntactic sugar of making it seem
> like it’s a variable.

In my opinion

public $property; // This is a property

public $property { // This is still a property
    set { ... }
}

I don't see accessors tied to the property as ways of simply setting
some other value (in your example, setting $seconds via $hours). I
have a feeling a lot of people will not be using these simply for
conversions, they will also be using them for validation and
sanitising. You already saw Niki throwing an Exception inside an
accessor.

try {
    $user->username = $rawData
} catch (InvalidUsernameException $e) {
    ...
}

They will expect the $username property to contain the data, not
$__username, and not having to implement $saneUsername as a second
property to store it in.

---

Next page: https://externals.io/message/63278.md?page=2
