2015-06-06 44 views
2

讓我們以下面的類了片刻:開關類()

 
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

你可以通過在php和call_user_func_array中引入另一個類(讓它叫做user)和使用__call魔術方法來調用這些方法。
邏輯就像這樣 -
創建一個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類,如果它是一個會自動決定membermoderator並調用該方法(如果存在)。

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

剛剛測試過它,它的工作非常好!我不太確定具體如何,但我想我已經開始瞭解它。實質上,每個對象實際上都是'user'的一個實例,它具有嵌入在$ this-> obj中的適當用戶級別類的另一個對象。如果不是'user'的一部分被調用,那麼__call()會指示它在嵌套對象中運行相應的函數。這是關於標誌嗎? – Kaji

+1

@Kaji是的,這就是整個想法:) – Kamehameha

+0

太棒了!是否可以設置屬性以同樣的方式工作? – Kaji