php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78455 Access violation of private trait members
Submitted: 2019-08-24 23:17 UTC Modified: 2019-08-25 00:17 UTC
From: developmenthero at gmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 7.3.8 OS: Windows 10
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: developmenthero at gmail dot com
New email:
PHP Version: OS:

 

 [2019-08-24 23:17 UTC] 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());


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-08-24 23:20 UTC] requinix@php.net
-Status: Open +Status: Feedback -Package: PHP Language Specification +Package: Scripting Engine problem
 [2019-08-24 23:20 UTC] 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-25 00:03 UTC] 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-25 00:14 UTC] requinix@php.net
-Status: Feedback +Status: Not a bug
 [2019-08-25 00:14 UTC] 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:17 UTC] 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:46 UTC] developmenthero at gmail dot com
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. ;-)
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Wed Apr 21 21:01:24 2021 UTC