註冊表單需即時檢查用戶名/郵箱是否已被佔用,Yii 2.0 內建 yii\bootstrap\ActiveForm 支援 AJAX 驗證,配合模型規則極簡實現。
use yii\helpers\Html; use yii\bootstrap\ActiveForm; /* @var $model frontend\models\SignupForm */ $this->title = '註冊'; $this->params['breadcrumbs'][] = $this->title; ?>= Html::encode($this->title) ?>
'form-signup', 'enableAjaxValidation' => true, // 關鍵:開啟 AJAX 'enableClientValidation' => true, // 同時啟用客戶端 ]); ?> = $form->field($model, 'username') ?> = $form->field($model, 'email') ?> = $form->field($model, 'password')->passwordInput() ?> = $form->field($model, 'password_compare')->passwordInput() ?>= Html::submitButton('註冊', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
public function actionSignup() {
$model = new SignupForm();
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model); // 直接返回驗證結果 JSON
}
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->render('signup', ['model' => $model]);
}
namespace frontend\models;
use common\models\User;
use yii\base\Model;
use Yii;
class SignupForm extends Model {
public $username;
public $email;
public $password;
public $password_compare;
public function rules() {
return [
['username', 'filter', 'filter' => 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => User::class, 'message' => '用戶名已存在。'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'filter', 'filter' => 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'unique', 'targetClass' => User::class, 'message' => '郵箱已存在。'],
[['password', 'password_compare'], 'required'],
[['password', 'password_compare'], 'string', 'min' => 6, 'max' => 16],
['password_compare', 'compare', 'compareAttribute' => 'password', 'message' => '兩次密碼不一致'],
];
}
public function signup() {
if (!$this->validate()) return null;
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
return $user->save() ? $user : null;
}
}
public function setPassword($password) {
$this->password_hash = Yii::$app->getSecurity()->generatePasswordHash($password);
}
public function generateAuthKey() {
$this->auth_key = Yii::$app->getSecurity()->generateRandomString();
}
public function validatePassword($password) {
return Yii::$app->getSecurity()->validatePassword($password, $this->password_hash);
}
/site/signup(含字段值){"username":["用戶名已存在。"]} 或 []若不想混在 actionSignup,可建立 actionValidate:
public function actionValidate() {
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = Response::FORMAT_JSON;
$model = new SignupForm();
$model->load(Yii::$app->request->post());
return ActiveForm::validate($model);
}
}
視圖改為:'validationUrl' => ['site/validate'](ActiveForm 選項)。
Yii 2.0 實現「用戶名/郵箱唯一性 AJAX 驗證」只需三步:視圖開啟 enableAjaxValidation、控制器返回 ActiveForm::validate()、模型加 unique 規則。零 JS 手寫,體驗流暢。