基于PHP面向对象编程的登录系统

4
假设我正在构建一个基于OOP的用户身份验证系统,并且我想要融入以下原则:直接注入(Direct Injection)、继承(Inheritance)、封装(Encapsulation)、多态性(Polymorphism)和单一职责原则(Single Responsibility Principle)。
我的编程背景一直依赖于过程式编程,因此,我发现真正将这些实践应用到正确的地方还是有困难的。
假设我有以下类:
class Config
{
    public function set($key, $value);
    public function get($key, $default = null);
}

class User
{
    public function __construct(PDO $dbh, $id = null);
    public function setProfile(Profile $profile);
}

class Auth
{
    public function __construct(Config $config);
    public function login($username, $password, $keepLoggedIn = true);
    public function isLoggedIn();
    public function getLoggedInUser();
    public function logout();
    public function register(array $data);
}

class Session
{
    public function start($sessionName = null);
    public function write($key, $value);
    public function read($key, $default = null);
}

class Profile
{
    public function setAddress(Address $address);
    public function setName($name);
    public function setDOB(DateTime $date);
    public function getAge();
}

class Validator
{
    public function validate($input);
}

我有意省略了函数体以保持简单。
据我所知,我认为我正确地使用了原则。然而,我仍然不清楚如何连接类,比如:将 Validator 连接到 User 模型,将 User 模型连接到 Auth,将 Session 连接到 Auth 类。所有这些都互相依赖。
1个回答

2
你走在正确的道路上了。这些类相互连接的方式被称为继承。我倾向于采用MVC设置,即模型(Model),视图(View)和控制器(Controller)。
你的逻辑应该放在控制器中,所有数据库查询和具体后端方法都应该放在模型中。控制器接收请求并返回响应。它是中间人。在请求发送给它之后,它与后端进行通信,并通过响应将前端馈送进来。
所以你会有一个核心控制器(保持最简),然后每个类都会继承核心控制器。因此,你的控制器就是把所有这些东西联系起来的地方。
 <?php
//your main core controller, where you load all these things you need avilable, so long as this class is extended
class CoreController {

    public $auth
    public $session;
    public $view;

   function construct__ ()
   {
       $this->auth = instantiateAuthClassHere();
       $this->session = instantiateSessionClassHere();
       $this->view = instantiateViewClassHere();
   }

    public function anotherHelperForSomething(){
        //helper stuff for this method    
    }
}

//index, page, or content controller, depending on how many you need, i.e. if you want a controller for each page, thats fine, e.g indexController, etc..
//this is the middle man, has logic, receives requst, returns response to view.
class Controller extends CoreController {

    public function index (){

        $userModel = new userModel();

        //do something with this
        $session = $this->session;

        $content = 'some html';
        $userInfo = $userModel->getUsers();

        $view = $this->view->render( array(
            'content' => $content,
            'userInfo' => $userInfo,
        ));

        return $view;
    }
}

//Core LIbraries
class Validator {
    //your validator stuff
}

//Core LIbraries
class Session {
    //your validator stuff
}

//Core LIbraries
class Auth {
    //your validator stuff
}

class CoreModel{

    public $validator;

    function __construct(){
        $this->validator = instantiateValidatorClassHere();
    }
}

//a user model  class (back end). you want a model class for each db table pretty much. 
class UserModel extends CoreModel {


// if you need the validator anywhere inside this class, its globally available here inside any class that extends the CoreModel, e.g.  $this->validator->methodName()


    public function getUsers (){
        $sql = 'SELECT * from users';
        $result = $db->get($sql);

        return $result;
    }
}

注意,在Controller中,这是类似于indexController或任何自定义内容的通用名称。此外,我在那里有一个词extends。它继承了从父级继承的所有对象。现在,在其中,它们将通过$this->可用。请参阅我的示例,我获取$this->session
尽量避免构造函数 - 除了核心和特殊情况下,您可能不需要它们,甚至在那种情况下,您也需要自己检查。我不再经常使用构造函数。它可能有点笨拙和难以管理。

嗨,我在那里添加了模型,在编辑中...好的,我想我看到你需要在模型中使用验证类,而不是索引控制器,所以我们也可以创建一个核心模型控制器,这样怎么样?好的,我更新了那个... - blamb
好的,这个模型只适用于你的应用程序,而不是其他应用程序。这是应用程序的模型。是的,它可以防止类被重写。是的,用户验证逻辑可能应该放在控制器中,而不是模型中。很好的想法,你走在正确的轨道上。把它想象成一个商业模型,只适用于一个企业。 - blamb
顺便说一句,我上面提到的核心库不适用于模型(M)、视图(V)或控制器(C),它们只是外部的第三方库,你可以进行扩展。在Symfony中,它们被称为vendors。将这些核心库类想象成你要使用的vendors,而不是MVC的一部分。因此,你可以有一个目录结构,例如site/app/model/、site/app/views/app/controller/和site/vendors/ValidationClassVendorName/ValidationController.php。 - blamb
以上更正为:site/app/model/、site/app/views/、site/app/controller、site/vendors/VendorName/VendorController.php。然后你可以将这些供应商包含在你的核心控制器中,或者更好地使用自动加载和命名空间(另一个话题)。顺便说一下,如果这篇回答有帮助,请标记为已接受的答案,谢谢! - blamb
2
这与MVC无关,OP的问题也不是。此外,您通过在类内实例化所有内容来紧密耦合所有内容。通过使所有内容“公开”,您失去了封装性。您的GodModeController实例化了它可能根本不需要的东西。您关于“尽量避免构造”的评论毫无意义。我为@NathanBishop感到难过,他认为这个答案实际上会以某种方式使他的代码更好。 - PeeHaa
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接