2015-05-14 50 views
3

我在FOSUserBundle控制器(ProfileController)檢查發現如果$userUserInteface爲什麼我們需要檢查用戶的UserInterface實例

$user = $this->getUser(); 
if (!is_object($user) || !$user instanceof UserInterface) { 
    throw new AccessDeniedException('This user does not have access to this section.'); 
} 

例如是否足夠只有if (!is_object($user))檢查?

如果我的用戶實體擴展爲FOS\UserBundle\Model\User,那麼$user將不會是UserInterface的實例?

回答

1

是的,如果你的代碼不是開源的,否則沒有。

不檢查對象的實例並不能確保方法getUser()返回的對象將擁有您所期望的所有方法(例如:getUsername())。

如果您查看Controller.php中的getUser()方法,它不一定會返回用戶對象。事實上,您可以設置Symfony2防火牆,getUser()將返回不同實例的不同對象。

承認我們有一個接口UserInterface,它定義了getUsername()

在以下代碼中,我們的用戶對象不執行UserInterface

$user = $this->getUser(); 
if (!is_object($user)) { 
    $user->getUsername(); 
} 

此代碼將拋出一個錯誤,因爲getUsername()不會在對象上存在,而不是代碼應該是以下幾點:

$user = $this->getUser(); 
if (!is_object($user) || !$user instanceof UserInterface) { 
    $user->getUsername(); 
} 

如果用戶對象沒有實現正確的接口,則代碼不會出錯,因爲它不會被執行。

避免檢查類似下面的

$user = $this->getUser(); 
if (!is_object($user) || !$user instanceof User) { 
    $user->getRoles(); 
} 

對象如果有人擴展了用戶對象,然後if語句將不再執行,因爲$user不會是User實例,但說ExtendedUser即使它有所有你需要的方法。

使用接口的另一個優點是可以在對象上實現多個接口。

class A implements C {} 

class B extends A implements C, D {} 

interface C {} 

interface D {} 

$nA = new A(); 
$nB = new B(); 

$nA instanceof A; // true - instance of A 
$nA instanceof B; // false - pretty obvious, no relationship with B 
$nA instanceof C; // true - A implements C 
$nA instanceof D; // false - A does not implement D 

$nB instanceof A; // false - B is not an instance of A 
$nB instanceof B; // true - instance of B 
$nB instanceof C; // true - A implements C, that's the key: 
        //  both A and B implements C but B is not an 
        //  instance of A. 
$nB instanceof D; // true - A implements D 

TLDR;接口是設置期望並避免重大難題的好方法。

當您通讀代碼時,您可以快速識別傳遞的對象的類型。如果有人更改了代碼,它將顯示一個有意義的錯誤,或者會優雅地降級(在這種情況下,用戶將被拒絕訪問)。

-1

是的,這對新老開發者來說有點奇怪。

該接口允許多重繼承。我被告知,當類最好被描述爲「是」時,你使用繼承,就像狗是一種動物,或者SwiftMailer是一個Mailer。

接口然後可以用來插入額外的功能,它就像一個合同,說這個類必須實現一些方法。像樹皮或郵件。我被教導說這些接口應該被命名爲canBark或Barkable或Mailable等,然後這些接口將實現諸如樹皮或郵件之類的方法。

但現代開發人員更傾向於使用接口作爲額外的抽象,因此您可以快速交換類。

因此,不是綁定到您的用戶類,而是綁定到User類將實現的UserInterface。

所以要回答你的實際問題,只要FOS \ UserBundle \ Model \ User類或你的User類實現了UserInterface接口,那麼你就很好。

+0

這不是爲了快速交換類,而是爲了確保這些類必須實現所需的方法,以便現有代碼可以在需要時調用這些方法,並且不需要破解源代碼以滿足您的需求自己的類 – DarkBee

+0

接口不允許多重繼承,在PHP中沒有多繼承。 – Stev

1

如果我的用戶實體延伸FOS\UserBundle\Model\User,在這種情況下$user不會是UserInterface實例?

這是不正確的,因爲實現了FOS\UserBundle\Model\UserFOS\UserBundle\Model\UserInterface,其延伸(接口擴展其他接口)Symfony\Component\Security\Core\User\AdvancedUserInterface延伸Symfony\Component\Security\Core\User\UserInterface。所以$user instanceof UserInterface將是真實的。

接口是面向對象世界中的契約。通過is_object($user),您知道$user是一個對象,但您不知道對象具有哪些公共方法等。沒有任何東西阻止$this->getUser()返回完全不同的對象,從而破壞您的代碼。當你檢查實例時,你有一個承諾:界面中的方法可供你使用。作爲一項規則,我會建議你永遠不要打電話給你沒有明確輸入暗號或檢查使用instanceof的方法。