【问题标题】:PHP OOP architecture question (OOP against Roles)PHP OOP 架构问题(针对角色的 OOP)
【发布时间】:2011-02-19 07:29:40
【问题描述】:

系统中有不同权限的用户。他们的权限是分层的

class User{//abstract user not logged in
    //function signIn(){}
}

class Guest extends User{

}

class FullUser extends Guest{
    static function signUp(){}//create an account
    function signOut(){}
}

class Moderator extends FullUser{
          function edit(){}//some new method introduced here,never introduced before
}

class Admin extends Moderator{
           //can do everything
}

//can use
FullUser::signUP()

我的架构好吗? 你还能给我什么建议吗? 我想知道哪个是创建用户的最佳方式 - 编写构造函数?或者让它成为一个“工厂”函数。

function signIn($username, $password)

我是 php 的 OOP 新手,所以我接受明智的建议、链接等。


编辑: 我打算使用这个角色-检查系统:

if(!method_exists($user->addComment())) die('Access denied')

你怎么看?


编辑 2: 我应该创建一个角色表,其中 X 轴为 ROLE,Y 轴为 METHOD?

            comment | post |  editPost | kill
guest          0        0        0         0
fullUser       1        0        0         0
moderator      1        1        1         0
admin          1        1        1         1

以后我应该写这样的东西

function addComment($user){
if(!$ROLES [$this->$role][__FUNCTION__])return;
....
}

这比 OOP 更好吗,聪明的程序员?

