Field required, but not always - Yii2 - php

Is there a possibility for a field to be required in one form, and in the other not? I have two different forms, different models, that have one field in common, and I want it to be required in the first one, and optional in the other.

http://www.yiiframework.com/doc-2.0/guide-structure-models.html#scenarios
public function rules()
{
return [
// username, email and password are all required in "register" scenario
[['username', 'email', 'password'], 'required', 'on' => self::SCENARIO_REGISTER],
// username and password are required in "login" scenario
[['username', 'password'], 'required', 'on' => self::SCENARIO_LOGIN],
];
}

It's better to add scenarios as constants to model instead of hardcoded strings, for example:
const SCENARIO_CREATE = 'create';
Then you can use it like this:
[['email','password'], 'required', 'on' => self::SCENARIO_CREATE],
Another way is to describe it in scenarios() method:
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_CREATE] = ['email', 'password'];
return $scenarios;
}
That way you need to specify all safe attributes for each scenario for different actions.
Set scenario in the model
$model = new User;
$model->scenario = User::SCENARIO_CREATE;

Related

Larave noting save hash password in database

My need create new user in admin dashboard, this store function, but database saving string not hash, please help.
When I output via dd(), then the hash working
`
public function store(Request $request)
{
$data = $request->validate([
'name' => 'required|string',
'email' => 'required|email|unique:users',
'password' => 'required|string|min:8|confirmed'
]);
$object = new Specialist();
$object->groups = 3;
$object->password = \Hash::make($data['password']);
$object->fill(request()->all());
$object->save();
return redirect()->route('specialists.index');
}
`
Model
`class Specialist extends Model
{
// USE DATABASE TABLE users
protected $table = 'users';
// FILL COLUMNS...
protected $fillable = ['email', 'password', 'name'];
}`
$object->fill(request()->all());
This line is overwriting the password field because request()->all() includes password.
Use except() method to remove the fields that you don't need:
$object->password = \Hash::make($data['password']);
$object->fill(request()->except('password'));

add in conditional to Laravel auth

In my users table I have role field which can be filled with any of admin, driver, petugas, rental. I want to let the user with role either admin or rental login, other than that the login system will deny the user.
I try to override the credentials() method in LoginController.php like below
protected function credentials(Request $request)
{
$field = $this->field($request);
return [
$field => $request->get($this->username()),
'password' => $request->get('password'),
'role'=>['admin', 'jasa_angkutan', 'rental']
];
}
but it's not working.. I truely have no idea how to achieve the requirement.
here's a dirty hack but at least works in my case.
protected function credentials(Request $request)
{
$field = $this->field($request);
$user = \App\User::where([
$field=>$request->get($this->username())
])->whereIn('role', [
'admin', 'jasa_angkutan', 'rental'
])->first();
if($user){
return [
$field => $request->get($this->username()),
'password' => $request->get('password')
];
}
return [];
}
before pass the credentials to auth method, I, first check if the user and role match the criteria. that's it.

Laravel append rules on custom validation rule

