简体   繁体   中英

Access outer variables from anonymous class

I was trying an alternative way of doing this:

public function index()
{
    $faker = Faker\Factory::create('fr_FR');

    $ideas = [];

    for ($i = 1; $i <= rand(10, 50); $i++) {
        $idea = new \stdClass;
        $idea->id = $i;
        $idea->author = $faker->name;
        //...

        $ideas[] = $idea;
    }
}

Instead of creating object and assigning attributes in the loop, I would like to create the object from a class, and populate $ideas[] with the array_pad() function:

public function index()
{
    $faker = Faker\Factory::create('fr_FR');

    $ideas = [];

    $idea = new class {
        private $id;
        private $author;

        function __construct() {
            $this->id = count($ideas) + 1;
            $this->author = $faker->name;
        }
    };

    array_pad($ideas, rand(10, 50), new $idea);
        
}

So I need to access $faker and $ideas from the anonymous class. I tried to pass them to the class like this:

$idea = new class($ideas, $faker) {

    private $id;
    private $author;

    private $ideas
    private $faker

    function __construct($ideas, $faker) {
        $this->id = count($ideas) + 1;
        $this->author = $faker->name;
    }
};

But I get a

Too few arguments to function class@anonymous::__construct(), 0 passed

Sad news: you cant use array_pad for this.

Here the fixes you need to apply to get rid of the error:

// array_pad($ideas, rand(10, 50), new $idea);
array_pad($ideas, rand(10, 50), $idea); // remove new

Since you did the new already here:

$idea = new class($ideas, $faker) {

Even though this will fill $ideas . It will store the same reference to your $idea over and over. Which means if you alter one element this change will be on all elements (i guess this is not desired).

In order to get this working you will have to use a loop, which creates a new $idea for every entry:

$faker = Faker\Factory::create('fr_FR');

$ideas = [];

for ($i = rand(10, 50); $i > 0; $i--) {
    $ideas[] = new class($ideas, $faker) {
        private $id;
        private $author;

        function __construct($ideas, $faker) {
            $this->id = count($ideas) + 1;
            $this->author = $faker->name;
        }
    };
}

Working example .

Additional information

Instead of doing this

for ($i = 1; $i <= rand(10, 50); $i++)

better do this

for ($i = rand(10, 50); $i > 0; $i--)

The reason is the comparison is getting called on every loop, so you generating a new random number on every loop. Example

This is problematic because you tend to get way more low numbers like this. For example to get 50 loops the random has to return > $i every time - which is very unlikely.

One more thing: array_pad returns the filled array, so you'd have to write

$ideas = array_pad(...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM