代码之家  ›  专栏  ›  技术社区  ›  Matthew M

扩展类穿越NULL-OOP

  •  0
  • Matthew M  · 技术社区  · 7 年前

    我的所有用户方法都有以下类:

    class User {
      protected $_db,
                $_data;
    
      public function __construct($user = null, $findby = 'id') {
        $this->_db = DB::getInstance();
    
        if (!$user) {
          ........
        } else {
          ........
        }
      }
    
     .......
    
      public function login($username = null, $password = null) {
        $user = $this->find($username, 'username');
        if ($user) {
          $lockdown = new Lockdown; 
        }
      }
    
      public function find($param = null, $method = null) {
        if ($param && $method) {
          $data = $this->_db->query("SELECT * FROM users ...");
          if ($data->count()) {
            $this->_data = $data->result();
            return true;
          }
        }
        return false;
      }
    
      public function data() {
        return $this->_data;
      } 
    }
    

    上面是我的用户类的一个完全精简版本。我还有另一个类(锁定),它扩展了用户:

    class Lockdown extends User {
      public $getAttempts;
    
      public function __construct() {
        var_dump($this->data());
        die();
      }
    }
    

    然而,当我在login类内部调用锁定类时,即使数据对象应该包含所有用户信息,var\u dump()也只是返回NULL。

    根据我在调用login类时的计算 应该设置$_data=USER INFO,因此应该允许在($this->find())之后调用的新锁定方法能够访问相同的数据方法。

    我还在学习面向对象编程,所以不知道我是否遗漏了什么,但我似乎无法理解为什么锁定类在应该继承数据方法时在数据方法上返回NULL。

    1 回复  |  直到 7 年前
        1
  •  2
  •   tereÅ¡ko    7 年前

    您不应该在构造函数中放置任何计算逻辑。这使得测试变得困难。也不能从构造函数返回。

    你的结构是一场彻底的灾难。都是因为你们滥用继承权和全球国家。

    对于一个类来说,创建自己的子类的新实例来检索数据是没有意义的。这可能是由于您试图 User Single Responsibility Principle ,然后以复杂调用图的形式显示。

    也是整体 class Lockdown extends User 构造没有意义。这个 extends OOP中的关键字可以翻译为“is special case of”(根据 LSP ). 用于跟踪用户登录尝试的类不是“user”的特例。

    为此,您应该至少有3个单独的类:一个用于处理“用户行为”,另一个用于保存/恢复“用户状态”(该方法称为“ data mapper 第三个将用于管理失败的尝试。

    this lecture .

    至于全局状态,您应该将数据库连接作为构造函数的依赖项传递给需要与持久性交互的类,而不是使用单例反模式。

    至于代码,在较高的层次上,它可能看起来像这样:

    $user = new User;
    $mapper = new UserMapper($db);
    
    $user->setName($username)
    if ($mapper->fetch($user)) {
       if ($user->matchPassword($password)) {
           // you have logged in
           // add some flag in session about it
           header('Location: /greetings');
           exit;
       }
       // check the failed attempts
    } else {
      // no matching username 
    }