Bug #78455 [Com]: Access violation of private trait members
| From: | developmenthero at gmail dot com | Date: | Sun, 25 Aug 2019 00:46:36 +0000 |
| Subject: | Bug #78455 [Com]: Access violation of private trait members | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-222401@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=78455&edit=1
ID: 78455
Comment by: developmenthero at gmail dot com
Reported by: developmenthero at gmail dot com
Summary: Access violation of private trait members
Status: Not a bug
Type: Bug
Package: Scripting Engine problem
Operating System: Windows 10
PHP Version: 7.3.8
Block user comment: N
Private report: N
New Comment:
Thank you @requenix for bringing some light in the darkness.
I guess i've been tricked a litte by the german tranlastion of the trait documentation wich
only talks about "methods" whereas the english version speaks of "inherited
members" and mentions an "insertion" of them.
If this is defined behaviour, i guess it may worth to mention it in the documention and this ticket
can be closed.
Sorry for creating an useless Bugticket. ;-)
Previous Comments:
------------------------------------------------------------------------
[2019-08-25 00:17:18] requinix@php.net
Oh, just noticed it's __get in this new stuff, not __set. So correction:
> var_dump($B->value);
Would not be valid because B::$value is private so you cannot access it outside the class, but you
have __get() so it will intercept the property access and return the string that it does.
------------------------------------------------------------------------
[2019-08-25 00:14:26] requinix@php.net
> Shouldn't it be possible to access private fields of traits from a different scope than
> the trait itself?
First thing to understand is that the trait isn't some special form of class. Nor is it a set
of rules like an interface. It's a bunch of things that PHP will copy and paste into whatever
class wants to use it. No really. It's sometimes described as "language-assisted copy and
paste" because that's an accurate description of how it works.
A's "private $value = 1;" is copied and pasted into B, and B ends up with its very
own "private $value = 1;" Same for getValue() and __set().
So
> var_dump($B->getValue());
Valid. You're calling B::getValue() which tries to access B::$value which is perfectly fine.
> var_dump($B->value);
Not valid. B::$value is private so you cannot access it outside the class.
------------------------------------------------------------------------
[2019-08-25 00:03:15] developmenthero at gmail dot com
Interestingly i just realized that __get won't be called from inside child-classes, since i
upgraded from 7.2.4 to 7.3.7(now /.3.8).
But clarify: Shouldn't it be possible to access private fields of traits from a different scope
than the trait itself?
Pardon me, i stripped down the snippet:
<?php
declare(strict_types=1);
trait A {
private $value = 1;
public function getValue() {
return $this->value;
}
public function __get($name) {
return "hello world";
}
}
class B {
use A;
public function getValue() {
return $this->value;
}
}
$B = new B();
var_dump($B->getValue());
var_dump($B->value);
------------------------------------------------------------------------
[2019-08-24 23:20:25] requinix@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves.
A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external
resources such as databases, etc. If the script requires a
database to demonstrate the issue, please make sure it creates
all necessary tables, stored procedures etc.
Please avoid embedding huge scripts into the report.
> Prior to v7.3, "A::__set()" would be triggered here.
Nope. https://3v4l.org/5XSGH
------------------------------------------------------------------------
[2019-08-24 23:17:14] developmenthero at gmail dot com
Description:
------------
Private members of traits are (at least) since v7.3.7 accessible from within "using"
classes now.
Unfortunately this broke triggering __get() and __set() methods within traits.
Test script:
---------------
trait A {
private $value = 1;
public function getValue() {
return $this->value;
}
public function __set($name, $val) {
var_dump($name, $val);
}
}
class B {
use A;
public function setValue($value) {
// Prior to v7.3, "A::__set()" would be triggered here.
$this->value = $value;
}
}
$B = new B();
var_dump($B->getValue());
$B->setValue(12);
var_dump($B->getValue());
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=78455&edit=1