启动 PHP 类时,我是否必须检查登录会话


do I have to check login session when initiating PHP class?

我曾经以程序化的方式编写php。由于我想了解更多关于OOP的信息,我决定为我的新项目以OOP方式编写php。

无论如何,假设我有一个需要用户登录的项目。这意味着在登录时.php一旦用户输入正确的用户名和密码,它将被重定向到index.php并开始从产品表中加载所有产品并在index.php中很好地显示它们。

以前,我是如何做到这一点的,在登录时.php我将有以下代码:

登录.php

session_start();
...
if (loggedCorrect($user, $password)) {
     $_SESSION['loggedinuser'] = $user;
     //redirect to index.php
}

索引.php

session_start();
if (isset($_SESSION['loggedinuser']) {
      //select fields from products table and display them
      ...
}

所以在 OOP 中它将是这样的:

登录.php

session_start();
$user = new User($user, $password);
if ($user->hasCorrectLogin()) {
     $_SESSION['loggedinuser'] = $user->getUsername();
     //redirect to index.php
}

索引.php

session_start();
if (isset($_SESSION['loggedinuser']) {
     $products = new Products();
     //display all products
}

产品类别

class Products {
    private $productArray;
    ...
    __construct() {
         //select all products from mySQL table then put every product in productArray
    }
...
}

我的问题是:

  1. 启动对象时(如我的情况中的产品)。 我必须检查登录会话吗? 如果是这样,我应该在__contruct内进行吗? 还是应该在"类产品"行之前进行?

  2. 我还有一个 cronjob.php,它将每 x 分钟执行一次。当它执行时,它将创建一些对象,如产品并分析它们。因此,如果需要登录会话检查,那么我不确定如何使其工作,因为 cronjob 不支持会话。

请告知

快速解答

  1. 不。域对象本身不应依赖于已登录的会话;但是,他们可能需要User实例来执行某些职责,例如仅显示特定用户能够看到的产品。

  2. 由于#1,这现在是微不足道的。

代码审查

首先,让我们考虑一下您的登录页面代码:

$user = new User($user, $password);
if ($user->hasCorrectLogin()) {

在此代码中,用户似乎与数据库交互并知道如何验证凭据。对于一个班级来说,这似乎有点过分了。

它可以通过将散列密码保留在对象中来执行密码验证,但您只需要验证一次密码,因此实际上没有必要保留该字段。不在这里完成它的另一个原因是当您需要考虑即时加强密码时,这可能是随着硬件增长而扩展的站点策略(例如,当您使用 bcrypt 时)。

它绝对不应该进行数据库交互;要将数据库交互和密码验证与 User 类分开,您可以考虑添加身份验证服务。

try {
    $user = $authService->login($userName, $password);
    $_SESSION['loggedinuser'] = $user;
    // redirect to index.php
} catch (InvalidLoginException $e) {
    // oops, username or password invalid
}

在身份验证服务中,您可以添加另一个抽象层来加载用户记录(例如使用数据映射器)。

除了将

用户名存储在会话中,还可以存储整个 User 对象。在某些情况下,这可能会导致不一致,但它可以节省到数据库的往返次数。

现在,让我们观察产品概述页面:

$products = new Products();

在命名方面,我会说Products不是描述对象集合的好候选者。诸如ProductListProductCollection之类的名称更好。

与上面的身份验证一样,目前还不清楚Products类是如何填充的;它应该来自一些存储,所以让我们介绍一下将提供产品列表的存储库:

$productRepository = new ProductRepository($db);
$products = $productRepository->getAll();

在最简单的场景中,存储库使用数据库实例进行初始化;必要时可以应用更多级别的抽象。