Delgus
@Delgus

Почему Fatal error: Allowed memory size of???

Решил немного поглубже изучить PHP. И натолкнулся на следующий баг. Что это? Утечка памяти? почему???

Вот пример в песочнице - sandbox.onlinephpfunctions.com/code/947ee84b800d52...
Вот сам код.
<?php

class BaseClass
{
    public function __construct(array $arguments = [])
    {
        foreach ($arguments as $property => $argument) {
            $this->{$property} = $argument;
        }
    }

    public function __call($method, $arguments)
    {
        if (isset($this->{$method}) /*&& is_callable($this->{$method})*/) {
            return $this->{$method}($arguments);
        } else {
            throw new Exception("Fatal error: Call to undefined method BaseClass::{$method}()");
        }
    }
}


class App extends BaseClass
{
    function hello()
    {
        echo "hello world";
    }
}

$app1 = new App();
$app1->hello();

$app2 = new BaseClass([
    'hello' => function () {
        echo "hello world";
    }
]);
$app2->hello();


Вывод:
hello world
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in [...][...] on line 15
  • Вопрос задан
  • 139 просмотров
Решения вопроса 1
Decadal
@Decadal
public function __call($method, $arguments)

эта конструкция вызывается только тогда, когда $method не был явно определен у класса.

class App extends BaseClass
{
    function hello()
    {
        echo "hello world";
    }
}


здесь вы явно определили функцию. Можете проверить это, добавив здесь:

public function __call($method, $arguments)
    {
        echo "------";  // kak-to tak
        if (isset($this->{$method}) /*&& is_callable($this->{$method})*/) {
            return $this->{$method}($arguments);
        } else {
            throw new Exception("Fatal error: Call to undefined method BaseClass::{$method}()");
        }
    }


какой-либо вывод. Вы заметите что он не выполнится вообще.

В случае же с замыканием вы вызываете функцию $app2->hello(); но её не находит явно. Потом вы снова вызываете функцию уже в теле метода __call: $this->{$method}($arguments); и её снова не находит явно. Таким образом создается бесконечный вызов __call.

А все потому что property и method - разные вещи. И пусть у класса есть свойство с именем hello, но у него нет метода с именем hello - как следствие, вы обречены на зацикливание.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы