在 __construct() 期间切换 类

Switching Classes during __construct()

让我们暂时看看以下 classes:

class member {
    public $id;

    public function __construct($id) {
        $this->id = $id;

        // Check user level
        if ($this->check_user_level() == moderator) {
            $this = new moderator($this->id);
        }
    }

    private function check_user_level() {
        // Return user level from system based on user ID
    }
}

class moderator extends member {
    public function show_moderator_tools() {
        // etc.
    }
}

==================

$user = new member($user_id);

期望的行为是 $user 检测用户是否被授权拥有主持人访问权限,如果是,则使用 moderator class 而不是 [=14] 重铸用户=].

PHP 禁止简单地重新分配 $this,因此最好的解决方案是以下之一:

运行 check_user_level($id) 作为常规函数并使用 if 语句

$user_level = check_user_level($id);

if ($user_level == "moderator") {
    $user = new moderator($id);
} else {
    $user = new member($id);
}

在初始化$user

后,在class中设置一个可以用于check/redefinition的标志
$user = new member($id);

if ($user->flag = TRUE) {
    $user = new moderator($id);
}

后者感觉像是引入了安全漏洞,特别是因为标志(我猜可能很容易是 $user->user_level 或类似的标志)必须是 public 才能之后再检查。

喜欢 做的是只调用 new member($id) 并让它从那里自动处理事情,而不需要之后的 if 语句事实。有办法吗?

您可以通过引入另一个 class(我们称它为 user)并使用 __call magic method in php and call_user_func_array 来调用方法。
逻辑是这样的 -
创建一个 user class 除了 check_user_level 之外没有任何方法。它检查适当的细节并将其 $obj 分配给 membermoderator class.
的实例
这是 classes 的样子(我已经更改了函数来打印一些东西)-

class user{
    public function __construct($id) {
        $this->id = $id;
        if ($this->check_user_level() == "moderator") {
            $this->obj = new moderator($this->id);
        }else{
            $this->obj = new member($this->id);
        }
    }

    public function __call($method, $args){
        call_user_func_array(array($this->obj,$method), $args);
    }

    public function __get($prop){
        if(isset($this->obj->$prop)){
            return $this->obj->$prop;    
        }
        return NULL;
    }

    private function check_user_level() {
        // Return user level from system based on user ID
        if($this->id == 1){
            return "moderator";
        }
        return "member";
    }
}

class member {
    public $id;

    public function __construct($id) {
        $this->id = $id;
    }

    public function show_message($arg){
        var_dump($this->id.$arg);
    }
}

class moderator extends member{
    public function show_moderator_tools() {
        var_dump($this->id ."My toolset!");
    }
}

所以,现在您可以简单地调用 user class,它会自动确定它是 member 还是 moderator,如果存在则调用该方法.

//Trying out a few examples
//Creating a member user
$mem_obj = new user(213);
$mem_obj->show_message("New message");

//Creating a moderator user
$mod_obj = new user(1);
$mod_obj->show_moderator_tools();

/*
OUTPUTS
-------
string(14) "213New message"
string(12) "1My toolset!"
*/

但是你需要小心这些黑客行为。
例如 -

//This will fail
//because mem_obj doesn't have show_moderator_tools()
$mem_obj->show_moderator_tools();

编辑 您可以类似地继续使用 __get.
重定向到属性 我修改了上面的代码,在 __call.

下面添加了这个方法
//Testing it
var_dump($mem_obj->id);
//This is an illegal property
var_dump($mem_obj->illegelProperty);
/*
OUTPUTS
int(213)
NULL
*/