Access the instance of the main class from an anonymous one in PHP 7

3

I'm trying to access the instance of the class where it contains an anonymous one as we do in Java, for example:

JAVA

class MyClass 
{
    private String prop = "test";

    public void test()
    {
        new Runnable() {

            public void run() 
            {
                // Consigo acessar prop a partir daqui
                System.out.println(MyClass.this.prop);
            }

        }.run();
    }
}

PHP 7

<?php

class MyClass
{
    private $prop = "test";

    public function test()
    {
        $class = new class{

            public function run() 
            {
                // ???? como acessar MyClass::$prop daqui de dentro?
            }

        };
    }
}

How do I access the MyClass instance from within the anonymous?

    
asked by anonymous 11.07.2017 / 18:35

2 answers

2

According to official documentation :

  

Nesting an anonymous class inside another class does not give access to any private or protected method, or properties of the outer class. To use the protected methods and properties of the outer class, the anonymous class can extend the outer class. To use the private properties of the outer class in the anonymous class, they must be passed through the constructor.

That is, the constructor of the anonymous class must be defined by passing the private values to be used. For example:

<?php

class MyClass
{
    private $prop = "teste";

    public function test()
    {
        $class = new class($this->prop) {

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

            public function run() 
            {
                echo $this->prop, PHP_EOL;
            }

        };

        $class->run();
    }
}

$obj = new MyClass();
$obj->test();
  

See working at Ideone

Notice that it is the desired value that must be passed through the constructor. Passing the $this object as a parameter and attempting to access the private attribute of it within the anonymous class results in a fatal error. See below:

<?php

class MyClass
{
    private $prop = "teste";

    public function test()
    {
        $class = new class($this) {

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

            public function run() 
            {
                echo $this->obj->prop, PHP_EOL;
            }

        };

        $class->run();
    }
}

$obj = new MyClass();
$obj->test();
  

See working at Ideone .

That is, even passing the object itself and using it to access the private attribute within the class itself results in an error. This is because PHP interprets the context of the anonymous class as something isolated from the parent class, not assigning the access permissions to the object's private attributes and methods.

Changeable or unchanging attribute

If the attribute passed to the anonymous class is immutable, it can not change the original value of the attribute in the parent class except when the value is passed by reference. By default, immutable attributes are passed by value in PHP. To verify, simply try to change the value of $prop within the anonymous class and then check the value of this attribute in the parent class:

<?php

class MyClass
{
    public $prop = "teste";

    public function test()
    {
        $class = new class($this->prop) {

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

            public function run() 
            {
                $this->prop = "teste na classe anônima";

                echo $this->prop, PHP_EOL;
            }

        };

        $class->run();
    }
}

$obj = new MyClass();
$obj->test();

echo $obj->prop, PHP_EOL;
  

See working at Ideone .

Output output is:

teste na classe anônima
teste

That is, because the attribute is a string and is an immutable type, the value was passed to the anonymous class as value and was not changed in the parent class. Basically the object was copied when passed to the anonymous class and it does not have the reference to the original object.

Now, if the value is of a changeable type, an object of class Foo, for example, the behavior is different:

<?php

class Foo {
    public function __construct($prop) {
        $this->prop = $prop;
    }

    public function __toString() {
        return $this->prop;
    }
}

class MyClass
{
    public function __construct()
    {
        $this->prop = new Foo("test");
    }

    public function test()
    {
        $class = new class($this->prop) {

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

            public function run() 
            {
                $this->prop->prop = "Teste na classe anônima";
                echo $this->prop, PHP_EOL;
            }

        };

        $class->run();
    }
}

$obj = new MyClass();
$obj->test();

echo $obj->prop, PHP_EOL;
  

See working at Ideone .

The result is:

Teste na classe anônima
Teste na classe anônima

That is, the original value of the attribute in the parent class has also changed. Since the object passed to the anonymous class is changeable, the object is passed by reference , so any changes made within the anonymous class will also affect the object in the parent class because they are the same object.

    
11.07.2017 / 18:56
1

I think you can not do this reference, but you can pass a parameter to the constructor of the anonymous class, for example:

class MyClass
{
    private $prop = "test";

    public function test()
    {
        $class = new class($this->prop){

            protected $prop;
            public function __construct($prop){
                $this->prop = $prop;
            }
            public function run() 
            {
                echo $this->prop;
            }

        };

        $class->run(); //test
    }
}
    
11.07.2017 / 18:50