我目前正在验证输入并在“胖控制器”中返回错误,如下所示:
class SomeController
{
public function register()
{
// validate input
$username = isset($_POST['username']) && strlen($_POST['username']) <= 20 ? $_POST['username'] : null;
// proceed if validation passed
if (isset($username)) {
$user = $this->model->build('user');
if ($user->insert($username)) {
$_SESSION['success'] = 'User created!';
} else {
$_SESSION['error'] = 'Could not register user.';
}
} else {
$_SESSION['failed']['username'] = 'Your username cannot be greater than 20 characters.';
}
// load appropriate view here
}
}
class SomeModel
{
public function insert($username)
{
// sql for insertion
// ...
return $result;
}
}
虽然这很有效并且我很容易实现,但我知道这是不正确的,因为验证属于模型,我试图使用“胖模型”进行纠正,如下所示:
class SomeController
{
public function register()
{
$user = $this->model->build('user');
$user->insert($_POST['username']);
// load appropriate view here
// ...
}
}
class SomeModel
{
public function insert($username)
{
// validate input
$error = false;
$username = trim($username) != '' && strlen($username) <= 20 ? $username : null;
// proceed if validation passed
if (isset($username)) {
// sql for insertion
// ...
$_SESSION['success'] = 'User created!';
} else {
// store error in session
$error = true;
$_SESSION['error']['username'] = 'Your username cannot be greater than 20 characters ';
}
return $error ? false : true;
}
}
我在这里看到的问题是该模型应该是可移植的,因为它永远不需要改变。但如果对$username
长度的要求发生变化,那么显然我将不得不改变我的模型。
我觉得这可能是一个非常常见的问题,但我还没有找到一个直截了当的答案。如果没有实现任何额外的“层”,“映射器”或其他任何令人困惑的术语,那么如何修改提供的示例伪代码以正确处理此事务? (例如,验证输入,如果验证失败则返回错误)?
答案 0 :(得分:6)
不实施任何额外的“图层”,“地图制作者”或其他任何
您应该将“模型”视为应用图层而不是单个类。术语“层”可以被认为是参考M切片MVC三明治的简单方式。因此,要实现您希望的灵活性, 需要创建它。
可以做出许多明确的分离。我会考虑有三个抽象:服务,数据映射器和实体。
服务将暴露给控制器并执行所请求的服务。
// some controller
function register() {
$service = $this->getUserService();
$user = $service->register($_POST['first_name'], $_POST['last_name']);
if ($user instanceof \My\Entity\User) {
// set user in view
} else {
// redirect to error
}
}
所以任务一完成,控制器现在对寄存器内发生的事情都是愚蠢的,它只想知道如何解决相应的结果。如果有用户对象,则成功,否则会出错。
服务类本身将封装所提供的服务:
// class UserService.php
function register($firstname, $lastname) {
// validate arguments
if ($this->isValidUsername(....
$userMapper = $this->getUserMapper();
$user = new My\Entity\User();
$user->setFirstName($firstname);
$user->setLastName($lastname);
return $userMapper->save($user);
}
return false;
}
我们处理参数的验证并创建新用户,将其传递给数据映射器,它将执行抽象数据库操作的“实际保存”。
// UserMapper
function save($user) {
// save $user to db
$sql = 'INSERT INTO ....
return true;
}
答案 1 :(得分:1)
我不确定你认为什么是不受欢迎的“图层”或“映射器”。这是一个有趣的问题,我的第一个问题是你可以只包含一个配置文件,为你的用户名长度定义一个常量。我的第二个问题是你可以让someModel扩展一个类或实现一个接口,其中你的值将被设置为属性或常量。我怀疑你已经想到了这些,并且正在避开它们;这就是你避免“层”和“映射器”的意思看来你在这段代码中受到这些原则的指导:
那么,你在运行php5.4 +吗?也许定义一个可以在这个和其他模型中使用的特征,它定义应用程序中的用户名长度和其他可变值。或者也许这也是一个“层”?