我对cakepp很陌生,但我从一开始就喜欢它。经过数小时的研究和教程,我现在觉得能够创建一个符合我要求的User::register()函数。该函数运行良好,但在某些方面我对代码不满意。由于我想确保我很好地理解cakepp的逻辑,我想问你是否有更好的方法来做这件事,或者它的代码是否很好(见评论):
public function register() {
if ($this->request->is('post')) {
//setting the data, so that it can be validated
$this->User->set($this->request->data);
//go on if no error occurs
if($this->User->validates()) {
//creatin a verification code the user has to click in the confirmation email to activate his account
//i think this is not solved very well, because i set the verification code in 2 variables.
//also: is there a better way to set the verification code to the user model than setting $this->request->data['User']['verification_code'] ?
$vcode = $this->request->data['User']['verification_code'] = sha1($this->request->data['User']['email'].rand(0,100));
//creating the record in database
$this->User->create();
//save, dont validate again
if ($this->User->save($this->request->data, array('validate' => FALSE))) {
//sending mail
$Email = new CakeEmail();
$Email->from(array('no-reply@'.$_SERVER['SERVER_NAME'] => $this->viewVars['appName']))
->to($this->request->data['User']['email'])
->subject(__('Deine Registrierung bei %s',$this->viewVars['appName']))
->template('register_confirmation','default')
->emailFormat('both')
->viewVars(array(
'appName' => $this->viewVars['appName'],
'first_name' => $this->data['User']['first_name'],
'verificationLink' => Router::url(array('controller' => 'users', 'action' => 'verifyEmail'),true).'?vcode='.$vcode //with the verification code. heres where is need the $vcode variable again.
//i thought it would be pretty ugly to write $this->request->data['User']['verification_code'] again
));
if($Email->send()) {
$this->Session->setFlash(__('Registrierung erfolgreich! Wir haben eine Bestätigungs-E-Mail an %s gesendet. Klicke auf den darinstehenden Link, um dein Konto zu aktivieren.',array('<strong>'.$this->request->data['User']['email'].'</strong>')),'flash_alert_success');
return $this->redirect(array('controller' => 'users', 'action' => 'login'));
}
$this->Session->setFlash(__('Die E-mail konnte nicht versendet werden. Fordere eine neue Bestätigungs E-Mail an.'),'flash_alert_error');
}
$this->Session->setFlash(__('Die Registrierung ist fehlgeschlagen. Bitte versuche es erneut.'),'flash_alert_error');
} else {
//ist there a better way to catch and display the validation errors?
$errmsg = __('%sDie Registrierung konnte nicht abgeschlossen werden:%s','<strong>','</strong><br />');
foreach($this->User->validationErrors as $key => $val) {
$errmsg .= __($val[0]).'<br />';
}
$this->Session->setFlash($errmsg,'flash_alert_error');
}
}
}
如有任何意见,我们将不胜感激。
提前感谢大家,oligen
体系结构
将电子邮件发送代码移动到一个单独的方法中。好的OOP意味着一个方法只做一项任务,您的注册方法也处理电子邮件发送,将其分离到另一个方法中,并从您的注册方式中调用它。为了能够更好地进行单元测试,我通常会创建一个类似的方法
public function getCakeEmail($config = null) {
return new CakeEmail($config);
}
在我的AppModel中,很容易在测试中模拟该方法,并返回一个模拟的CakeEmail对象,然后断言该方法对它的调用。
将整个数据处理逻辑移动到模型层中(显示控制器调用模型方法):
public function register() {
if ($this->request->is('post')) {
if ($this->User->register($this->request->post)) {
//...
} else {
//...
}
}
}
最佳实践:
$errmsg, $vcode
不要使用简短的变量名,这一个是可以猜测的,但通常易于阅读和理解的代码比缩短任何内容都要好。那么,为什么不称之为$errorMessage和$verficationCode呢?
if($this->User->validates()) {
if后面缺少空格,请遵循编码约定。您可以使用类似phpcs的工具来验证您的代码。
MVC违反,除非在视图层,否则您永远不希望在脚本中使用HTML。
$errmsg .= __($val[0]).'<br />';
这里甚至没有使用<br>
,使用CSS在元素之间创建空间。<br>
是换行,不被认为被滥用为创建间距的"设计元素"。不需要运行验证错误数组并添加<br>
。
如果您遵循约定,如果每个输入字段的验证规则失败,CakePHP应该自动在该字段下面显示错误消息。