我已经使用PHP大约一年了,但我这样做是为了一个爱好。我没有任何人可以作为老师或导师给我建议我可能做的完全错误,或者我可以做得更好。那一年里我做了很多不同的事情,所以我不认为自己是一个完整的菜鸟。
无论如何,我刚刚开始使用一个框架(Kohana),那里确实没有很多教程,所以我不能完全确定我是否做得很好。
我想发布一些代码片段,以获得一些与我刚才所说的相关的反馈。
初学者
class User_Controller extends Template_Controller{
public function register()
{
// logged in users cant register
if($this->logged_in)
{
url::redirect('user/profile');
}
// initially show an empty form
$form = $errors = array
(
'username' => '',
'email' => '',
'password' => '',
'gender' => '',
'dob_month' => '',
'dob_day' => '',
'dob_year' => '',
'date_of_birth' => '',
'captcha' => '',
'registration' => ''
);
// check for a form submission
if($this->input->post('register'))
{
// get the form
$post = $this->input->post();
// prepare the data for validation
$post['date_of_birth'] = "{$post['dob_year']}-{$post['dob_month']}-{$post['dob_day']}";
// create a new user
$user = ORM::factory('user');
// validate and register the user.
if($user->register($post, TRUE))
{
// SEND EMAIL
// login using the collected data
if(Auth::instance()->login($post->username, $post->password, TRUE))
{
// redirect the user to the profile page
//url::redirect("user/profile/{$user->id}");
}
}
// get validation errors and repopulate the form
$form = arr::overwrite($form, $post->as_array());
$errors = arr::overwrite($errors, $post->errors('registration_errors'));
}
// template variables
$this->template->title = 'Sign Up';
$this->template->body = new View('layout_1');
// layout variables
$this->template->body->left = new View('user/registration_form');
$this->template->body->right = 'Right Side Content';
// registration form variables
$this->template->body->left->form = $form;
$this->template->body->left->errors = $errors;
$this->template->body->left->captcha = new Captcha('register');
}
}
class User_Model extends ORM{
public function register(array& $user, $save = FALSE)
{
$user = new Validation($user);
// logged in users cant register
if(Auth::instance()->logged_in())
{
$user->add_error('registration', 'logged_in');
return FALSE;
}
// trim everything
$user->pre_filter('trim')
// everything is required
->add_rules('*', 'required')
// username must be 5 - 30 alphanumeric characters and available
->add_rules('username', 'length[5,30]', 'valid::alpha_numeric', array($this, 'username_available'))
// email must be valid format and available
->add_rules('email', 'valid::email', array($this, 'email_available'))
// password must be 5 - 15 characters and alpha dash
->add_rules('password', 'length[5,15]', 'valid::alpha_dash')
// gender must be either male or female. capitalize first letter
->add_rules('gender', array($this, 'valid_gender'))
->post_filter('ucfirst', 'gender')
// dob must be a valid date, and user must be old enough.
->add_callbacks('date_of_birth', array($this, 'check_dob'))
// captcha must be entered correctly.
->add_rules('captcha', 'Captcha::valid');
// add the registration date
$this->registration_date = date::unix2mysql(); // helper function transforms the current unix to mysql datetime format
// validate the information. an ORM function.
$result = parent::validate($user, $save);
// was the user info valid?
if($result === TRUE)
{
// was the user saved?
if($save === TRUE)
{
// add a login role
$this->add(ORM::factory('role', 'login'));
$this->save();
}
}
else
{
$user->add_error('registration', 'failed');
}
return $result;
}
}
在验证信息时,我的所有模型大多采用相同的格式。
我还有其他一些我会很感激的反馈意见,但我不想压倒任何人。
编辑:对不起,我应该发布用户控制器和型号。我一直在阅读很多关于模型应该如何变胖的信息,控制器应该是瘦的。这就是为什么我在模型中创建一个寄存器功能来验证信息而不是在控制器中这样做。 register函数接受一个数组,但将该数组转换为验证对象,以便我可以检索用户输入和错误。我已经在Kohana上看到了一些关于这样做的教程。
答案 0 :(得分:3)
首先,我不会将register()方法放入User模型中。模型应该是数据库中对象的表示,通常只包含“CRUD”方法(创建,检索,更新,删除),getter和setter方法,以及一些与模型相关的静态帮助方法。通过将register()方法放入模型中,您可以使模型执行应该由用户控制器完成的表示逻辑,因为这是对用户操作的响应。控制器处理用户操作,验证这些用户操作,然后在验证成功时更新模型。
在您的示例中,用户正在尝试创建新帐户。他填写表格并点击提交。表单的POST操作应指向控制器的方法,如/ user / register,该方法将使用Validation库来验证用户发送的表单数据。只有当数据成功验证时,才应创建用户模型实例,将该模型的属性设置为用户输入的属性,然后使用模型的save()方法保存到数据库。如果验证失败,您将向用户报告错误,并且您根本没有创建用户模型,因为您还没有有效的数据集来创建模型。
接下来,您正在检查用户是否已登录。再次,这应该在控制器中,而不是模型中。除此之外,如果用户已经登录,则用户不应该首先进入此注册过程。创建用户注册表单视图的控制器方法应该检查用户是否已登录,如果他是,然后他应该被重定向到另一页。即使用户正在玩弄技巧并设法提交表单(也许他在旧窗口中打开表单时通过另一个窗口登录),您的注册方法应首先检查该表单,而不是创建$ user验证对象。
我可以在您的代码中看到根据您的模型设置存在一些令人困惑的项目。例如,您将$ user数组传递给方法,我认为该方法是表单数据。但是你使用的是“按引用传递”操作符(&),这在PHP5中是不必要的,因为所有对象现在都通过引用传递。但之后你将$ user重新作为Validation对象。您是否在其他地方使用$ user Validation对象并要求通过引用传递它?如果是这样,这是逻辑中的另一个缺陷,因为所有这些处理都需要在控制器中,并且$ _POST值可以直接在控制器中使用,而不必传递Validation对象。
稍后,您将使用parent :: validate($ user,$ save)验证用户信息。为什么在父类上调用validate()方法作为静态方法?如果这是一个模型,它应该扩展Kohana的核心Model类,而“parent”引用Model类。您的模型是否扩展了Validation类?另外,为什么要将$ user Validation对象传递给validation()方法?如果您需要进行递归(在从先前的过滤器进行更改后再次验证元素),则需要执行此操作,但看起来您没有做任何要求递归的操作。您应该在$ user Validation对象上调用validate():
$user->validate();
没有任何参数。验证错误将成为$ user对象的一部分,因此您可以使用
检查错误$user->errors();
最后,虽然Kohana允许您使用方法链接,但我不会使用一个长链来设置规则和其他项目以进行验证。这令人困惑,可能导致调试困难。将其中的每一个放在自己的行上,并直接在$ user对象上执行每个。
答案 1 :(得分:1)
我不知道Kohanna所以我不确定他们的MVC分离的土地是什么,但通常我会在控制器上进行register
动作。我在你的代码中引发的主要问题是模型内部与身份验证系统耦合。验证检查应在类外部进行,控制流决策也应在外部进行,或者验证检查的结果应传递给模型以供其内部操作使用。
通常情况下,我可能会执行以下伪代码:
// in my controller class for User or whatever
public function registerAction()
{
// get the form data from the request if its POST, ortherwise a blank array
$userData = $this->getRequest('user', array(), 'POST');
// create a user
$user = new User($userData);
if(Auth::instance()->logged_in())
{
// we are logged in add an error to the user object for use by the view
$user->getValidator()->add_error('registration', 'logged_in');
}
elseif($user->is_valid())
{
// user data is valid, set the view with the success message
$user->save();
$this->setView('register_success');
}
/**
* render the designated view, by default this would be the one containing the
* registration form which displays errors if they exist - however if we success-
* fully registered then the view with the success message we set above will be
* displayed.
*/
$this->render();
}