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

时间:2019-07-15 15:19:37

标签: 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 '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();

最后,我得到“在null上调用成员函数test_model()”。我确实知道,每次实例化“扩展器”类时,都会重新初始化“模块”类的变量。好的,没问题,但是在那之后我给“父类”属性分配了所需的“值”(我的意思是$ module-> controller = new controller();)。

我不明白如何处理此行为。我想在我在控制器函数中编写的模块内实现这种类型的引用:$ this-> model-> some_func(),$ this-> view-> some_other()。还将有一个带有其他类的所谓注册表,扩展类也应该可用。

如果这是设计问题-好的,请指点我:)

谢谢。

4 个答案:

答案 0 :(得分:0)

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

<?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());

输出:

NULL

$foo的栏和$foo::baz的栏不相同。

答案 1 :(得分:0)

如其他答案所述,控制器拥有$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();

尽管我不确定要分配多少个类,但是您可能要使用注入:

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

如果您要注入并想使用动态注入,则可能需要查看Reflection,以便您的类不需要显式的参数分配。

您可以进入动态调用的范围,但是如果您不小心,可能会陷入困境!

<?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] => 
)

动态调用就位了,因此,如果您使用它,请小心操作。

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

答案 2 :(得分:0)

在调用$module作为树之前,Controller::test_controller()的状态(我将以驼峰式的方式显示类名):

$module: Module
Props:
  $controller: Controller
  Props:
    $controller: null
    $model: null
    $view: null
    $var: "global"
  $model: Model
  Props:
    $controller: null
    $model: null
    $view: null
    $var: "global"
  $view: View
  Props:
    $controller: null
    $model: null
    $view: null
    $var: "global"
  $var: "global"

可以看到吗? $module->controller$module->controller->controller不同。甚至$module->var$module->controller->var都不是同一个人。 $module$module->controller不同。

我不知道您是否做对了,但是解决方案是使用依赖注入。这意味着您应该将$module(依赖项)作为Controller::test_controller()的参数传递(或注入)。

答案 3 :(得分:0)

感谢您的回答。就是这样:您必须要求自己找到答案:)

应用程序的进入点是控制器和api,因此我必须在此处提供可用的东西,但不能在其他地方使用:“视图”一定不能看到“模型”。

因此,如果有人可能正在寻找此设计,它就会:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

我们的目标是像我自己设法实现的那样,在控制器和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; 之类的调用。