I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.
Nikita and I (as well as Stas a bit) have all been working hard to make
this happen for 5.5, voting and the specifications are here:
https://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
Thanks,
-Clint
-Clint
I'm happy to say that Property Accessors is ready for a vote for inclusion
in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to make
this happen for 5.5, voting and the specifications are here:https://wiki.php.net/rfc/**propertygetsetsyntax-v1.2#**votinghttps://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
Thanks,
-Clint
This is great news, thank you very much for all your hard work! Its much
appreciated!
I'm happy to say that Property Accessors is ready for a vote for inclusion
in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to make
this happen for 5.5, voting and the specifications are here:https://wiki.php.net/rfc/**propertygetsetsyntax-v1.2#**votinghttps://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
Thanks,
-Clint
This is great news, thank you very much for all your hard work! Its much
appreciated!
Absolutely brilliant that this feature has been developed enough to
get to this state.
--
Richard Quadling
Twitter : @RQuadling
EE : http://e-e.com/M_248814.html
Zend : http://bit.ly/9O8vFY
I'm happy to say that Property Accessors is ready for a vote for inclusion in 5.5 release.
Nikita and I (as well as Stas a bit) have all been working hard to make this happen for
5.5, voting and the specifications are here:
I'll say my peace on this. This is a very good implementation, and as long as authors use
accessors that depend on a separate property for storage (like other langs require),
everything will be straightforward. Otherwise, I fear they're in for some confusing behavior.
Consider the code from the RFC:
class TimePeriod {
public $Hours {
get { return $this->Hours ?: "not specified"; }
set { $this->Hours = $value; }
}
}
$tp = new TimePeriod();
$tp->Hours; // "not specified"
isset($tp->Hours); // true!?
The auto implementation of isset compares $this->Hours to NULL, but since $this->Hours
goes through the getter, it will return "not specified". So the property will always
appear to be isset.
-
The guards seem spooky: A set of tokens ($this->prop) will have varying behavior (e.g.
direct prop read vs. getter call) depending on the call stack. -
Giving issetter/unsetter no direct access to the property limits functionality and leads
to weirdness like the example above.
Steve Clay
I'll say my peace on this. This is a very good implementation, and as
long as authors use accessors that depend on a separate property for
storage (like other langs require), everything will be
straightforward. Otherwise, I fear they're in for some confusing
behavior.Consider the code from the RFC:
class TimePeriod {
public $Hours {
get { return $this->Hours ?: "not specified"; }
set { $this->Hours = $value; }
}
}$tp = new TimePeriod();
$tp->Hours; // "not specified"
isset($tp->Hours); // true!?
$tp->Hours isset, the property exists and it's value is non-null.
The auto implementation of isset compares $this->Hours to NULL, but
since $this->Hours goes through the getter, it will return "not
specified". So the property will always appear to be isset.
The guards seem spooky: A set of tokens ($this->prop) will have
varying behavior (e.g. direct prop read vs. getter call) depending on
the call stack.
This is the same as would occur with isset against an undefined
property, that would call __isset(), followed by __get() which would
then compare the value to NULL.Giving issetter/unsetter no direct access to the property limits
functionality and leads to weirdness like the example above.
This is possible, simply by supplying your own implementation of
isset/unset that calls isset/unset, such as:
public $foo {
get; set;
isset { return isset($this->foo); }
unset { unset($this->foo); }
}
The above five lines of code is exactly equivalent in functionality to:
public $foo;
-Clint
https://wiki.php.net/rfc/**propertygetsetsyntax-v1.2#**votinghttps://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
I'll say my peace on this. This is a very good implementation, and as
long as authors use accessors that depend on a separate property for
storage (like other langs require), everything will be straightforward.
Otherwise, I fear they're in for some confusing behavior.Consider the code from the RFC:
class TimePeriod {
public $Hours {
get { return $this->Hours ?: "not specified"; }
set { $this->Hours = $value; }
}
}$tp = new TimePeriod();
$tp->Hours; // "not specified"
isset($tp->Hours); // true!?$tp->Hours isset, the property exists and it's value is non-null.
The auto implementation of isset compares $this->Hours to NULL, but since
$this->Hours goes through the getter, it will return "not specified". So
the property will always appear to be isset.
- The guards seem spooky: A set of tokens ($this->prop) will have varying
behavior (e.g. direct prop read vs. getter call) depending on the call
stack.This is the same as would occur with isset against an undefined property,
that would call __isset(), followed by __get() which would then compare the
value to NULL.
- Giving issetter/unsetter no direct access to the property limits
functionality and leads to weirdness like the example above.This is possible, simply by supplying your own implementation of
isset/unset that calls isset/unset, such as:public $foo {
get; set;
isset { return isset($this->foo); }
unset { unset($this->foo); }
}The above five lines of code is exactly equivalent in functionality to:
public $foo;
-Clint
--
I'm not sure if this has already come up in past discussion or not. So
I apologize in advance if this is repetitive. The discussion for property
accessors has been so lengthy I couldn't find the time to keep up with it
all.
However, I found some time to play around with the patch today and I
noticed something that might use improving. When you use var_dump()
on the
object properties that have defined get accessors don't produce any useful
output with var_dump. Is this fixable?
On Sun, Jan 20, 2013 at 5:46 AM, Sherif Ramadan theanomaly.is@gmail.comwrote:
I'm not sure if this has already come up in past discussion or not. So
I apologize in advance if this is repetitive. The discussion for property
accessors has been so lengthy I couldn't find the time to keep up with it
all.However, I found some time to play around with the patch today and I
noticed something that might use improving. When you usevar_dump()
on the
object properties that have defined get accessors don't produce any useful
output with var_dump. Is this fixable?
The var_dump will output the state of the object, i.e. the values that are
internally stored. It will not go through the get accessors, rather it will
directly give you the value of the underlying property. If the underlying
property is not used, then it will just give you NULL.
Nikita
On Sun, Jan 20, 2013 at 5:46 AM, Sherif Ramadan theanomaly.is@gmail.comwrote:
I'm not sure if this has already come up in past discussion or not. So
I apologize in advance if this is repetitive. The discussion for property
accessors has been so lengthy I couldn't find the time to keep up with it
all.However, I found some time to play around with the patch today and I
noticed something that might use improving. When you usevar_dump()
on the
object properties that have defined get accessors don't produce any useful
output with var_dump. Is this fixable?The var_dump will output the state of the object, i.e. the values that are
internally stored. It will not go through the get accessors, rather it will
directly give you the value of the underlying property. If the underlying
property is not used, then it will just give you NULL.
While I agree with your initial assessment of the accessor not having set
any value, and therefore the logic of var_dump only providing what is
stored in the object's instance properties, I disagree with your
interpretation of what var_dump should do here.
Here is my reasoning for this:
-
var_dump is documented to provide you with information about a variable
(there is no mention of its implementation being limited to what the
variable stores). -
Even if you interpret this to mean that var_dump will output the state
of the object then you are still wrong, since var_dump($foo->accessor) will
give me a value that the object does not store if the accessor returns a
computation rather than a stored value. -
If this were a discussion of distinguishing between magic methods such
as __get/__set then we can simply say that only inaccessible properties can
invoke such methods and as such we have no confusion between what the
object stores and what var_dump returns when invoking those methods. With
accessors it is not the case at all.
Here's an example
class surface {
public $area {
get { return $this->width * $this->height; }
private set;
}
public $width {
set($val) { $this->width = $val; }
private get;
}
public $height {
set ($val) { $this->height = $val; }
private get;
}
}
$surface = new surface;
var_dump($surface);
this gives us the following output for $surface...
object(surface)#1 (3) {
["area"]=>
NULL
["width"]=>
NULL
["height"]=>
NULL
}
This is to be completely expected since, technically, all we did here was
use class initialization that provided public properties initialized to
null.
However, let's say we set $surface->width and $surface->height...
$surface->width = 4;
$surface->height = 2;
var_dump($surface);
Now $surface shows us the following from var_dump....
object(surface)#1 (3) {
["area"]=>
NULL
["width"]=>
int(4)
["height"]=>
int(2)
}
This is not accurate since var_dump($surface->area) will give us the
following...
int(8)
It's not obvious what's happening here if I'm debugging this code in real
life, because on one hand I can see that my instance property returns a
value (which I expect). On the other hand I see my object has a null
property, which I don't expect. If this were magic the property would
simply not exist and i would know to look for __get / __set magic. Now, if
we argue that accessors are magic then why do they also not work like
magic? This is a bit of a hybrid approach, and I understand the reasoning
for most of what's going on here. I'm not here to argue about
implementation details.
What I'm saying is this kind of behavior needs far more serious reasoning
than the very naive assesment you're making above.
I mean that with all due respect. Just wondering if there is another take
on this from anyone else?
Sherif,
He who asks too many questions
Nikita
On Sun, 20 Jan 2013 14:35:14 +0100, Sherif Ramadan
theanomaly.is@gmail.com wrote:
What I'm saying is this kind of behavior needs far more serious reasoning
than the very naive assesment you're making above.I mean that with all due respect. Just wondering if there is another take
on this from anyone else?
I think the current behavior is most appropriate one for var_dump()
(and
array casts/get_object_vars()). It's the same behavior as if you had
manually defined getXXX() methods or used __get().
If you start marking function calls, you get new problems like handling
getters that throw exceptions or have side effects ("the code behaves
differently when add a var_dump()
?!").
--
Gustavo Lopes
On Sun, Jan 20, 2013 at 8:45 AM, Gustavo Lopes glopes@nebm.ist.utl.ptwrote:
On Sun, 20 Jan 2013 14:35:14 +0100, Sherif Ramadan <
theanomaly.is@gmail.com> wrote:What I'm saying is this kind of behavior needs far more serious reasoning
than the very naive assesment you're making above.I mean that with all due respect. Just wondering if there is another take
on this from anyone else?I think the current behavior is most appropriate one for
var_dump()
(and
array casts/get_object_vars()). It's the same behavior as if you had
manually defined getXXX() methods or used __get().
It's actually not the same behavior at all. __get can only work on
inaccessible properties. So I would not see NULL
there in the object and
then get a value in the instance property.
If you start marking function calls, you get new problems like handling
getters that throw exceptions or have side effects ("the code behaves
differently when add avar_dump()
?!").
I'm not suggesting the getters should be invoked from afar. I'm just
suggesting some additional means of informing the user of the existence of
that getter to distinguish it from the property in the output of var_dump.
So for example, in var_dump, you can get ["property":protected] => ... when
the property has a visibility outside of the current context. It might be
helpful to provide some similar behavior for accessors with null
initialized values, but have getters available to the caller?
Just a thought.
--
Gustavo Lopes
On Sun, 20 Jan 2013 14:52:36 +0100, Sherif Ramadan
theanomaly.is@gmail.com wrote:
I think the current behavior is most appropriate one for
var_dump()
(and
array casts/get_object_vars()). It's the same behavior as if you had
manually defined getXXX() methods or used __get().It's actually not the same behavior at all. __get can only work on
inaccessible properties. So I would not seeNULL
there in the object and
then get a value in the instance property.
OK, it's not 100% analogous. And I'm ready to concede that the differences
that do exist may be (arguably) sufficient to draw a principled
distinction, namely:
- getXXX() is clearly a method call and not a (direct) property read and
the XXX property may not even exist. - __get() only works on inaccessible properties, so there is no possible
confusion.
I still think you put too much emphasis on the __get() argument -- even
though there is no accessible property, there may be a protected/private
property; it it isn't the case, there's still usually some backing
storage, like a private array (shown in var_dump()
) and the backing value
may be different from what's returned.
In any case, assuming this feature is accepted, the current solution,
whether in isolation it's appropriate or not, must be evaluated in the
light of the alternatives. Here, I thought you were proposing calling the
getters.
If you start marking function calls, you get new problems like handling
getters that throw exceptions or have side effects ("the code behaves
differently when add avar_dump()
?!").I'm not suggesting the getters should be invoked from afar. I'm just
suggesting some additional means of informing the user of the existence
of that getter to distinguish it from the property in the output of
var_dump.So for example, in var_dump, you can get ["property":protected] => ...
when the property has a visibility outside of the current context. It
might be
helpful to provide some similar behavior for accessors with null
initialized values, but have getters available to the caller?
We could add some sort of marker to indicate the property is an accessor.
It would not be trivial under the current implementation as
get_properties() and get_debug_info() only return a HashTable*, so some
abstraction breaking would be required.
Another possibility would be the ability to mark some properties as not
backed by any storage, like the area in your example. But this would still
be insufficient to eliminate confusion in cases like this:
class A {
private $scale;
public $value {
get { return $this->value * $this->scale; }
set;
}
function __construct($scale) { $this->scale = (double)$scale; }
}
--
Gustavo Lopes
Now $surface shows us the following from var_dump....
object(surface)#1 (3) {
["area"]=>
NULL
["width"]=>
int(4)
["height"]=>
int(2)
}
Sounds like a reasonable approach to me...var_dump()
- Should not invoke the getters..
- Should indicate that they are property accessors (perhaps not even
show the underlying guarded property?)
Possibly:
object(surface)#1 (3) {
["area":accessor]=>
NULL
["width":accessor]=>
int(4)
["height":accessor]=>
int(2)
}
This could easily be changed if nobody had any further disagreements
with this?
Only issue I could see would be existing code that may parse var_dump()
might break if it wasn't written to accept something other that
private/protected...
--
-Clint
Now $surface shows us the following from var_dump....
object(surface)#1 (3) {
["area"]=>
NULL
["width"]=>
int(4)
["height"]=>
int(2)
}Sounds like a reasonable approach to me...
var_dump()
- Should not invoke the getters..
I can agree this since the side effects could be unpredictable (as in the
case of an accessor implementing an actual method rather than dealing with
with any values -- the performance loss is unjustified)
- Should indicate that they are property accessors (perhaps not even show
the underlying guarded property?)
That is a sensible approach to me.
Possibly:
object(surface)#1 (3) {
["area":accessor]=>
NULL
["width":accessor]=>
int(4)
["height":accessor]=>
int(2)
}This could easily be changed if nobody had any further disagreements with
this?Only issue I could see would be existing code that may parse
var_dump()
might break if it wasn't written to accept something other that
private/protected...
I think that one should rely on serialize or json_* serialization methods
or parsing data structures as opposed to var_dump output, since var_dump
doesn't always provide parseable output. Look at the output of DateTime
objects from var_dump or DateInterval objects, which have changed a bit
over 5.2 -> 5.3 and other objects like DOMDocument, which at one point did
not have any meaningful var_dump output at all.
--
-Clint
Am 17.01.2013 19:20, schrieb Clint Priest:
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to make
this happen for 5.5, voting and the specifications are here:https://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
Thanks,
-Clint
Thanks Clint and Niki for your work. Sorry to respond only now that the
voting process has already started. I usually don't follow/participate
on internals due to the noise and poisoned atmosphere (but that's a
different story). Also thanks Niki for taking the time to answer all my
questions I had about this beforehand.
IMO, the new getter/setter syntax adds very little benefit for the loads
of syntax it introduces. I understand that people are looking forward to
that new feature though, so I won't oppose it just because I have little
use for it.
My main issue with the implementation at hand is the weird way in which
we allow the visibility on the properties to be declared, e.g.
public $foo { get; protected set; }
The visibility keyword on the property is watering down the visibility
semantics. Either the property is public (then it can be set) or it is
not public. I would have much less of a problem with this, if declaring
visibility on a property could only be loosened but not tightened. That
would at least be consistent with how visibility works with inheritance.
It would be much better though to remove the visibility keyword from the
property altogether. It almost never tells the truth.
Removing the visibility keyword from the property altogether would also
remove the purported default visibility that is applied to the
accessors. I say "purported" because doing
public $foo { get; protected set; }
will also change the unset accessor to protected, which makes perfect
sense when you think about it but is completely unobvious when the
declaration claims the default visibility of all accessors to be public.
The default visibility of isset is that of get and the default
visibility of unset is that of set instead.
To add to the confusion, doing
public $foo { get; protected set; public unset; }
WILL work and change the visibility of unset back to what the property
claims it is. This should not be necessary when visibility on the
keyword defines the default visibility. I guess it's safe to say that
having the visibility on the property does very little to express
anything meaningful about the property or the default visibility of
all the accessors.
I briefly discussed possible solutions to this problem with Niki. Simply
removing the visibility looks odd
$foo { get; protected set; public unset; }
but might be the easiest approach. The above would follow the same rules
visibility follows for any other methods, e.g. omitting the visibility
on the accessor will make it public.
Both of us are not keen on introducing new keywords, though I find
property $foo { get; protected set; public unset; }
quite nice and it is also more obvious that this is not your regular
property. Niki suggested
var $foo { get; protected set; public unset; }
but it's keyword recycling and one could argue that in PHP4 a var was
always public. But then again, PHP4 didn't have the concept of
visibility at all, so why not?
If this could be changed, I'd be more willing to vote pro the proposal.
TL;DR: The visibility keyword on the property is almost never giving an
accurate information about the accessor visibility. Thus, it should be
removed or replaced for clarity's sake.
Regards,
Gordon
Am 17.01.2013 19:20, schrieb Clint Priest:
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to make
this happen for 5.5, voting and the specifications are here:https://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
Thanks,
-Clint
Thanks Clint and Niki for your work. Sorry to respond only now that
the voting process has already started. I usually don't
follow/participate on internals due to the noise and poisoned
atmosphere (but that's a different story). Also thanks Niki for taking
the time to answer all my questions I had about this beforehand.My main issue with the implementation at hand is the weird way in
which we allow the visibility on the properties to be declared, e.g.public $foo { get; protected set; }
The visibility keyword on the property is watering down the visibility
semantics. Either the property is public (then it can be set) or it is
not public. I would have much less of a problem with this, if
declaring visibility on a property could only be loosened but not
tightened. That would at least be consistent with how visibility works
with inheritance. It would be much better though to remove the
visibility keyword from the property altogether. It almost never tells
the truth.
This is basically an argument against asymmetrical visibility altogether
which is one of the most useful features of this proposal. I think
there are many use cases where an object wants to be able to emit a
message (value) but not receive one and being able to declare that fact
is important.
Removing the visibility keyword from the property altogether would
also remove the purported default visibility that is applied to the
accessors. I say "purported" because doingpublic $foo { get; protected set; }
will also change the unset accessor to protected, which makes perfect
sense when you think about it but is completely unobvious when the
declaration claims the default visibility of all accessors to be
public. The default visibility of isset is that of get and the default
visibility of unset is that of set instead.To add to the confusion, doing
public $foo { get; protected set; public unset; }
WILL work and change the visibility of unset back to what the property
claims it is. This should not be necessary when visibility on the
keyword defines the default visibility. I guess it's safe to say that
having the visibility on the property does very little to express
anything meaningful about the property or the default visibility of
all the accessors.
Perhaps this is just a documentation problem in that somewhere the
implication that public applies to all accessors when it should really
say that it applies to all declared accessors.
It is perfectly logical that when you cannot set a value, then you
cannot unset a value.
Defining what you have done above is declaring that you want to allow
people to get or unset the value, but not set it directly. This makes
sense in some usage scenarios. As an example, perhaps $foo represents
an internally generated id which is generated on the first call to the
getter, you don't want outsiders to specify the id, but you're okay with
having it unset so that a new one can be generated with the internal
generation mechanics on the next get request.
As an aside, your previous example can also be declared like this:
public $foo { get; protected set; unset; }
unset is explicitly declared and implicitly implemented and is public,
isset would be implicitly declared and implicitly implemented and follow
the visibility of the getter.
isset/unset only follow the get/set visibility if isset/unset are left
undeclared.
If this could be changed, I'd be more willing to vote pro the proposal.
TL;DR: The visibility keyword on the property is almost never giving
an accurate information about the accessor visibility. Thus, it should
be removed or replaced for clarity's sake.
I think I've made the case above that this isn't accurate, it always
affects declared accessors which do not have their own visibility specified.
Regards,
Gordon
--
-Clint
Am 22.01.2013 02:46, schrieb Clint Priest:
Am 17.01.2013 19:20, schrieb Clint Priest:
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to make
this happen for 5.5, voting and the specifications are here:https://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
Thanks,
-Clint
Thanks Clint and Niki for your work. Sorry to respond only now that
the voting process has already started. I usually don't
follow/participate on internals due to the noise and poisoned
atmosphere (but that's a different story). Also thanks Niki for taking
the time to answer all my questions I had about this beforehand.My main issue with the implementation at hand is the weird way in
which we allow the visibility on the properties to be declared, e.g.public $foo { get; protected set; }
The visibility keyword on the property is watering down the visibility
semantics. Either the property is public (then it can be set) or it is
not public. I would have much less of a problem with this, if
declaring visibility on a property could only be loosened but not
tightened. That would at least be consistent with how visibility works
with inheritance. It would be much better though to remove the
visibility keyword from the property altogether. It almost never tells
the truth.This is basically an argument against asymmetrical visibility altogether
which is one of the most useful features of this proposal. I think
there are many use cases where an object wants to be able to emit a
message (value) but not receive one and being able to declare that fact
is important.
I understand the purpose and utility of having different levels of
visibility. I am not argueing against that. I am argueing that putting
the visibility on the property does not give accurate information about
the property's visibility itself.
Contrived Example: doing just public $foo (Traditional Property) means I
can access the property from everywhere directly. But doing public $foo
{} (Guarded Property) means I cannot access the property at all. So we
went through full access to no access just by adding curly braces.
Likewise, private $foo { public get; public set; } is not private at all.
When the visiblity only applies to declared accessors we should just
declare in on the accessors only. That makes for better semantics. After
all, it's a guarded property, which already implies that it is hidden
behind accessors and thus non-public.
Removing the visibility keyword from the property altogether would
also remove the purported default visibility that is applied to the
accessors. I say "purported" because doingpublic $foo { get; protected set; }
will also change the unset accessor to protected, which makes perfect
sense when you think about it but is completely unobvious when the
declaration claims the default visibility of all accessors to be
public. The default visibility of isset is that of get and the default
visibility of unset is that of set instead.To add to the confusion, doing
public $foo { get; protected set; public unset; }
WILL work and change the visibility of unset back to what the property
claims it is. This should not be necessary when visibility on the
keyword defines the default visibility. I guess it's safe to say that
having the visibility on the property does very little to express
anything meaningful about the property or the default visibility of
all the accessors.Perhaps this is just a documentation problem in that somewhere the
implication that public applies to all accessors when it should really
say that it applies to all declared accessors.
Yes, that should be stretched. I think the final documentation should
also strongly emphasize that Guarded Properties is an entirely new
concept and not some extension to Traditional Properties or to Magic
Methods. We should prevent people from trying to map these new Guarded
Properties onto their existing mental models of how Traditional
Properties or Magic Methods work.
It is perfectly logical that when you cannot set a value, then you
cannot unset a value.Defining what you have done above is declaring that you want to allow
people to get or unset the value, but not set it directly. This makes
sense in some usage scenarios. As an example, perhaps $foo represents
an internally generated id which is generated on the first call to the
getter, you don't want outsiders to specify the id, but you're okay with
having it unset so that a new one can be generated with the internal
generation mechanics on the next get request.As an aside, your previous example can also be declared like this:
public $foo { get; protected set; unset; }unset is explicitly declared and implicitly implemented and is public,
isset would be implicitly declared and implicitly implemented and follow
the visibility of the getter.isset/unset only follow the get/set visibility if isset/unset are left
undeclared.
I agree that set and unset would usually have the same visibility, but I
do not agree that this should happen magically. Implicit means hidden
and hidden always leads to WTF moments. I understand the convenience of
having this happen automatically when this is how you'd use it most of
the time. But it's still a side-effect and your UseCase shows there are
exceptions where you would not want to have it that way. Maybe it should
just not happen silently?
If this could be changed, I'd be more willing to vote pro the proposal.
TL;DR: The visibility keyword on the property is almost never giving
an accurate information about the accessor visibility. Thus, it should
be removed or replaced for clarity's sake.I think I've made the case above that this isn't accurate, it always
affects declared accessors which do not have their own visibility
specified.
Thanks for your clarification. I'd still favor dropping the visibility
from the property though. Your summary of what the visibility does is
giving a clear description of the problem I see: the visibility is not
about the property at all (like it is with traditional properties) and
it only affects a subset of accessors (declared ones).
Regards,
Gordon
Hello Clint, Nikita and Stas.
To facilitate complete functionality with properties it is necessary to
provide accessor functions to act on isset() and unset() calls.
Note: isset & unset implementations are always provided with default
implementations unless the author explicitly defines their own.
a) With magic methods we can make the accessed property inaccessible (as
properties may appear/disappear at runtime) and so we need some magic there
(__isset/__unset as of 5.1).
A property (accessors) is defined at design-time and may not become
inaccessible so the default implementation for isset/unset should be
sufficient.
b) Result of (unset)$this->foo is always NULL.
If we provide a way to alter this "set(NULL)" behavior:
- it may fail before calling set(NULL)
- unset($this->foo); $this->foo !== (unset)$this->foo; // foo is not foo?
c) Logically isset/unset methods wrap up getter/setter at a higher level.
Maybe both methods are better suited for "operator
overloading/overriding RFC"
where i would again expect some magic too.
I wonder what the functionality would be as someone have to override
isset/unset accessors. Do you have some examples?
cryptocompress
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to
make this happen for 5.5, voting and the specifications are here:
For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?
There seems to be a lot of userland support for this proposal from
people who don't have voting rights.
--
-Clint
Clint Priest wrote:
There seems to be a lot of userland support for this proposal from people who
don't have voting rights.
And what about the userland people who don't want the additional complexity who
don't have voting rights?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
@Lester seems pretty much opt-in to me :)
Marco Pivetta
2013/1/22 Lester Caine lester@lsces.co.uk
Clint Priest wrote:
There seems to be a lot of userland support for this proposal from people
who
don't have voting rights.And what about the userland people who don't want the additional
complexity who don't have voting rights?
Don't use it. Regarding your other mails you are stuck with 5.2 anyway ;)
--
Lester Caine - G8HFLContact - http://lsces.co.uk/wiki/?page=**contacthttp://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.**ukhttp://rainbowdigitalmedia.co.uk--
Sebastian Krebs wrote:
Clint Priest wrote: There seems to be a lot of userland support for this proposal from people who don't have voting rights. And what about the userland people who don't want the additional complexity who don't have voting rights?
Don't use it. Regarding your other mails you are stuck with 5.2 anyway ;)
No I'm committed now to converting everything to PHP5.4 which given the amount
of work involved is going to take a couple of years, but does not give any
'improvement' to the resulting projects. Just as the latest changes will only
mean that we need to maintain PHP5.4 versions of libraries to prevent creep if
these developments into those libraries. 'Don't use it' is simply not an
acceptable argument when things added in one version become more integrated in
the next as has happened between php5.2->3->4 and now 5.5 will take this even
further. We NEED to nail down a clean base before changing the rules yet again ...
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
@Lester your explanation simply exposes the fact that your resources to
upgrade to newer technologies are insufficient. This doesn't mean that
newer technologies don't have to exist.
And no, it won't be possible to fix all bugs/flaws before getting a new
feature. We'd all be running in circles looking for perfection :)
Marco Pivetta
@Lester your explanation simply exposes the fact that your resources to
upgrade to newer technologies are insufficient. This doesn't mean that
newer technologies don't have to exist.And no, it won't be possible to fix all bugs/flaws before getting a new
feature. We'd all be running in circles looking for perfection :)
I can agree that some things need fixing though, perhaps Lester could
put together an RFC detailing the myriad of things he deems critical to
be fixed.
Marco Pivetta
--
-Clint
Clint Priest wrote:
And no, it won't be possible to fix all bugs/flaws before getting a new
feature. We'd all be running in circles looking for perfection :)
I can agree that some things need fixing though, perhaps Lester could put
together an RFC detailing the myriad of things he deems critical to be fixed.
Actually I don't have anything that I find 'critical'. I have perfectly working
systems which only break when ISP's switch off PHP5.2 and install 5.3. HIDING
warnings is simply the wrong way to handle BC ... We are forced to address these
warnings simply because they can become errors in later versions. HAVING
disabled the warnings and not addressed them is the critical bit that requires
that code is re-writen in every version update!
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?
I can say that this bit is particularly confusing:
public $foo {}
My understanding that this code will not emit any warnings when
interpreted, but the $foo property has no getter nor setter. You can
call isset which will return false but unset will emit a warning, yes?
I would think that the above snippet would create a property with all
public, default implementations. I see why it doesn't: it doesn't
permit you to declare only a getter and no setter.
This is just one more reason for me to vote no on this.
For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?
I can say that this bit is particularly confusing:public $foo {}
My understanding that this code will not emit any warnings when
interpreted, but the $foo property has no getter nor setter. You can
call isset which will return false but unset will emit a warning, yes?
This is correct except in the case where you are inheriting the
property. The above, on it's own class would be pointless.
I would think that the above snippet would create a property with all
public, default implementations.
If you are looking to create a public property with default
implementations, the following will suffice and has for a long time:
public $foo;
I see why it doesn't: it doesn't
permit you to declare only a getter and no setter.
Not sure what you mean here, you can declare a property with a getter
and no setter, such as:
public $foo { get; }
Which allows the property to be read, but not written, this is what the
asymmetrical access is about.
This is just one more reason for me to vote no on this.
--
-Clint
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to
make this happen for 5.5, voting and the specifications are here:For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?There seems to be a lot of userland support for this proposal from
people who don't have voting rights.
The simple explanation from me is that the ROI isn't there on this one.
It adds a lot of code complexity for very little return. Yes, it saves a
couple of lines of boilerplate code for a few people, but the cost is
high in terms of ongoing maintenance and potential issues for opcode
caches as well. If you look at the split in voting you will notice it is
pretty much split along the lines of the people who have to maintain
this code vs. the people who would like a shiny new feature.
-Rasmus
The simple explanation from me is that the ROI isn't there on this one.
It adds a lot of code complexity for very little return. Yes, it saves a
couple of lines of boilerplate code for a few people, but the cost is
high in terms of ongoing maintenance and potential issues for opcode
caches as well. If you look at the split in voting you will notice it is
pretty much split along the lines of the people who have to maintain
this code vs. the people who would like a shiny new feature.
I did a bit of testing with APC today and here is what I came up with:
https://gist.github.com/4597660 It adds the logic for copying the accessor
functions in my_copy_property_info*. This seemed to do the trick in my
testing, but I don't really know APC, so I can't judge whether it might
require further changes.
Thanks,
Nikita
For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?There seems to be a lot of userland support for this proposal from
people who don't have voting rights.
The simple explanation from me is that the ROI isn't there on this one.
It adds a lot of code complexity for very little return. Yes, it saves a
couple of lines of boilerplate code for a few people, but the cost is
high in terms of ongoing maintenance and potential issues for opcode
caches as well. If you look at the split in voting you will notice it is
pretty much split along the lines of the people who have to maintain
this code vs. the people who would like a shiny new feature.
Hey Rasmus,
With all due respect, I think you missed the post where Nikita Popov
analysed two of the biggest PHP based frameworks around, Symfony
(Standard) and Zend Framework where he found that there were 3,805 and
4,080 functions which served as a getter or a setter. I do not think
his analysis even included any usage of __get() or __set(). Here is his
original gist of his analysis:
https://gist.github.com/3884203
In terms of cost of maintenance, I was under the impression that since I
wrote it, I would be maintaining it which is why I applied for and you
approved a VCS account for me.
Lastly, I'm not sure if you have looked over the code, but a very large
amount of duplicate code has been cleaned up and centralized, both
property accessors and magic accessors use the same pre/post function
and logic. I can honestly say that adding the feature to the project
would improve the code base.
-Rasmus
--
-Clint
Am 22.01.2013 22:27, schrieb Clint Priest:
property accessors and magic accessors use the same pre/post function
and logic
So this is the reason for some "magic" behaviour of "property
accessors". Logically "property accessors" may be a subset of "magic
accessors" but not the other way around.
cryptocompress
In terms of cost of maintenance, I was under the impression that
since I wrote it, I would be maintaining it which is why I applied
for and you approved a VCS account for me.
The concern is historical and not personal. Frequently the long-term
contributors to PHP have been left to stabilize, integrate (e.g. with
APC), and then maintain code that was contributed.
I do note & appreciate your outstanding perseverance and leadership in
working through the RFC process.
Chris
--
christopher.jones@oracle.com http://twitter.com/ghrd
Newly updated, free PHP & Oracle book:
http://www.oracle.com/technetwork/topics/php/underground-php-oracle-manual-098250.html
In terms of cost of maintenance, I was under the impression that
since I wrote it, I would be maintaining it which is why I applied
for and you approved a VCS account for me.The concern is historical and not personal. Frequently the long-term
contributors to PHP have been left to stabilize, integrate (e.g. with
APC), and then maintain code that was contributed.I do note & appreciate your outstanding perseverance and leadership in
working through the RFC process.
Thanks, its been a long hard road for two years. I've wanted to contribute to PHP for years but there was a steep learning curve.
I'm personally honored to have been given a VCS account and would like to see the project flourish far beyond where it is presently, I fully intend to be a long term core contributor to this project.
I would also like to thank Nikita as he has done a lot with the project as well. Were it not for him, it would not be ready for release.
-Clint
Chris
--
christopher.jones@oracle.com http://twitter.com/ghrd
Newly updated, free PHP & Oracle book:
http://www.oracle.com/technetwork/topics/php/underground-php-oracle-manual-098250.html
Rasmus,
If you look at the split in voting you will notice it is
pretty much split along the lines of the people who have to maintain
this code vs. the people who would like a shiny new feature.
I pulled some numbers, and this isn't really the case.
Based off of commits from the past year (since 2012-01-01), here are the
raw numbers:
No: 1238
Yes: 895
But if you remove the top 2 committing voters (in general, not tied to a
list), the numbers even out quite significantly:
No: 514
Yes: 456
So I think that point falls somewhat flat...
I'm not saying this to raise issues or anything. I just want to point out
that the active maintainers are working on both sides of the fence. It's
not a "maintainers" vs "the others" vote split...
Anthony
Rasmus,
If you look at the split in voting you will notice it is pretty much split along the lines of the people who have to maintain this code vs. the people who would like a shiny new feature.
I pulled some numbers, and this isn't really the case.
Based off of commits from the past year (since 2012-01-01), here are the
Now do 5 or even 10+ years and commits to Zend and APC. We are talking
about a core language feature here, so commits to the code most affected
is what you should be looking at and when I talk about maintenance I
talk about code we are fixing 10 years from now. Commits in the past
year doesn't really reflect that very well.
-Rasmus
Rasmus,
Now do 5 or even 10+ years and commits to Zend and APC. We are talking
about a core language feature here, so commits to the code most affected
is what you should be looking at and when I talk about maintenance I
talk about code we are fixing 10 years from now. Commits in the past
year doesn't really reflect that very well.
True, but if someone hasn't been active with even a single commit in the
past year, I don't think they should be counted as an active maintainer.
I ran the numbers back to 2011. And they actually shift more towards Yes:
Total Commits:
No: 2011
Yes: 1877
All but top 2:
No: 996
Yes: 1011
And for 2010 (past 3 years):
No: 2455
Yes: 2395
All but top 2:
No: 1440
Yes: 1028
This is pointless though. The point is pretty well proven that within
reason the activity level of both groups is about even.
And when measuring a feature against "number of maintainers", I honestly
believe that only current active maintainers should count for that ranking.
It's not about "discrediting" prior contributors. Not in the least. I'm not
suggesting their votes should count less. I'm not suggesting that they
should lose voting rights or anything like that. But to count active
maintainers against a list which contains people who's last commit was in
2006 isn't fair.
Anthony
Rasmus,
Now do 5 or even 10+ years and commits to Zend and APC. We are talking
about a core language feature here, so commits to the code most affected
is what you should be looking at and when I talk about maintenance I
talk about code we are fixing 10 years from now. Commits in the past
year doesn't really reflect that very well.True, but if someone hasn't been active with even a single commit in the
past year, I don't think they should be counted as an active maintainer.I ran the numbers back to 2011. And they actually shift more towards Yes:
Total Commits:
No: 2011
Yes: 1877All but top 2:
No: 996
Yes: 1011And for 2010 (past 3 years):
No: 2455
Yes: 2395All but top 2:
No: 1440
Yes: 1028This is pointless though. The point is pretty well proven that within
reason the activity level of both groups is about even.And when measuring a feature against "number of maintainers", I honestly
believe that only current active maintainers should count for that ranking.
It's not about "discrediting" prior contributors. Not in the least. I'm not
suggesting their votes should count less. I'm not suggesting that they
should lose voting rights or anything like that. But to count active
maintainers against a list which contains people who's last commit was in
2006 isn't fair.Anthony
Why are you people so conservative in adding this feature? The vote
was going very well, but right now i really doubt this will make it in
PHP 5.5...
I would like to see this feature get in. So please, be a bit less conservative.
If there is so much conservatism then please make a userland poll
perhaps on php.net to ask the php devs (from userland) if they'd like
this feature.
hi Rasmus,
The simple explanation from me is that the ROI isn't there on this one.
It adds a lot of code complexity for very little return. Yes, it saves a
couple of lines of boilerplate code for a few people, but the cost is
high in terms of ongoing maintenance and potential issues for opcode
caches as well. If you look at the split in voting you will notice it is
pretty much split along the lines of the people who have to maintain
this code vs. the people who would like a shiny new feature.
With all respects, this has nothing to do with a shiny new feature.
The opcode cache support is actually a problem, I'd to agree. While we
(my team and I) do more maintenance around the opcode area with APC
(read: not the opcode related area per itself, not enough time sadly),
I cannot buy your argument. This feature has been requested since
years, by many major projects, same for other long awaited features
like annotations. We simply can't keep ignoring these requests, that's
what kill us.
About opcode cache complexity, I think apc per se is full of things we
should simplify or drop as features to make the code base much smaller
and much easier to test and valid, we have discussed that already and
we disagreed. But this is a topic I really want to bring on the table
before we even consider bringing it in core (see other requests about
that).
Cheers,
Pierre
@pierrejoye
About opcode cache complexity, I think apc per se is full of things we
should simplify or drop as features to make the code base much smaller
and much easier to test and valid, we have discussed that already and
we disagreed. But this is a topic I really want to bring on the table
before we even consider bringing it in core (see other requests about
that).
You completely changed the subject. I made no mention of opcode cache
complexity.
As far as I am concerned, the way to handle opcode cache simplification
is to attack it from both ends. A lot of the tricks that need to be done
in APC are because the compiler isn't really geared towards opcode
caching. To really simplify APC we need to simplify the compiler and
obviously make the corresponding changes to the executor. The things you
want to remove from APC are superficial things and are not the root
cause of the complexity. Things like the compiler spitting out
context-sensitive op_arrays (see the MAKE_NOP() tricks in
zend_compile.c) really make life difficult for an opcode cache.
But yes, I completely agree that this is a much more interesting problem
that I think we should be working on rather than more OO candy.
-Rasmus
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to
make this happen for 5.5, voting and the specifications are here:For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?There seems to be a lot of userland support for this proposal from
people who don't have voting rights.The simple explanation from me is that the ROI isn't there on this one.
It adds a lot of code complexity for very little return. Yes, it saves a
couple of lines of boilerplate code for a few people, but the cost is
high in terms of ongoing maintenance and potential issues for opcode
caches as well. If you look at the split in voting you will notice it is
pretty much split along the lines of the people who have to maintain
this code vs. the people who would like a shiny new feature.
I think it would be important to gather the reasons for the No Votes and
ways how to address this problems.
Some from the previous discusisons are:
- Neglected APC support
- adding complexity to PHP Core
- Reference Handling
- Visibility Rules
- Fear of testing in production
And come up with solutions to those (like cutting some features, or putting
the code into 5.6 to allow for more testing)
Since several contributors helped with the development and committed
themselves for quite some time already, then if there were a chance to
address all the concerns then this feature could still move forward (maybe
at a later point)?
-Rasmus
On Wed, Jan 23, 2013 at 12:11 PM, Benjamin Eberlei kontakt@beberlei.dewrote:
On Tue, Jan 22, 2013 at 6:20 PM, Rasmus Lerdorf rasmus@lerdorf.com
wrote:I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to
make this happen for 5.5, voting and the specifications are here:For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?There seems to be a lot of userland support for this proposal from
people who don't have voting rights.The simple explanation from me is that the ROI isn't there on this one.
It adds a lot of code complexity for very little return. Yes, it saves a
couple of lines of boilerplate code for a few people, but the cost is
high in terms of ongoing maintenance and potential issues for opcode
caches as well. If you look at the split in voting you will notice it is
pretty much split along the lines of the people who have to maintain
this code vs. the people who would like a shiny new feature.I think it would be important to gather the reasons for the No Votes and
ways how to address this problems.
Some from the previous discusisons are:
- Neglected APC support
- adding complexity to PHP Core
- Reference Handling
- Visibility Rules
- Fear of testing in production
And come up with solutions to those (like cutting some features, or putting
the code into 5.6 to allow for more testing)Since several contributors helped with the development and committed
themselves for quite some time already, then if there were a chance to
address all the concerns then this feature could still move forward (maybe
at a later point)?
Hi,
for the record I'm one of the people who thinks that this is a good idea
and the implementation improved a bunch from the previous
versions/proposals, but I think that there were too many changes which
could have introduced new bugs (both in design and implementation).
Accepting this feature just before the feature freeze would either prolong
the 5.5 release or we could end up in the same spot as with 5.4, where
major problems with the new features were discovered after the release plus
some of the must-have extensions wasn't ready to work with the new version.
I don't wanna hijack the discussion, but I think there are a couple of
concerns raised here would worth a separate discussion and possibly changes
in our rfc and release process.
--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to
make this happen for 5.5, voting and the specifications are here:For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?There seems to be a lot of userland support for this proposal from
people who don't have voting rights.The simple explanation from me is that the ROI isn't there on this one.
It adds a lot of code complexity for very little return. Yes, it saves a
couple of lines of boilerplate code for a few people, but the cost is
high in terms of ongoing maintenance and potential issues for opcode
caches as well. If you look at the split in voting you will notice it is
pretty much split along the lines of the people who have to maintain
this code vs. the people who would like a shiny new feature.
Rasmus, could you maybe point out more specifically what issues you see
with the implementation (this also applies to all the other people who
voted "no" due to maintenance concerns)? It doesn't look like the RFC will
make it this time around, but it would be nice to know what issues there
are for next time. (If someone wants to give inline-comments on the
implementation, here's the PR: https://github.com/php/php-src/pull/263)
Thanks,
Nikita
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to make
this happen for 5.5, voting and the specifications are here:https://wiki.php.net/rfc/**propertygetsetsyntax-v1.2#**votinghttps://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
For those that have voted against this proposal, are there any
clarifications that can be made or questions answered?There seems to be a lot of userland support for this proposal from people
who don't have voting rights.
I just wanted to add my two cents here on top of what has already been
mentioned about added complexity with minimal benefit (which I mostly agree
with).
For me, the proposal sounded intriguing from the start, but I noticed a lot
of discussion around this RFC early on. This led me to believe that it was
going to be a popular feature, which I believe it is. Unfortunately, the
discussion seemed to grow so quickly that I could not find the time to
follow it all. The discussion also seemed to be torn into a hundred
different directions at once. Mostly just the regular internals noise that
I'm used to, but with a few moments of confusion on implementation.
I didn't really get it when it was being discussed. I was actually kind of
confused about what exactly was being proposed and I saw lots of changes in
the RFC and then the newly added RFC that was supposed to be a compliment
to this one. After seeing the patch and getting a chance to test it out,
though, I realized that the feature seems really confusing in terms of
behavior. It felt like a lot was being added, but in reality it was just a
lot of code complexity, not a lot of functionality.
Don't get me wrong, I liked it, but I also disliked the fact that it
introduces language changes that aren't easy to grasp or document. To me
this means we've borderline changed the behavior of a property (which most
PHP users currently understand to be a variable) into potential methods.
This is basically saying we can now completely change the behavior of a
property from a storage unit to a functional unit. That's a bit of a scary
thought to me, because it makes me question everything I know about
properties in PHP.
I think you did a wonderful job on this RFC and the code, as well as
everyone involved. Clearly, there is a demand for this. However, I'm not
sure I would feel comfortable seeing the after effects of this feature in
PHP. For what it's worth, this was not an easy vote for me. I debated it
for several days before I made my decision and I tried to be as objective
as possible. I just couldn't bring myself to vote it in for 5.5.
--
-Clint
Sherif,
Don't get me wrong, I liked it, but I also disliked the fact that it
introduces language changes that aren't easy to grasp or document. To me
this means we've borderline changed the behavior of a property (which most
PHP users currently understand to be a variable) into potential methods.
This is basically saying we can now completely change the behavior of a
property from a storage unit to a functional unit. That's a bit of a scary
thought to me, because it makes me question everything I know about
properties in PHP.
Except that everything that's proposed here is possible today with __get,
__set, __isset and __unset. So already today you can't assume that a
property is a "variable". In fact, you could build something like this
using __get, etc extremely dirty:
class Foo {
public function __get($name) {
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->method();
}
return $this->$name; // public properties
}
public function __set($name, $value) {
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->method($value);
}
return $this->$name = $value; // public properties
}
}
The difference in functionality that this provides is the ability to
custom-scope getters and setters. And it's a LOT cleaner...
Anthony
On Wed, Jan 23, 2013 at 9:03 AM, Anthony Ferrara ircmaxell@gmail.comwrote:
Sherif,
Don't get me wrong, I liked it, but I also disliked the fact that it
introduces language changes that aren't easy to grasp or document. To me
this means we've borderline changed the behavior of a property (which most
PHP users currently understand to be a variable) into potential methods.
This is basically saying we can now completely change the behavior of a
property from a storage unit to a functional unit. That's a bit of a scary
thought to me, because it makes me question everything I know about
properties in PHP.Except that everything that's proposed here is possible today with __get,
__set, __isset and __unset. So already today you can't assume that a
property is a "variable". In fact, you could build something like this
using __get, etc extremely dirty:class Foo {
public function __get($name) {
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->method();
}
return $this->$name; // public properties
}
public function __set($name, $value) {
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->method($value);
}
return $this->$name = $value; // public properties
}
}The difference in functionality that this provides is the ability to
custom-scope getters and setters. And it's a LOT cleaner...
This is not true. Magic getters and setters make a distinction that
accessors do not. That distinction is that they can only work on
inaccessible properties. Accessors offer no such distinction. They are
explicitly defined and as such their properties are not magical even though
they provide somewhat magical characteristics.
When you use var_dump to debug the property of an object, or the object
itself, for example, you would expect that whatever value is returned for
that property is either stored in memory somewhere or is the result of a
magic getter. Now, if it is the result of a magic getter there is no
confusion between whether this is an actual property or magic getter,
because a look at var_dump of that object tells us the whole story.
With accessors you now make the case that the property can be the result of
any computation and as such var_dump only reveals the underlying storage
unit and has no awareness of any computation.
class foo {
public $bar {
get() { return 'baz'; }
}
}
var_dump(json_encode(new foo),new foo, (new foo)->bar);
// gives us
string(12) "{"bar":null}"
object(foo)#1 (1) {
["bar"]=>
NULL
}
string(3) "baz"
There's a subtle difference here that's not obvious at first. The
difference is that we have no way of knowing whether "bar" is the result of
an accessor or a an actual property without closely examining the code.
There's no easy way to debug who went wrong when this causes a problem. If
the property is now acting as a method we have to start treating it like a
method in order to debug it. That could mean backtraces, exception
handling, and a variety of other things that I really find weird to have to
do with an a property.
Now, let's examine the alternative. Using magic methods...
class foo {
private $bar;
public function __get($name) {
if ($name == 'bar') {
return 'baz';
}
}
}
var_dump(json_encode(new foo),new foo, (new foo)->bar);
string(2) "{}"
object(foo)#1 (1) {
["bar":"foo":private]=>
NULL
}
string(3) "baz"
At least here we know that "bar" is undoubtedly a private property so
whatever we got from (new foo)->bar must be the result of a magic getter.
There's only one place to look for that (in the magic method). With an
accessor I could easily create a situation where a bug manifests itself
anywhere in the code and not necessarily in the accessor itself that
accessor effectively becomes a method that does computation rather than
handling mere storage and retrieval.
I really really feel this is a way to give users lots of rope to hang
themselves with and at the cost of added complexity. I'm just not sure I
buy it. Sorry.
Sherif,
Arbiter of null.
Anthony
Except that everything that's proposed here is possible today with __get,
__set, __isset and __unset. So already today you can't assume that a
property is a "variable". In fact, you could build something like this
using __get, etc extremely dirty:class Foo {
public function __get($name) {
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->method();
}
return $this->$name; // public properties
}
public function __set($name, $value) {
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->method($value);
}
return $this->$name = $value; // public properties
}
}The difference in functionality that this provides is the ability to
custom-scope getters and setters. And it's a LOT cleaner...
Just a reminder on that cleanliness... Symfony: 3,805 functions that are
getters or setters, Zend Framework: 4,080 functions that are getters or
setters, not even counting what is being done with __get().
This is not true. Magic getters and setters make a distinction that
accessors do not. That distinction is that they can only work on
inaccessible properties. Accessors offer no such distinction. They are
explicitly defined and as such their properties are not magical even though
they provide somewhat magical characteristics.When you use var_dump to debug the property of an object, or the object
itself, for example, you would expect that whatever value is returned for
that property is either stored in memory somewhere or is the result of a
magic getter. Now, if it is the result of a magic getter there is no
confusion between whether this is an actual property or magic getter,
because a look at var_dump of that object tells us the whole story.
Actually you could say that last sentence is precisely opposite of the
truth in that avar_dump()
will never expose properties that are
available via a magic __get() therefore avar_dump()
already mis-leads
the developer because there can be properties that can be retrieved
which are not shown by a simplevar_dump()
.
With accessors you now make the case that the property can be the result of
any computation and as such var_dump only reveals the underlying storage
unit and has no awareness of any computation.class foo {
public $bar {
get() { return 'baz'; }
}
}var_dump(json_encode(new foo),new foo, (new foo)->bar);
// gives us
string(12) "{"bar":null}"
object(foo)#1 (1) {
["bar"]=>
NULL
}
string(3) "baz"There's a subtle difference here that's not obvious at first. The
difference is that we have no way of knowing whether "bar" is the result of
an accessor or a an actual property without closely examining the code.
There's no easy way to debug who went wrong when this causes a problem. If
the property is now acting as a method we have to start treating it like a
method in order to debug it. That could mean backtraces, exception
handling, and a variety of other things that I really find weird to have to
do with an a property.Now, let's examine the alternative. Using magic methods...
class foo {
private $bar;
public function __get($name) {
if ($name == 'bar') {
return 'baz';
}
}
}var_dump(json_encode(new foo),new foo, (new foo)->bar);
string(2) "{}"
object(foo)#1 (1) {
["bar":"foo":private]=>
NULL
}
string(3) "baz"
There had been very recent talk of having an accessor output something
to the effect of:
object(foo)#1 (1) {
["bar":"foo":accessor]=>
NULL
}
I would actually favor the idea that nothing can see the property value
except the accessor and this would mean that a var_dump()
would call the
accessor. By having var_dump()
read the value of the underlying
property directly it really violates the entire idea of an accessor.
Every other language that implements accessors (and it's most modern
languages) there is no actual underlying property. This is the way 1.1
originally proposed it, but that was not what people wanted, they did
not want to have to declare a backing property of their own and so it
was changed.
The result of the current RFC is a result of the endless discussion that
was had on this topic. It's really not appropriate to vote against
something if you did not make your voice heard when discussions of some
aspect were happening.
At least here we know that "bar" is undoubtedly a private property so
whatever we got from (new foo)->bar must be the result of a magic getter.
There's only one place to look for that (in the magic method). With an
accessor I could easily create a situation where a bug manifests itself
anywhere in the code and not necessarily in the accessor itself that
accessor effectively becomes a method that does computation rather than
handling mere storage and retrieval.I really really feel this is a way to give users lots of rope to hang
themselves with and at the cost of added complexity. I'm just not sure I
buy it. Sorry.
I'm not sure what kind of rope you're talking about here, if an error
occurs in an accessor it's stack trace clearly indicates where it is
occurring, even if it happened somewhere outside of an accessor but
through it (like the getter calls other code where the error occurs).
Unless you're talking about someone who doesn't know how to use a
debugger or use the basic functionality such as stack traces, there is
no lack of clarity in what has gone wrong.
--
-Clint
Actually you could say that last sentence is precisely opposite of the
truth in that avar_dump()
will never expose properties that are
available via a magic __get() therefore avar_dump()
already mis-leads the
developer because there can be properties that can be retrieved which are
not shown by a simplevar_dump()
.
They're not shown because they don't exist. Thus no confusion about whether
this is a property or not. If it's a property we can see it in
var_dump($obj). If it's magic you can only see it in
var_dump($obj->property). With accessors you see both, but you are seeing
(potentially) two different values. For me, that's the "misleading" part.
I agree that there are benefits here, but I can't agree that the benefits
outweigh the draw backs for me, which are all the added complexity. Like
Anthony said it's pretty much just coming down to custom scoping
getters/setters at the end of the day.
The result of the current RFC is a result of the endless discussion that
was had on this topic. It's really not appropriate to vote against
something if you did not make your voice heard when discussions of some
aspect were happening.
I made my voice heard on the aspect that I was concerned with. My decision
was based on reading the entire RFC, downloading the patch, compiling the
code, testing it myself, and weighing the pros and cons of the proposal. I
believe I was pretty fair, but I am just one person of many that voted.
They're not shown because they don't exist. Thus no confusion about whether
this is a property or not. If it's a property we can see it in
var_dump($obj). If it's magic you can only see it in
var_dump($obj->property). With accessors you see both, but you are seeing
(potentially) two different values. For me, that's the "misleading" part.I agree that there are benefits here, but I can't agree that the benefits
outweigh the draw backs for me, which are all the added complexity. Like
Anthony said it's pretty much just coming down to custom scoping
getters/setters at the end of the day.
Actually, having the properties shown even if virtual allows us to access
them in a reflection-ish manner without doing dangerous assumptions like
"does the setter/getter exist"?
The fact that the property is virtual is very useful, even though in
dumping it doesn't show any value. I don't see any radical difference in
debugging or ease of use in general.
Actually, doing the same things with magic getters/setters would probably
imply having to think more about the trace we want to follow when analyzing
our bugs. It is just a matter of being aware of new setter/getters (that
are anyway in our trace).
Marco Pivetta
Actually, having the properties shown even if virtual allows us to
access them in a reflection-ish manner without doing dangerous
assumptions like "does the setter/getter exist"?The fact that the property is virtual is very useful, even though in
dumping it doesn't show any value. I don't see any radical difference
in debugging or ease of use in general.
Actually, doing the same things with magic getters/setters would
probably imply having to think more about the trace we want to follow
when analyzing our bugs. It is just a matter of being aware of new
setter/getters (that are anyway in our trace).
If you stop and think about it, the current accessors are identical in
functionality to defining a private variable for every __get().
So these two sets of code work and act identically:
class Foo {
private $bar;
public __get($name) {
if($name == 'bar')
return $this->bar;
}
public __set($name, $value) {
if($name == 'bar')
$this->bar = $value;
}
public __isset($name) {
if($name == 'bar')
return isset($this->bar);
}
public __unset($name) {
if($name == 'bar')
unset($this->bar);
}
}
-- OR --
class Foo {
public $bar { get; set; }
}
Except in the first case, you have to look at four sections of code to
find "everything that applies to bar" and if you add 5 or 6 more dynamic
properties, you have 4 huge switch statements, again with all the code
split up everywhere.
With Property Accessors, it's all right there. This of course is a very
simple case, if you actually USE the dynamic nature of __get(), etc then
you've got a ton more code.
--
-Clint
Actually, having the properties shown even if virtual allows us to access
them in a reflection-ish manner without doing dangerous assumptions like
"does the setter/getter exist"?The fact that the property is virtual is very useful, even though in
dumping it doesn't show any value. I don't see any radical difference in
debugging or ease of use in general.
Actually, doing the same things with magic getters/setters would probably
imply having to think more about the trace we want to follow when analyzing
our bugs. It is just a matter of being aware of new setter/getters (that are
anyway in our trace).If you stop and think about it, the current accessors are identical in
functionality to defining a private variable for every __get().So these two sets of code work and act identically:
class Foo {
private $bar;
public __get($name) {
if($name == 'bar')
return $this->bar;
}
public __set($name, $value) {
if($name == 'bar')
$this->bar = $value;
}
public __isset($name) {
if($name == 'bar')
return isset($this->bar);
}
public __unset($name) {
if($name == 'bar')
unset($this->bar);
}
}-- OR --
class Foo {
public $bar { get; set; }
}Except in the first case, you have to look at four sections of code to find
"everything that applies to bar" and if you add 5 or 6 more dynamic
properties, you have 4 huge switch statements, again with all the code split
up everywhere.With Property Accessors, it's all right there. This of course is a very
simple case, if you actually USE the dynamic nature of __get(), etc then
you've got a ton more code.
Let's not forget that all __get and __set would have save visibility
unless you manually controlled that which means more coding. Yay!
I'm happy to say that Property Accessors is ready for a vote for
inclusion in 5.5 release.Nikita and I (as well as Stas a bit) have all been working hard to
make this happen for 5.5, voting and the specifications are here:https://wiki.php.net/rfc/propertygetsetsyntax-v1.2#voting
Thanks,
-Clint
Voting has been closed, proposal declined. 34 to 22.
--
-Clint