Массив в объекте, переданном по ссылке, пуст, хотя он был заполнен позже

1

В ходе написания небольшой рамочной основы для веб-приложения я столкнулся с некоторыми трудностями в том, чтобы люди общались друг с другом.

Окружающая среда

У меня есть абстрактный класс LizardModule, который должен быть расширен всеми отдельными модулями веб-приложения. Этот класс имеет final protected function registerController(...), которая создает новый объект типа LizardController. Это, как кажется, основано на идее MVC. С final protected function registerFunction(...) модули могут регистрировать функции для каждого контроллера. Они сохраняются с помощью addFunction(...) на объекте контроллера. Вот как это выглядит:

Пример:

class ModuleOverview extends LizardModule {
    protected function setup() {
        $this->registerController(
            'overview',
            'App Overview'
        );
        $this->registerFunction(
            'overview',
            'myfunction',
            'My Function',
            array(&$this, 'theFunctionToCall')
        );
    }

    public function theFunctionToCall() { ... Generate Content ... }
}

Класс модуля:

class LizardModule {
    private $controllers = array();

    final public function __construct() { $this->setup(); }

    abstract protected function setup();

    [...]

    final protected function registerController($controllerSlug, $controllerName) {
        if (array_key_exists($controllerSlug, $this->controllers))
            return false;

        $this->controllers[$controllerSlug] = new LizardController($controllerSlug, $controllerName);
    }

    final protected function registerFunction($controllerSlug, $functionSlug, $functionName, callable $function) {
        if (!array_key_exists($controllerSlug, $this->controllers))
            return false;

        $this->controllers[$controllerSlug]->addFunction($functionSlug, $functionName, $function);
    }
}

Это приводит к множеству объектов типа LizardController в разных местах приложения. Чтобы сделать доступными все эти объекты, я создал одиночный класс LizardRouter, который должен содержать ссылку на все эти объекты контроллера. Следовательно, объект-контроллер регистрируется с помощью этого одноэлементного класса:

Класс контроллера:

class LizardController {
    [...]
    private $functions = array();

    public function __construct($slug, $name, $menu) {
        $this->slug = $slug;
        $this->name = $name;
        $this->menu = $menu;

        LizardRouter::registerController($this);
    }

    public function addFunction(...) { Tested, this works. }

    public function getFunctions() {
        return $this->functions;
    }
}

Класс маршрутизатора:

final class LizardRouter {
    [...]

    public static function getControllers() {
        return static::getInstance()->controllers;
    }

    public static function registerController(LizardController $controller) {
        static::getInstance()->controllers[] = $controller;
    }
}

Проблема

Все это прекрасно работает для контроллеров. В моем классе интерфейса я могу считывать все контроллеры и печатать меню, содержащее их имена. Проблема в том, что всякий раз, когда я обращаюсь к функциям-массиву контроллеров (см. Класс контроллера) через массив-контроллеры, заданный классом маршрутизации, я получаю пустой массив. Я предполагаю, что где-то ссылка не работает, и я передаю фактический объект контроллера, прежде чем мой модуль-класс смог добавить функции к функциям-массиву контроллеров. Но я не могу понять, где именно лежит проблема. Вот пример из моего класса интерфейса, показывающий проблему:

foreach (LizardRouter::getControllers() as $controller) {

    // Allways returns an empty array, even though
    // the module added functions to the controller.
    $controller->getFunctions();
}
Теги:

1 ответ

0
Лучший ответ

Поскольку это очень конкретный случай, я предполагаю, что маловероятно, что кто-нибудь когда-либо наткнется на ту же проблему. Так или иначе; Я нашел причину проблемы:

Объекты по умолчанию передаются как ссылка с PHP5. Переменные по умолчанию передаются по значению.

Массивы обрабатываются как переменные, поэтому, когда я передаю массив, содержащий объектные ссылки, создается и передается новая копия этого массива. Ссылки на объекты, добавленные в массив после того, как они были переданы, поэтому добавляются в исходный массив.

Решение, которое я выбрал, состояло в том, чтобы создать собственный "массив-класс" для хранения объектов. Он имеет не что иное, как частный объект массива, сеттер и геттер. Поскольку этот пользовательский класс массива является объектом, он автоматически передается по ссылке. Позже я также добавил некоторые функции для удобного доступа к массиву - хороший побочный эффект.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню