在我的表单模型中,我有一个以这种方式定义的字段的自定义验证函数
class SignupForm extends Model
{
public function rules()
{
return [
['birth_date', 'checkDateFormat'],
// other rules
];
}
public function checkDateFormat($attribute, $params)
{
// no real check at the moment to be sure that the error is triggered
$this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
}
}
当我按下提交按钮时,错误消息不会显示在表单视图中的字段下,而其他规则(如所需的电子邮件和密码)会出现。
我正在处理注册本机表单,因此为了确保它不是归档问题,我设置了规则
['username', 'checkDateFormat']
并删除了与用户名字段相关的所有其他规则,但该消息也没有显示。
我尝试过不将任何参数传递给checkDateFormat
,我尝试将字段的名称显式传递给addError()
$this->addError('username', '....');
但什么也没出现。
设置自定义验证函数的正确方法是什么?
你读过文档吗?
根据上述验证步骤,属性将是 验证当且仅当它是在 中声明的活动属性 scenario() 并与一个或多个活动规则相关联 在规则()中声明。
因此,您的代码应如下所示:
class SignupForm extends Model
{
public function rules()
{
return [
['birth_date', 'checkDateFormat'],
// other rules
];
}
public function scenarios()
{
$scenarios = [
'some_scenario' => ['birth_date'],
];
return array_merge(parent::scenarios(), $scenarios);
}
public function checkDateFormat($attribute, $params)
{
// no real check at the moment to be sure that the error is triggered
$this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
}
}
在控制器集场景中,示例:
$signupForm = new SignupForm(['scenario' => 'some_scenario']);
尝试对空字段强制验证
['birth_date', 'checkDateFormat', 'skipOnEmpty' => false, 'skipOnError' => false],
此外,请确保不要为视图中的birth_date
字段分配 id。
如果您有 birth_date
的 id,则需要指定selectors
<?= $form->field($model, 'birth_date', ['selectors' => ['input' => '#myBirthDate']])->textInput(['id' => 'myBirthDate']) ?>
要在 yii 2 中进行自定义验证,您可以在模型中编写自定义函数并在规则中分配该函数。例如。我必须在password
字段中应用密码条件,然后我将在模型中这样写。
public function rules()
{
return [
['new_password','passwordCriteria'],
];
}
public function passwordCriteria()
{
if(!empty($this->new_password)){
if(strlen($this->new_password)<8){
$this->addError('new_password','Password must contains eight letters one digit and one character.');
}
else{
if(!preg_match('/[0-9]/',$this->new_password)){
$this->addError('new_password','Password must contain one digit.');
}
if(!preg_match('/[a-zA-Z]/', $this->new_password)){
$this->addError('new_password','Password must contain one character.');
}
}
}
}
如果要从类模型扩展,则需要在某处触发$model->validate()
。
我在使用 CRUD 生成器时偶然发现了这个。生成的 actionCreate() 函数不包含模型验证调用,因此永远不会调用自定义验证器。此外,_form不包括和错误摘要。
因此,将错误摘要添加到_form。
<?= $form->errorSummary($model); ?>
。并将验证调用 - $model->validate() - 添加到控制器操作
public function actionCreate()
{
$model = new YourModel();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {...
虽然这是一个旧帖子,但我认为我应该回答。
您应该创建一个自定义验证程序类,并且要创建一个支持客户端验证的验证程序,您应该实现 yiivalidatorsValidator::clientValidateAttribute()
方法,该方法返回一段在客户端执行验证的 JavaScript 代码。在 JavaScript 代码中。
您可以使用以下预定义变量:
attribute:
要验证的属性的名称。
value:
正在验证的值。
messages:
用于保存 的验证错误消息的数组 属性。
deferred:
可以将延迟对象推入的数组 (在下一小节中解释)。
因此,这意味着您可以使用messages
数组在此方法的 javascript 代码块中运行时将消息推送到客户端。
我将创建一个包含虚拟支票的类,这些检查可以按照您希望的方式替换。 并根据您的 yii2 advanced
或basic
更改namespace
。
Custom Client-side Validator
namespace commoncomponents;
use yiivalidatorsValidator;
class DateFormatValidator extends Validator{
public function init() {
parent::init ();
$this->message = 'You entered an invalid date format.';
}
public function validateAttribute( $model , $attribute ) {
if ( /*SOME CONDITION TO CHECK*/) {
$model->addError ( $attribute , $this->message );
}
}
public function clientValidateAttribute( $model , $attribute , $view ) {
$message = json_encode ( $this->message , JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
return <<<JS
if ($("#DATE-1").val()=="" || $("#DATE-2").val() =="") {
messages.push($message);
}
JS;
}
}
然后在模型中SigupForm
添加rule
['birth_date', 'commoncomponentsDateFormatValidator'],
Deferred Validation
您甚至可以在 clientValidateAttribute
函数中添加 ajax 调用,并且基于该 ajax 调用的结果,您可以将消息推送到客户端,但您可以使用 yii 提供的 deferred
对象,它是一个延迟对象数组,您可以在该数组中推送调用或显式创建延迟对象并调用其 resolve()
方法。
Default Yii's deferred Object
public function clientValidateAttribute($model, $attribute, $view)
{
return <<<JS
deferred.push($.get("/check", {value: value}).done(function(data) {
if ('' !== data) {
messages.push(data);
}
}));
JS;
}
关于Deferred Validation
您需要从控制器渲染模型。无需初始化视图中的模型。在控制器中,您需要调用验证函数
你确定addError
的第一个参数不应该是这样的吗
$this->addError(**'attribute'**, Yii::t('user', 'You entered an invalid date format.'));
我遇到了常见问题。
在验证函数中:
public function checkDateFormat($attribute, $params)
{
// no real check at the moment to be sure that the error is triggered
$this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
}
$params根本没有任何价值。它实际上总是等于 Null。您必须在函数中检查属性值:
public function checkDateFormat($attribute, $params)
{
if($this->birth_date == False)
{
$this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
}
}
这就是它对我的工作方式。
如果不对模型使用方案,则必须将致敬标记为"安全":
['birth_date','safe'],
['birth_date', 'checkDateFormat'],
另一方面,您可以使用它进行日期验证:
['birth_date','safe'],
[['birth_date'],'date', 'format'=>'php:Y-m-d'],
您可以根据需要更改格式。
**我们应该为函数设置属性以使用输入值 **
public function rules()
{
return [
['social_id','passwordCriteria'],
];
}
public function passwordCriteria($attribute, $params)
{
if(!empty($this->$attribute)){
$input_value = $this->$attribute;
//all good
}else{
//Error empty value
$this->addError('social_id','Error - value is empty');
}
}
您是否有机会使用客户端验证?如果你这样做,那么你必须编写一个javascript函数来验证输入。你可以在这里看到他们是如何做到的:
http://www.yiiframework.com/doc-2.0/guide-input-validation.html#conditional-validation
另一种解决方案是禁用客户端验证,使用 ajax 验证,这也应该带回错误。
还要确保你没有覆盖输入的模板,这意味着如果你覆盖了它,请确保你仍然有{error}。
你对规则的语法应该是这样的人,
[['birth_date'], 'checkDateFormat']
不是这个
['birth_date', 'checkDateFormat']
所以在你的例子中,它应该看起来像下面
...
class SignupForm extends Model
{
public function rules()
{
// Notice the different with your previous code here
return [
[['birth_date'], 'checkDateFormat'],
// other rules
];
}
public function checkDateFormat($attribute, $params)
{
// no real check at the moment to be sure that the error is triggered
$this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
}
}