In request I got attribute that defines validation rules and flow. Let's say it is account_type: business, personal.
Each value changes validation flow and requires different attributes to be present ir request.
Let's say I have following custom rules methods:
public function validateAccountTypeBusiness($attribute, $value, $parameters, Validator $validator)
{
// check is present:
// Company address
// VAT number
}
public function validateAccountTypePersonal($attribute, $value, $parameters, Validator $validator)
{
// check is present:
// User mobile phone
}
Since each rule requires more than single attribute to be presented in this request depending on account type ( vat number, company name, etc ) returning false would be not informative to user because generated response notices that account type is invalid without any details which actual attributes is missing.
The question is: how I can append more rules to be validated in this validation custom rule?
Following not working:
public function validateAccountTypeBusiness($attribute, $value, $parameters, Validator $validator)
{
$validator->addRules([
'company_address' => 'required|string',
'vat_number' => 'required',
]);
}
If you follow Complex Conditional Validation, you can validate using the following way
Step 1: Create Validator instance with static rules which would be same in both the cases(business or personal account) like name,check,phone,email,etc.
$v = Validator::make($data, [
'email' => 'required|email',
'name' => 'required|alpha',
'phone' => 'required|numeric',
'check' => 'required' //common in both account type
//add more rules as required
]);
Step 2: Add specific rules with condition
$v->sometimes('VAT', 'required|max:50', function ($input) {
return $input->account_type == 'business';
});
$v->sometimes('Company_address', 'required|max:500|alpha', function ($input) {
return $input->account_type == 'business';
});
$v->sometimes('user_mobile', 'required|numeric', function ($input) {
return $input->account_type == 'personal';
});
Parameters for sometimes() method :
The first argument passed to the sometimes method is the name of the
field we are conditionally validating. The second argument is the
rules we want to add. If the Closure passed as the third argument
returns true, the rules will be added.
As per my understanding, Custom validation rule can be used for only one parameter & you're trying to club them together.
This is one of many ways to approach your problem. Hope it helps.
<?php
namespace App\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class AccountController extends Controller
{
/**
* Store a new user account.
*
* #param Request $request
* #return Response
*/
public function store(Request $request)
{
if($request->input('account_type' == 'business') {
// Validation for business account
$validator = Validator::make($request->all(), [
'company_address' => 'required|string',
'vat_number' => 'required',
]);
}
else {
// Validation for personal account
$validator = Validator::make($request->all(), [
'contact_number' => 'required',
]);
}
if ($validator->fails()) {
return redirect('account/create')
->withErrors($validator)
->withInput();
}
// Store the user account...
}
}
Reference -
Manually creating validators -
https://laravel.com/docs/5.4/validation#manually-creating-validators

Yii2: ActiveForm field numeric, length => 8

I'm trying to make yii2 to validate my ActiveForm field that should be numeric and of 8 characters long.
Following is what I tried in the default LoginForm model of yii2/advanced/backend, but unfortunately the isNumeric validator simply doesn't kick in:
public function rules()
{
return [
// username and password are both required
[['username', 'password'], 'required'],
// username should be numeric
['username', 'isNumeric'],
// username should be numeric
['username', 'string', 'length'=>8],
// password is validated by validatePassword()
['password', 'validatePassword'],
];
}
/**
* Validates if the username is numeric.
* This method serves as the inline validation for username.
*
* #param string $attribute the attribute currently being validated
* #param array $params the additional name-value pairs given in the rule
*/
public function isNumeric($attribute, $params)
{
if (!is_numeric($this->username))
$this->addError($attribute, Yii::t('app', '{attribute} must be numeric', ['{attribute}'=>$attribute]));
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* #param string $attribute the attribute currently being validated
* #param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
I also tried adding a scenario as suggested in a related post (https://stackoverflow.com/a/27817221/2037924) but that only worked (as in displayed the error) if I did not include the password field in the scenario.
Is this a good way to achieve this at all, or can you think of a better way of doing it?
Note: the reason I define username as string is because the numbers may contain leading 0's.
Try with integer data type:
[['username'], 'integer'],
[['username'], 'string', 'min' => 8],
It will validate both numeric and length. This will do the trick.
Read more about the validations here: http://www.yiiframework.com/doc-2.0/guide-tutorial-core-validators.html#number
This works fine for me using the contact form from yii2-basic
/**
* #return array the validation rules.
*/
public function rules()
{
return [
// name, email, subject and body are required
[['name', 'email', 'subject', 'body'], 'required'],
// email has to be a valid email address
['email', 'email'],
['subject', 'is8NumbersOnly'],
// verifyCode needs to be entered correctly
['verifyCode', 'captcha'],
];
}
public function is8NumbersOnly($attribute)
{
if (!preg_match('/^[0-9]{8}$/', $this->$attribute)) {
$this->addError($attribute, 'must contain exactly 8 digits.');
}
}
public function rules()
{
return [
// username should be numeric
['username', 'match', 'pattern' => '/^\d{8}$/', 'message' => 'Field must contain exactly 8 digits.],
// ...
];
}
try this:
public function rules()
{
return [
// name, email, subject and body are required
[['name', 'email', 'subject', 'body'], 'required'],
// email has to be a valid email address
['email', 'email'],
[['subject'], 'number'],
[['subject'], 'string', 'max' => 8, 'min' => 8],
// verifyCode needs to be entered correctly
['verifyCode', 'captcha'],
];
}

Laravel Required Field on Model Update

I have a Users system which allows account creation, login and logout procedures.
I'm currently working on an Edit Profile, which allows editing of the full name, username etc.
For this procedure, I would like the password to be not required, however, it needs to be required for the create and login procedures.
Is there a way to support this in Laravel?
I thought about detecting the presence of an Input::get('password') and if not, passing through the original password, however, this would re-hash
So, to summarise, I would like the password field to be required on create, but not on update procedures. Alternatively, if there's another way to achieve the same end, then I'm open to it.
For reference, I'm using JeffreyWay/Laravel-Model-Validators which handles the validation within the save procedure.
Probably you cannot do this using this package. However you can create such functionality manually, for example creating 2 methods that chooses required fields for validation, a piece of User class:
protected static $rules
= [
'name' => 'required|min:3|max:60',
'password' => [
'required',
'min:10'
],
];
public static function validateRegistration($data, $translation)
{
return self::validate($data, $translation);
}
public static function validateUpdate($data, $translation)
{
$rules = self::$rules;
if (trim($data['password']) == '') {
unset($rules['password']); // unsetting unwanted password rule
}
return self::validate($data, $translation, $rules);
}
public static function validate($data, $translation, $rules = null)
{
if (is_null($rules)) {
$rules = self::$rules;
}
$v = Validator::make($data, $rules, $translation);
if ($v->fails()) {
self::$errors = $v->messages()->toArray();
return false;
}
return true;
}

Categories