我曾经以程序的方式编写php。由于我想了解更多有关OOP的知识,我决定以OOP方式为我的新项目编写php。
无论如何,假设我有一个需要用户登录的项目。这意味着在login.php中,一旦用户输入正确的用户名和密码,它将被重定向到index.php并开始加载产品表中的所有产品并在index.php中很好地显示它们。
之前,我是怎么做到的,在login.php中我会有以下代码:
的login.php
session_start();
...
if (loggedCorrect($user, $password)) {
$_SESSION['loggedinuser'] = $user;
//redirect to index.php
}
的index.php
session_start();
if (isset($_SESSION['loggedinuser']) {
//select fields from products table and display them
...
}
所以在OOP中它会是这样的:
的login.php
session_start();
$user = new User($user, $password);
if ($user->hasCorrectLogin()) {
$_SESSION['loggedinuser'] = $user->getUsername();
//redirect to index.php
}
的index.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
}
...
}
我的问题是:
启动对象时(就像我的情况下的产品一样)。我必须检查登录会话吗?如果是的话,我应该在__contruct中进行吗?或者我应该在“类产品”行之前这样做?
我还有一个cronjob.php,每隔x分钟执行一次。当它正在执行时,它将创建一些像Products这样的对象并对它们进行分析。因此,如果需要登录会话检查,那么我不知道如何使其工作,因为cronjob不支持会话。
请告知
答案 0 :(得分:1)
快速回答
没有。您的域对象本身不应该依赖于登录的会话;但是,他们可能需要一个User
实例来执行某些职责,例如只显示特定用户能够看到的产品。
由于#1,现在这是微不足道的。
代码审核
首先让我们考虑您的登录页面代码:
$user = new User($user, $password);
if ($user->hasCorrectLogin()) {
在此代码中,似乎用户与数据库交互并且知道如何验证凭据。对于单个班级来说,这似乎有点太多了。
它可以通过在对象中保留散列密码来执行密码验证,但是您只需要验证一次密码,因此实际上不需要保留该字段。不在此处完成此操作的另一个原因是,您需要考虑即时加强密码,这可能是随着硬件增长而扩展的网站策略(例如,当您使用bcrypt时)。
绝对不应该进行数据库交互;要将数据库交互和密码验证与用户类分开,您可以考虑添加身份验证服务。
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
不适合描述对象集合。 ProductList
或ProductCollection
等名称更好。
与上面的身份验证一样,不清楚Products
类是如何填充的;它应该来自某个存储,所以让我们介绍一下将提供产品列表的存储库:
$productRepository = new ProductRepository($db);
$products = $productRepository->getAll();
在最简单的场景中,使用数据库实例初始化存储库;必要时可以应用更多抽象级别。