Php 在MVC网站中验证和处理表单提交的位置
我正在开发一个基于PHP的模型-视图-控制器结构化网站。我理解模型应该处理业务逻辑,视图向用户呈现HTML(或任何内容),而控制器促进了这一点。我要做的就是处理表格我应该在控制器中放入多少处理程序,我应该在我的模型中放入多少处理程序? 假设我正在尝试更新用户的名字和姓氏。我想做的是使用AJAX向我的一个控制器提交一个表单。我希望(再次)在服务器端验证数据,如果有效,则将其保存到数据库,然后将JSON响应返回到视图,无论是成功还是错误 我应该在控制器中创建用户模型的实例,还是应该让控制器中继到模型中的静态方法?下面是两个示例,说明了这是如何工作的: 选项#1:在模型中处理POSTPhp 在MVC网站中验证和处理表单提交的位置,php,model-view-controller,validation,forms,Php,Model View Controller,Validation,Forms,我正在开发一个基于PHP的模型-视图-控制器结构化网站。我理解模型应该处理业务逻辑,视图向用户呈现HTML(或任何内容),而控制器促进了这一点。我要做的就是处理表格我应该在控制器中放入多少处理程序,我应该在我的模型中放入多少处理程序? 假设我正在尝试更新用户的名字和姓氏。我想做的是使用AJAX向我的一个控制器提交一个表单。我希望(再次)在服务器端验证数据,如果有效,则将其保存到数据库,然后将JSON响应返回到视图,无论是成功还是错误 我应该在控制器中创建用户模型的实例,还是应该让控制器中继到模型
<form action="/user/edit-user-form-submit/" method="post">
<input type="text" name="firstname">
<input type="text" name="lastname">
<button type="submit">Save</button>
</form>
<?php
class user
{
public function __construct($id){} // load user from database
public function set_firstname(){} // validate and set first name
public function set_lastname(){} // validate and set last name
public function save_to_database(){} // save object fields to database
public static function save_data_from_post()
{
// Load the user
$user = new user($_POST['id']);
// Was the record found in the db?
if($user->exists)
{
// Try to set these fields
if(
$user->set_firstname($_POST['firstname'])
and
$user->set_lastname($_POST['lastname'])
)
{
// No errors, save to the dabase
$user->save_to_database();
// Return success to view
echo json_encode(array('success' => true));
}
else
{
// Error, data not valid!
echo json_encode(array('success' => false));
}
}
else
{
// Error, user not found!
echo json_encode(array('success' => false));
}
}
}
class user_controller extends controller
{
public function edit_user_form()
{
$view = new view('edit_user_form.php');
}
public function edit_user_form_submit()
{
user::save_data_from_post();
}
}
?>
<form action="/user/edit-user-form-submit/" method="post">
<input type="text" name="firstname">
<input type="text" name="lastname">
<button type="submit">Save</button>
</form>
<?php
class user
{
public function __construct($id){} // load user from database
public function set_firstname(){} // validate and set first name
public function set_lastname(){} // validate and set last name
public function save_to_database(){} // save object fields to database
}
class user_controller extends controller
{
public function edit_user_form()
{
$view = new view('edit_user_form.php');
}
public function edit_user_form_submit()
{
// Load the user
$user = new user($_POST['id']);
// Was the record found in the db?
if($user->exists)
{
// Try to set these fields
if(
$user->set_firstname($_POST['firstname'])
and
$user->set_lastname($_POST['lastname'])
)
{
// No errors, save to the dabase
$user->save_to_database();
// Return success to view
echo json_encode(array('success' => true));
}
else
{
// Error, data not valid!
echo json_encode(array('success' => false));
}
}
else
{
// Error, user not found!
echo json_encode(array('success' => false));
}
}
}
?>
拯救
选项#1:在模型中处理POST
<form action="/user/edit-user-form-submit/" method="post">
<input type="text" name="firstname">
<input type="text" name="lastname">
<button type="submit">Save</button>
</form>
<?php
class user
{
public function __construct($id){} // load user from database
public function set_firstname(){} // validate and set first name
public function set_lastname(){} // validate and set last name
public function save_to_database(){} // save object fields to database
public static function save_data_from_post()
{
// Load the user
$user = new user($_POST['id']);
// Was the record found in the db?
if($user->exists)
{
// Try to set these fields
if(
$user->set_firstname($_POST['firstname'])
and
$user->set_lastname($_POST['lastname'])
)
{
// No errors, save to the dabase
$user->save_to_database();
// Return success to view
echo json_encode(array('success' => true));
}
else
{
// Error, data not valid!
echo json_encode(array('success' => false));
}
}
else
{
// Error, user not found!
echo json_encode(array('success' => false));
}
}
}
class user_controller extends controller
{
public function edit_user_form()
{
$view = new view('edit_user_form.php');
}
public function edit_user_form_submit()
{
user::save_data_from_post();
}
}
?>
<form action="/user/edit-user-form-submit/" method="post">
<input type="text" name="firstname">
<input type="text" name="lastname">
<button type="submit">Save</button>
</form>
<?php
class user
{
public function __construct($id){} // load user from database
public function set_firstname(){} // validate and set first name
public function set_lastname(){} // validate and set last name
public function save_to_database(){} // save object fields to database
}
class user_controller extends controller
{
public function edit_user_form()
{
$view = new view('edit_user_form.php');
}
public function edit_user_form_submit()
{
// Load the user
$user = new user($_POST['id']);
// Was the record found in the db?
if($user->exists)
{
// Try to set these fields
if(
$user->set_firstname($_POST['firstname'])
and
$user->set_lastname($_POST['lastname'])
)
{
// No errors, save to the dabase
$user->save_to_database();
// Return success to view
echo json_encode(array('success' => true));
}
else
{
// Error, data not valid!
echo json_encode(array('success' => false));
}
}
else
{
// Error, user not found!
echo json_encode(array('success' => false));
}
}
}
?>
拯救
我意识到这两个例子做了完全相同的事情。但这样做有对有错吗?我读过很多关于瘦控制器和胖模型的书,选项1来自哪里。你是怎么处理的?谢谢,很抱歉问了这么长的问题 简而言之,您可以使用这两种方法中的任何一种,但是您应该稍微改变一下 考虑一下:模特们并不真正“了解”post、get等等。他们应该只知道他们是什么业务相关的东西-在你的情况下是一个用户 因此,虽然可以使用方法1,但不应该直接从模型访问post变量。相反,让函数获取一组参数,然后使用这些参数创建用户 通过这种方式,您可以很容易地重用代码,比如在shell脚本或其他任何地方,那里没有
$\u POST
之类的东西
虽然第二种方法在控制器中更加冗长,但您也可以这样做。然而,这种风格中更好的方法可能是使用“服务类”。服务将有一个方法,比如“createUserFromArray”,它接受一个数组并返回一个用户。同样,您可以将$\u POST
作为参数传递给此方法-类似于在modified#1中传递给函数的方式
只有控制器应直接处理输入。这是因为控制器处理请求,因此它可以知道post
tl;dr您的模型不应直接使用超全局变量,如
$\u POST
。从我的观点和我们的工作方式来看,模型将处理传递给它的数据的验证和过滤,但我们使用控制器将这些数据推送到模型内部
如上所述,模型不必知道$u POST或$u GET这些是控制器必须处理的用户输入。另一方面,模型必须处理传递给它的所有数据验证,因为您肯定不想在项目的不同代码部分反复验证数据。MVC设计模式的一个重要原因是它是保持关注点分离的好方法。视图应该忽略模型,反之亦然。控制器只是作为模型和视图之间的一种交通警察。因此,控制器应从视图中获取数据,进行所需的最小处理,以便模型能够理解数据,而无需知道视图是如何实现的(即通过HTML表单),并将其提供给模型,以便模型能够持久化数据 这使得当需要通过HTML表单以外的其他方式创建/保存/持久化项时,模型可以在其他实例中重用,而无需跨多个控制器复制项保存代码
更新:我忘了提到验证。按照与持久化数据相同的思路,控制器应该获取数据并将其传递给模型进行验证,因为模型知道它需要的数据的确切格式。如果数据无效,您可以让模型抛出异常,将验证和持久性结合起来,控制器可以根据需要捕获和处理异常(例如,呈现JSON错误响应)。也非常感谢您的输入。很高兴知道不在模型中访问全局函数…这是有道理的。关于服务类的有趣想法。您是否将服务类的功能限制为仅一种方法(即从数组创建新用户),或者添加其他功能(如从数组更新用户)是否有意义?另外,对于这两个函数,您会在数组中强制特定数量的值,还是让函数简单地处理传递给它的内容(即firstname和lastname以及另一个time用户名和密码)?一般来说,服务通常会包含与某个特定类型的模型相关的任意数量的方法。例如,您可以拥有一个用户服务,其中包含与用户模型交互的不同方法。我认为这些方法的数组可以包含任意数量的值,但您应该检查实际需要的值,如果所需值为missng,则抛出异常。如果你想查找更多信息,这个概念被称为“服务层”。一个服务层,从来没有想过!但是,在处理多个域模型时,不是通常使用服务层吗?我喜欢这个想法,但在一个典型的小型web应用程序中,这会不会有些过分呢?假设你有一个稍微复杂一点的动作,你可能会有一个只使用单一模型的服务。是的,我同意它可以在一个简单的应用程序中被过度使用——但是,在你发现你可能需要将代码复制在一起的时候,考虑将其中的一些移动到Service J可能是个好主意。