【问题讨论】:

    标签: php oop


    【解决方案1】:

    角色绝对是要走的路。

    您可以做一些简单的事情,例如让每个用户都有一个 public $role 属性,其中 $role 只是一个数字(例如 9 = admin、6 = fulluser、3 = guest)。

    数据库表如下所示

    Users
    id  username    password    role
    1   admin       somePass    9
    2   someUser    somePass    3
    

    在代码中,您可以执行“if ($user->role >= 9)”之类的操作。

    如果需要,您可以使用角色表而不是仅使用数字 - 像这样:

    Roles
    id  role
    1   admin
    2   fulluser
    3   user
    4   guest
    

    您还可以让它更高级,一个用户可以拥有一系列角色。

    【讨论】:

    • 我帖子中的 EDIT 2 是您方法的扩展吗?
    【解决方案2】:

    我更倾向于基于基于角色的系统设置权限。它更加灵活,因为用户可以与 1 个或多个角色相关联,并且根据这些角色,他们可以执行不同的操作。

    【讨论】:

    • 您能否在我的简单示例中描述“基于角色的系统”?
    【解决方案3】:

    我也会定义一个基于角色的架构。

    首先,让我们为用户凭据创建一个类:

    class CUserCredentials {
    
        public 
            $orgID,
            $ordSubID,
            $password;
    
        // or protected instance variables an accessors
    
    } // CUserCredentials
    

    在我们的例子中,用户通过组织 ID [公司编号] 进行识别,这是一个与其相关的数字 orgID [例如。他的员工编号] 和密码。

    针对某个角色测试凭据的过程被抽象类封装:

    class CAbstractRoleVerifier {
    
        // return 
        public static function hasRoleUsingUserCredentials( CUserCredentials $cred );
    
    }
    

    hasRoleUsingUserCredentials() 方法根据“任何”验证凭据,例如一个数据库表。

    然后我们定义一个抽象的角色管理器,它是具体实现的模板:

    class CAbstractRoleManager {
    
        static protected 
            $possibleRoles;
    
        // The standard role
        protected $primaryRole;
    
        // The other roles he is able to use
        protected $userrRoles;
    
        // verifies all defined roles
        public function verifyAllRoles( CUserCredentials $cred );
    
    }
    

    虽然上述类是我们框架的一部分,但我们的应用程序需要实现一个具体的角色管理器,例如像这样:

    class CMyRoleManager extends CAbstractRoleManager {
    
        // these two are nomal roles
        const ROLE_USER     = 1;
        const ROLE_MANAGER  = 2;
    
        // this is a special role, which allows to 
        const ROLE_ADMIN    = 3;
    
        protected 
            $userRoles;
    
        public function __construct() {
    
    
            // prepare CMyRoleVerifierUser, CMyRoleVerifierManager as subclasses of the             
            // above class          
            self::$possibleRoles = array(
                self::ROLE_USER     => new CMyRoleVerifierUser(),
                self::ROLE_USER     => new CMyRoleVerifierManager(),
                self::ROLE_ADMIN    => new CMyRoleVerifierAdmin(),
                ); 
    
            // Initially, user has no role
            $this->userRoles = array();
    
            $this->mainRole = FALSE;
    
    
        }
    
        public function verifyAllRoles( CUserCredentials $cred ) {
    
            foreach( self::$possibleRoles as $roleID => $verifier ) {
    
                if ( $verifier->hasRoleUsingUserCredentials( $cred ) ) {
    
                    $this->userRoles[ $roleID ] = $roleID; 
                }
    
            }
    
        }
    
        public function hasRole( $aRoleID ) {
    
            return isset( $this->userRoles[ $roleID ] );
    
        }
    
    }
    

    注意,验证角色集的过程和验证特定角色的过程是如何在不同的类中分离的。

    虽然可以使用类/子类设计,但我更喜欢这种设计。它允许保留一组可能有任何关系的角色,不仅允许 ROLE_MANAGER 对所有 ROLE_USER 加上一些其他操作。

    就我而言,ROLE_ADMIN 是一个特殊角色。如果用户针对 ROLE_ADMIN 进行验证,他会看到某些管理功能已启用。除了其他特殊操作,他可以​​暂时表现得好像他是另一个角色。 $this->mainRole 在这里没有完全实现

    【讨论】:

    • 您能看看我的基于角色的架构版本吗?
    • 我很高兴明天提供一个基本实现。今天有点晚了,晚上1点22分;-)
    • 你能用几句话解释一下你的想法吗?
    【解决方案4】:

    一般来说,我倾向于使用按位权限系统,权限是根据个人需要设置的,并且可以被组权限覆盖,例如,您可以查看用户是否有权限,如果没有,请查看是否他们所属的组拥有它,等等。这在添加新功能和可扩展性方面似乎非常灵活。

    你的方法会奏效。至于构造函数,我可能不会覆盖它并让它登录用户,获取他们的统计信息和权限等,并确保在每个新页面上调用它。然后创建简单的函数,比如class::listPermissions等,都使用parent::function,比如parent::listPermissions。这将有助于继承,例如在我的示例中,列出 admin 类的权限将调用 Admin::listPermissions、FullUser::listPermissions、Guest::listPermissions,因此它们将获得它们继承的所有权限。

    我通常对基于类的系统不太满意,但我以前见过它们的实际应用。

    【讨论】:

      【解决方案5】:

      我认为您的继承层次结构有点混乱。据我所知,它看起来像:

      User // abstract
          Guest // anonymous and can't do anything
              FullUser // can sign up
                      Admin // can do everything
      

      换句话说,Guests 是用户,FullUsers 是 Guests,Admins 是 FullUsers,因此 Admins 也是 Guests。我想我可以看到你在做什么 - 在继承层次结构中逐步给予更多特权。但是,结果是您将在扩展 User 类的具体类上具有高度耦合,并且您将完全错过 OOP 的最大好处之一 - 多态性。

      许多其他发帖人建议改用角色,这很好。您也可以通过继承来实现,其中User 是一个抽象类,它定义了抽象方法signInsignOut,而不同的子类(例如AdminUserGuestUser)对这些方法实现完全不同的行为——例如对于 GuestsignOut 没有任何行为。

      【讨论】:

      • 我会失去多态性吗?假设我写$moderator->addComment() addComment 是在FullUser 类中定义的
      • 阅读您的第二段 - 这也是一个对象模型!它是多态的。什么是角色系统?那是基于数组吗?正如 arex1337 提议的那样?
      • 当您需要引用特定的具体类而不是基类时,您就失去了多态性。
      【解决方案6】:

      忽略数据库设计,您可能应该只有一个 User 类,而不是拥有越来越少的强大用户的继承系统 - 这很容易改变。有时您可能希望一个不太强大的用户能够做一些更强大的用户不能做的事情。

      让您的用户对象具有一个或多个角色。然后做这样的事情:

      if ($user->isAdmin()) {
          //
      }
      

      【讨论】:

      • 是的,如果由于一些新的客户要求而导致层次结构中断,您的方法可以工作,并且很容易更改我的 ROLES 表。在这种情况下,OOP 方式很糟糕
      • 我的方法没有任何非 OOP。如果您想将用户拥有的角色表示为类,欢迎您这样做。
      猜你喜欢
      • 2012-09-20
      • 2011-05-07
      • 2014-07-18
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      • 2012-08-26
      相关资源
      最近更新 更多