在__construct()

时间:2015-06-06 06:26:57

标签: php class oop constructor magic-methods

让我们来看看以下课程:

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类而不是member重新构建用户。

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

后,在基类中设置一个可用于检查/重新定义的标记
$user = new member($id);

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

后者感觉它引入了一个安全漏洞,特别是因为旗帜(可能很容易$user->user_level或类似的,我猜)必须公开才能检查之后它。

喜欢做的就是只调用new member($id)并让它自动处理,而不需要if语句。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:1)

您可以通过引入另一个类(让我们称之为user)并使用php中的__call魔术方法和call_user_func_array来调用方法来实现此目的。
逻辑是这样的 -
创建一个除user之外没有方法的check_user_level类。它会检查正确的详细信息,并将其$obj分配给membermoderator类的实例。

这是类的外观(我已经改变了函数来打印出来的东西) -

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课程即可自动决定是member还是moderator并调用该方法(如果存在)。
< / p>

//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
*/