yii2 validation rules on update - php

I have a model and validation rules for it:
class User extends ActiveRecord implements IdentityInterface
{
...
public function rules()
{
return [
[['username', 'password', 'email'], 'required', 'on' => 'insert'],
[['password', 'email'], 'required', 'on' => 'update'],
]
}
Actually the code produces no validators. When I remove 'on' section, everything goes well.
Digging in official documentation and search thru The Web didn't help me to understand what is the issue, and why can't I have custom required fields sets for different actions.

The Scenario is not automaticaly setted by Yii2 ActiveReccoed. If you need a specific scenario you must create it and assign
E.g. for update ...
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['update'] = ['password', 'email'];//Scenario Values Only Accepted
return $scenarios;
}
Also you can set scenario in your actionUpdate
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->scenario = 'update';
........
}

Related

yii2 - SQLSTATE[23000]: Integrity constraint violation: 1048

I'm new to yii2, I'm trying to send a request to the database, but it comes out that such columns cannot be null, although when checking through #var_dump I can see the sending data, what is the matter and how to fix it
---> Controller
public function actionSignup()
{
$model = new Signup();
if (isset($_POST['Signup'])) {
$model->attributes = Yii::$app->request->post('Signup');
if ($model->validate()) {
$model->signup();
# code...
}
}
return $this->render('signup', ['model'=>$model]);
---> View page
<?php
use \yii\widgets\ActiveForm;
?>
<?php
$form = ActiveForm::begin(['class'=>'form-horizontal']);
?>
<?= $form->field($model,'email')->textInput(['autofocus'=>true]) ?>
<?= $form->field($model,'password')->passwordInput() ?>
<div>
<button type="submit" class="btn primary-btn">Submit</button>
</div>
<?php
ActiveForm::end();
?>
---> Model
class Signup extends Model
{
public $email;
public $password;
public function reles()
{
return [
[['email', 'password'], 'required'],
['email', 'email'],
['email', 'unique', 'targetClass'=>'app\models\User'],
['password', 'string', 'min'=>2,'max'=>10]
];
}
public function signup()
{
$user = new User();
$user->email = $this->email;
$user->password = $this->password;
return $user->save();
}
---> phpmyadmin database
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord
{
}
--> var_dump
--> sql
Try this:
**
* Signs user up.
*
* #return mixed
*/
public function actionSignup()
{
$model = new SignupForm()
//Sign up if it is post request
if ($model->load(Yii::$app->request->post()) && $model->signup()) { //Here YOU LOAD your POST data in to the Lodal using load() method.
Yii::$app->session->setFlash('success', 'Thank you for registration. Please check your email for further instructions.', false);
return $this->goHome();
} else {
Yii::$app->session->setFlash('success', 'Sorry, you can not register right now.', false);
return $this->redirect('/login');
}
}
In Model
First of all, the method for attribute rules is called "rules" I don't know if it's a typo from you in the question or this is the problem; If there are no rules for user input data the returned values will be NULL, I have faced this issue before, I didn't include a rules() method (or in your case it's name is not correct) and the model returned null for attribute values. Your code have to be:
public function rules()
{
return [
[['email', 'password'], 'required'],
['email', 'email'],
['email', 'unique', 'targetClass'=>'app\models\User'],
['password', 'string', 'min'=>2,'max'=>10]
];
}
Technical note: normally, or based upon my understanding a password should have a minimum of 8 not 2 characters, if the password entered is only 2 characters it can be brute-forced in a second.
In Controller
As in #Serghei Leonenco's Answer, Yii2 already provides some functions to use to handle post requests and so, so please stick to Yii2 functions it can enhance your app security
So in the actionSignup() method the code ought to be
public function actionSignup()
{
$model = new Signup();
// Loads the post request directly onto the model and validates it against the model rules() method
if($model->load(Yii::$app->request->post()) && $model->validate){
$model->signup();
// Model validated and saved successfully, IT OUGHT TO BE SAVED IN THE DATABASE AT THIS POINT
// Here you can set a flash or redirect the user to another page
}
return $this->render('signup', ['model'=>$model]);
}
In View
At last, in your view code it's better to use Yii2 internal functions for Html buttons
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary']) ?>
Of course don't forget to use yii\helpers\Html
use yii\helpers\Html;

Validation for form

Please help with setting rules (). The thing is, I have a form. Where 2 fields are present. If all fields are empty, the form cannot be submitted, but if at least ONE is not empty, then the form can be submitted. Can you help me please, I'm new at it?
Here's my form
<?php $form = ActiveForm::begin() ?>
$form->field($model, 'field1')->textInput();
$form->field($model, 'field2')->textInput();
<?php $form = ActiveForm::end() ?>
And this's my model, but this rule does not quite suit me. Because the rules require you to fill in all the fields. And the main thing for me is that at least one, but was filled, so i could send the form. If ALL fields are empty, then validation fails.
public function rules()
{
return [
[['field1', 'field1'], 'require'] ]}
Should I add something in controller maybe?
You have TYPO in rules: use required
public function rules()
{
return [
[['field1', 'field1'], 'required']
];
}
You can use yii\validators\Validator::when property to decide whether the rule should or shouldn't be applied.
public function rules()
{
return [
[['field1'], 'required', 'when' => function ($model) {
return empty($model->field2);
}]
[['field2'], 'required', 'when' => function ($model) {
return empty($model->field1);
}]
];
}
The when property is expecting a callable that returns true if the rule should be applied. If you are using a client side validation you might also need to set up the yii\validators\Validator::whenClient property.
You can use standalone validation:
public function rules()
{
return [
[['field1', 'field2'], MyValidator::className()],
];
}
And create a new class like follows:
namespace app\components;
use yii\validators\Validator;
class MyValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
if (empty($model->filed1) and empty($model->field2)) {
$this->addError($model, $attribute, 'some message');
}
}
}

