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 - как следствие, вы обречены на зацикливание.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
YCLIENTS Москва
от 200 000 до 350 000 ₽
Ведисофт Екатеринбург
от 25 000 ₽
ИТЦ Аусферр Магнитогорск
от 100 000 до 160 000 ₽