duanrang3357 2015-11-09 15:19 采纳率: 0%
浏览 68
已采纳

通过引用传递的对象中的数组是空的,即使它稍后被填充

In the progress of writing a little framework for a web app I came along some difficulties in making classes communicate with each other.

Environment

I have an abstract class called LizardModule, that should be extended by all the single modules of the web-app. This class has a final protected function registerController(...), that creates a new Object of the type LizardController. This is, as it sounds, based on the idea of MVC. With the final protected function registerFunction(...), modules can register functions for every controller. Those are stored using addFunction(...) on the controller object. Here is what this looks like:

Example Module:

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 ... }
}

Module Class:

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);
    }
}

This results in a lot of objects of type LizardController in different places of the app. To make all of those objects accessable, I created a singleton class LizardRouter, that should hold a reference to all of those controller objects. Therefore, the controller-object registers itself with this singleton class:

Controller Class:

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;
    }
}

Router Class:

final class LizardRouter {
    [...]

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

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

The Problem

The whole thing works alright for the controllers. In my interface class, I can read out all controllers and print a menu containing their names. The problem is: Whenever I access the controllers functions-array (see controller class) through the controllers-array given by the routing class, I get an empty array. I asume that somewhere a reference is not working and I am passing the actual controller object, before my module-class was able to add the functions to the controllers functions-array. But I can't figure out where exactly the problem lies. Here is an example from my interface class showing the problem:

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

    // Allways returns an empty array, even though
    // the module added functions to the controller.
    $controller->getFunctions();
}
  • 写回答

1条回答 默认 最新

  • duangangmo0583 2015-11-13 13:36
    关注

    Since this is a very specific case, I guess it is unlikely, that anyone will ever stumble upon the same problem. Anyway; I found the reason for the problem:

    Objects are by default passed as reference since PHP5. Variables are by default passed by value.

    Arrays are handled like variables, so when I pass an array containing object-references, a new copy of this array is created and passed. Object references added to the array after it was passed are therefore only added to the original array.

    The solution i chose was to create my own "array-class" for holding objects. It has nothing more than a private array object, a setter and a getter. Since this custom array class is an object, it is automatically passed by reference. Later I also added some functions to conveniently access the array - a good side-effect.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?