2015-05-14 43 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的方法。