Override Backpack validation roles

What I did:
I am trying to override backpack form validation roles (update request).
UserUpdateCrudRequest.php
use App\Http\Requests\Backpack\PermissionManager\UserUpdateCrudRequest as UpdateRequest;
class UserUpdateCrudRequest extends \Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest
{
function __construct()
{
parent::__construct();
}
public function authorize()
{
// only allow updates if the user is logged in
return \Auth::check();
}
public function rules()
{
$rules = [
'name' => 'required',
'password' => 'confirmed',
];
return $rules;
}
}
app/Http/Controllers/Admin/Backpack/PermissionManager/UserCrudController.php
public function update(UpdateRequest $request)
{
//code
}
What I expected to happen:
The email field is mandatory on create , and not mandatory on update.
What happened:
ErrorException in UserCrudController.php line 18:
Declaration of App\Http\Controllers\Admin\Backpack\PermissionManager\UserCrudController::update() should be compatible with Backpack\PermissionManager\app\Http\Controllers\UserCrudController::update(Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest $request)
If I'm right,
inside UserCrudController you have,
use Backpack\PermissionManager\app\Http\Requests\UserStoreCrudRequest as StoreRequest;
use Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest as UpdateRequest;
If you want to make the email field not mandatory on update you have to edit the UserUpdateCrudRequest.php inside your-project/vendor/backpack/permissionmanager/src/app/Http/Requests and remove the line
'email' => 'required',

Save value of checkboxlist to db in yii2

I have a yii2 form which contain a checkbox list items which i made like this:
<?php $CheckList = ["users" => 'Users', "attendance" => 'Attendance', "leave" => 'Leave', "payroll" => 'Payroll'];?>
<?= $form->field($model, 'MenuID')->checkboxList($CheckList,['separator'=>'<br/>']) ?>
Now what i need is to save the values in the database column as a comma separated value.
I tried to modify the create function in my controller in this way:
public function actionCreate()
{
$model = new Role();
if ($model->load(Yii::$app->request->post())) {
if ($model->MenuID != " ") {
$model->MenuID = implode(",", $model->MenuID);
}
$model->save();
return $this->redirect(['view', 'id' => $model->RoleID]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
But the values are not being saved in the database
You need to set your model rules().
When you call $model->load(Yii::$app->request->post()); the framework call method setAttributes() with param $safeOnly = true. This method with param $safe = true check if attributes are safe or not according to the rules of model. If you haven't any rules on the model all attributes are considered unsafe so your model is not populated.
Add rules() on your model and your code works
class Role extends yii\db\ActiveRecord
{
...
public function rules()
{
return [
['MenuID', 'your-validation-rule'],
];
}
...
Some additional info
N.B. If you do not specify scenario in the rules the default scenario is 'default' and if during instantiate of model object you set scenario to another didn't work. My example:
You have the same rules as I wrote before and you run this code
...
$model = new Role(['scenario' => 'insert']);
if ($model->load(Yii::$app->request->post())) {
...
model is empty after load becouse any rules is founded in 'insert' scenario and your problem is back. So if you want a rule that work only in particular scenario you must add 'on' rules definition. Like this:
...
public function rules()
{
return [
['MenuID', 'your-validation-rule', 'on' => 'insert'],
];
}
...
For more example and explanations visit:
Declaring Rules
load()
setAttributes()
safeAttributes()

Rules Scenario on model based action and parameter

Is it possible to create customize rule for a model in Yii2 with
name of action and its parameter.
I know that rules in model can create by on action.
Because I have a model and controller like this :
Model
public function rules()
{
$rules = [
[['pre_approved_by', 'pre_approved_date'], 'required', 'on' => 'pre'],
[['first_approved_by', 'first_approved_date'], 'required', 'on' => 'first'],
];
return $rules;
}
Controller
public function acctionApprove($hierarchy, $id){
$model = $this->findModel($id);
if($hierarchy != 1){
$model->scenario = "pre";
}else{
$model->scenario = "first";
}
}
Please advise
You can create a conditional validation. With this kind of rule you can write your own function.
For example:
['state', 'required', 'when' => function($model) {
return $model->country == 'USA';
}]
For a detailed explaination, check out the official doc

Categories