I have model form (SomeForm
) and custom validation function in there:
use yii\base\Model;
class SomeForm extends Model
{
public $age;
public function custom_validation($attribute, $params){
if($this->age < 18){
$this->addError($attribute, 'Some error Text');
return true;
}
else{
return false;
}
}
public function rules(){
return [
['age', 'custom_validation']
];
}
}
I use this custom_validation
in rules()
function but form even submitting whatever value has age
attribute.
Here is the form:
age.php
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'age')->label("Age") ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
and the controller:
use yii\web\Controller;
class SomeController extends Controller
{
//this controller is just for rendering
public function actionIndex(){
return $this->render('age');
}
public function actionSubmit(){
$model = new SomeForm();
if($model->load(Yii::$app->request->post()){
//do something here
}
}
}
You don't need to return anything just adding the error to the attribute is enough.
Since version 2.0.11
you can use yii\validators\InlineValidator::addError()
for adding errors instead of using $this
. That way the error message can be formatted using yii\i18n\I18N::format()
right away.
Use {attribute}
and {value}
in the error message to refer to an attribute label (no need to get it manually) and attribute value accordingly:
What I suspect is the problem in your case is that you are missing the $formModel->validate()
as in the model given above extends the yii\base\Model
and not \yii\db\ActiveRecord
and you must be saving some other ActiveRecord
model and want to validate this FormModel
before saving the ActiveRecord
model, you have to call the $formModel->validate()
to check if valid input is provided and trigger the model validation after loading the post array to the model.
And another thing to notice is by default, inline validators will not be applied if their associated attributes receive empty inputs or if they have already failed some validation rules. If you want to make sure a rule is always applied, you may configure the skipOnEmpty
and/or skipOnError
properties to be false
in the rule declarations.
Your model should look like below you are missing the namespace
in your model definition if that is not just intentional or due to sample code. just update you namespace according to the path where it is.
namespace frontend\models;
use yii\base\Model;
class SomeForm extends Model
{
public $age;
const AGE_LIMIT=18;
public function rules(){
return [
['age', 'custom_validation','skipOnEmpty' => false, 'skipOnError' => false]
];
}
public function custom_validation($attribute, $params,$validator){
if($this->$attribute< self::AGE_LIMIT){
$validator->addError($this, $attribute, 'The value "{value}" is not acceptable for {attribute}, should be greater than '.self::AGE_LIMIT.'.');
}
}
}
your controller/action
should look like
public function actionTest()
{
//use appropriate namespace
$formModel = new \frontend\models\SomeForm();
$model= new \frontend\models\SomeActiveRecordModel();
if ($formModel->load(Yii::$app->request->post()) && $model->load(Yii::$app->request->post())) {
if ($formModel->validate()) {
// your code after validation to save other ActiveRecord model
if($model->save()){
Yii::$app->session->setFlash('success','Record added succesfully.')
}
}
}
return $this->render('test', ['model' => $model,'formModel'=>$formModel]);
}
The Input field age
in the view file should use the $formMoedl
object
echo $form->field($formModel, 'age')->textInput();