PHP如何使用$this引用邻居类->;类名?

PHP如何使用$this引用邻居类->;类名?,php,reference,extends,Php,Reference,Extends,很明显,我错过了什么。我有以下代码: <?php class module { protected $registry; public $controller; public $model; public $view; public $var = 'global'; } class controller extends module { public function test_controller() { echo '

很明显,我错过了什么。我有以下代码:

<?php

class module {
    protected $registry;
    public $controller;
    public $model;
    public $view;
    public $var = 'global';

}

class controller extends module {
    public function test_controller() {
        echo 'controller test';
        echo $this->var;
        $this->model->test_model();
        $this->view->test_view();
    }
}

class model extends module {
    public function test_model() {
        echo 'model test';
        echo $this->var;
    }
}

class view extends module {
    public function test_view() {
        echo 'view test';
        echo $this->var;
    }
}

$module = new module();
$module->controller = new controller();
$module->model = new model();
$module->view = new view();

echo "\n\n\n" . print_r($module);

$module->controller->test_controller();

这些是不同的实例。下同:

<?php

class Foo
{
    public $bar;
    public $baz;
}

class Baz extends Foo
{
    public function showMeTheBar()
    {
        return $this->bar;
    }
}

$foo      = new Foo;
$foo->bar = 'Hat';
$foo->baz = new Baz;
var_dump($foo->baz->showMeTheBar());
$foo
的条形图和
$foo::baz
的条形图是不同的。

如其他答案所述,控制器拥有
$this->model
$this->view
的所有权,因此在您的实例中,您必须为控制器分配新实例:

$module = new module();
$module->controller         =   new controller();
# Need to assign to the controller now, not the $module
$module->controller->model  =   new model();
$module->controller->view   =   new view();
这可能是你不打算做的。如果您想执行您正在执行的操作,您必须在
$module
范围内执行,并将单个元素带回
module

<?php
class module
{
    public $controller,
           $model,
           $view;

    public $var = 'global';

    protected $registry;
    # Add a new method that basically does what your controller method was doing.
    # Difference is that now these other classes are in the $module scope
    public function get()
    {
        $this->controller->test_controller();
        $this->model->test_model();
        $this->view->test_view();
    }
}

class controller extends module
{
    public function test_controller()
    {
        echo $this->var;
    }
}

class model extends module {
    public function test_model()
    {
        echo $this->var;
    }
}

class view extends module {
    public function test_view()
    {
        echo $this->var;
    }
}

$module = new module();
$module->model = new model();
$module->view = new view();
$module->controller = new controller();
$model->get();
如果您注入并希望使用动态注入,那么您可能希望查看反射,这样您的类就不需要显式的参数赋值

你可以进入动态调用的范围,但是如果你不小心的话,那可能会进入一个兔子洞

<?php
class module
{
    public $var = 'global';
    protected $registry;
    # Might want to add a getter
    public function __get($prop)
    {
        if(property_exists($this, $prop)) {
            return $this->{$prop};
        }
    }
    # Create a method getter
    public function __call($class, $args = false)
    {
        $class = strtolower(str_replace('get','', $class));
        # Set the dynamic variable
        if(!isset($this->{$class}))
            $this->{$class} = (is_array($args))? new $class(...$args) : new $class($args);
        # Send back new variable
        return $this->{$class};
    }
}

class controller extends module
{
    public function test_controller()
    {
         echo $this->var;
    }
}

class model extends module
{
    public function test_model()
    {
        echo $this->var;
    }
}

class view extends module
{
    public  function __construct()
    {
        print_r(func_get_args());
    }

    public function test_view()
    {
        echo $this->var;
    }
}

# Create instance of module
$module =   new module();
# use getView() to fetch and assign view
print_r($module->getView('arg1', 'arg2')->test_view());
# Since you set this value already, it can be pulled directly or by using
# getView()
print_r($module->view);
动态调用有它的位置,所以如果你使用它,就用心去做


对于持久变量,如前所述,您可以使用静态变量,因此如果您在一个类中更改变量,它将在所有类中更改。

调用
Controller::test\u Controller()
之前,将
$module
的状态作为树(我将以驼峰大小写的方式显示类名):

$module:module
道具:
$controller:controller
道具:
$controller:null
$model:null
$view:null
$var:“全球”
$model:model
道具:
$controller:null
$model:null
$view:null
$var:“全球”
$view:view
道具:
$controller:null
$model:null
$view:null
$var:“全球”
$var:“全球”
你能看见吗<代码>$module->controller
$module->controller->controller
不同。即使是
$module->var
$module->controller->var
也不是一回事<代码>$module和
$module->controller
是不同的


我不知道你做的是否正确,但解决方案是使用依赖注入;这意味着您应该将(
$module
(dependency)作为参数传递(注入)到
Controller::test\u Controller()
或其他任何内容。

谢谢您的回答。事情就是这样发生的:你必须自己问才能找到答案:)

该应用程序的入口点是控制器和api,因此我必须在那里提供资料,但不能在其他地方:“视图”不能看到“模型”

因此,如果有人可能正在寻找这种设计,那么它就是:

$controller = new Controller($registry);
$model = new Model($registry);
$api = new Api($registry);
$view = new Template($modulename);
//these classes above are already extended by abstract classes to bring $registry classes with __get()

$settings = new Settings($modulename);
$language = new Language($code);

$module = new stdClass();

$module->controller = $controller;
$module->controller->model = $model;
$module->controller->view = $view;
$module->controller->api = $api; //this might be questionable, but sometimes it's easier to do so
$module->controller->settings = $settings;
$module->controller->language = $language;

$module->api = $api;
$module->api->model = $model;
$module->api->view = $view;
$module->api->controller = $controller; //this might also be questionable, but sometimes it's easier to do so
$module->api->settings = $settings;
$module->api->language = $language; 

$model->settings = $settings;

我们的目标是(在控制器和api中)调用
$this->model->method(),$this->view->method()
,等等,我已经设法实现了这些调用。

为什么要扩展模块类?控制器的实例有一个空模型和视图。如果您真的想在继承类的不同实例之间共享变量,您可以使用静态属性,并且需要以不同的方式引用它们。但这可能是一种反模式。我扩展了module类,因为$registry中的功能应可用于控制器、模型和视图类。这是一件事。另一个是我想引用模型和控制器中的其他类(和其他类),比如$this->model,$this->api,$this->controller等等。是的,我已经意识到了这一点。谢谢你的回答。我不得不重新思考关于类的“可见性”的东西,例如视图必须对控制器可用,但控制器不能对视图可用等等。我重新设计了这个结构。是的,确切地说:我必须手动将这些实例分配给每个需要的类。这样我就可以更好地控制谁看谁。至于“getter”(getter)——我也不得不重新考虑这个问题,因为getter已经被定义为适合$registry。无论如何,谢谢。
<?php
class module
{
    public $var = 'global';
    protected $registry;
    # Might want to add a getter
    public function __get($prop)
    {
        if(property_exists($this, $prop)) {
            return $this->{$prop};
        }
    }
    # Create a method getter
    public function __call($class, $args = false)
    {
        $class = strtolower(str_replace('get','', $class));
        # Set the dynamic variable
        if(!isset($this->{$class}))
            $this->{$class} = (is_array($args))? new $class(...$args) : new $class($args);
        # Send back new variable
        return $this->{$class};
    }
}

class controller extends module
{
    public function test_controller()
    {
         echo $this->var;
    }
}

class model extends module
{
    public function test_model()
    {
        echo $this->var;
    }
}

class view extends module
{
    public  function __construct()
    {
        print_r(func_get_args());
    }

    public function test_view()
    {
        echo $this->var;
    }
}

# Create instance of module
$module =   new module();
# use getView() to fetch and assign view
print_r($module->getView('arg1', 'arg2')->test_view());
# Since you set this value already, it can be pulled directly or by using
# getView()
print_r($module->view);
Array
(
    [0] => arg1
    [1] => arg2
)

global

view Object
(
    [var] => global
    [registry:protected] => 
)
$controller = new Controller($registry);
$model = new Model($registry);
$api = new Api($registry);
$view = new Template($modulename);
//these classes above are already extended by abstract classes to bring $registry classes with __get()

$settings = new Settings($modulename);
$language = new Language($code);

$module = new stdClass();

$module->controller = $controller;
$module->controller->model = $model;
$module->controller->view = $view;
$module->controller->api = $api; //this might be questionable, but sometimes it's easier to do so
$module->controller->settings = $settings;
$module->controller->language = $language;

$module->api = $api;
$module->api->model = $model;
$module->api->view = $view;
$module->api->controller = $controller; //this might also be questionable, but sometimes it's easier to do so
$module->api->settings = $settings;
$module->api->language = $language; 

$model->settings = $settings;