下載 Laravel 驗證類
composer require illuminate/validation:~5.6
建立 Validate 類
use Illuminate\Translation\FileLoader;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Translation\Translator;
use Illuminate\Validation\Factory;
use yii\web\Controller;
use yii\base\Action;
class Validate {
protected $validator = null;
//網上抄的程式碼,獲取 Laravel Validate 例項
private function getValidator(){
if(is_null($this->validator)){
$test_translation_path = __DIR__ . '/lang';
$test_translation_locale = 'en';
$translation_file_loader = new FileLoader(new Filesystem, $test_translation_path);
$translator = new Translator($translation_file_loader, $test_translation_locale);
$this->validator = new Factory($translator);
}
return $this->validator;
}
// 使用反射獲取控制器的驗證規則
private function getRuleClass(Controller $controller,Action $action){
$reflection = new ReflectionClass($controller);
$comment = $reflection->getMethod($action->actionMethod)->getDocComment();
return Tools::getDocComment($comment, 'validator');
}
// 驗證控制器規則
public function check(Controller $controller, Action $action){
$ruleClass = $this->getRuleClass($controller,$action);
// 如果控制器沒有驗證規則,直接返回 true
if(empty($rules) || !class_exists($validator)){
return true;
}
$ruleClass = new $ruleClass;
// 獲取表單資料,GET + POST
$request = \Yii::$app->request;
$input = array_merge($request->get(), $request->post());
$rules = $ruleClass->rules();
$messages = $ruleClass->messages();
$attributes = $ruleClass->attributes();
$result = $this->getValidator()->make($input, $rules, $messages, $attributes);
// 驗證失敗丟擲 ValidateException
if ($result->fails()) {
throw new ValidateException($result->messages()->first());
}
return ture;
}
}
Tools::getDocComment
:
public static function getDocComment($comment, $tag)
{
if (empty($tag)) {
return $comment;
}
$matches = [];
preg_match("/" . $tag . "(.*)(\\r\\n|\\r|\\n)/U", $comment, $matches);
if (isset($matches[1])) {
return trim($matches[1]);
}
return '';
}
建立抽象 RuleClass 類
abstract class ValidateRules{
/**
* 驗證規則
*
* @return array
* @see https://laravel-china.org/docs/laravel/5.6/validation/1372
*/
abstract public function rules(): array;
abstract public function messages(): array;
abstract public function attributes(): array;
}
建立具體的驗證規則
class UserAddRules extends ValidateRules{
public function rules(){
return [
'username' => 'required|email',
'password' => 'required'
];
}
public function messages(){
return [
'required' => ':attribute 不能為空',
'email' => ':attribute 必須為郵箱格式'
];
}
public function attributes(){
return [
'username' => '使用者名稱',
'password' => '密碼'
];
}
}
在控制器中加入驗證
class UserController extends BaseController {
/**
* @validator app\Validate\UserAddRules
*/
public function actionAdd(){
}
}
使用註解將驗證規則加入到控制器上,@validator 填寫包含名稱空間的完整類名
在 BaseController 中全域性驗證
public function beforeAction($action)
{
try {
$validate = new Validate();
$validate->check($this, $action);
} catch (\ReflectionException $e) {
$this->responseJson(Status::SERVER_ERROR, $e->getMessage());
return false;
} catch (ValidateException $e) {
$this->responseJson(Status::BAD_REQUEST, $e->getMessage());
return false;
}
return parent::beforeAction($action);
}
結束語
之前在開發 Yii 應用時,發現框架自帶驗證是在資料入庫時進行的驗證,不太符合專案需求,然後透過搜尋發現 Laravel 驗證包可以單獨使用,嘗試一番,還是挺不錯的,在 RuleClass
中的編寫方式與 Laravel 中的 Request
類一致,只有個別需要資料庫驗證的( unique
等)不能使用,可以實現 Illuminate\Contracts\Validation\Rule
進行自定義規則。
本作品採用《CC 協議》,轉載必須註明作者和本文連結