Custom validation in yii2 while merging two public variables - php

Actually I'm working on ajax validation in Yii 2. I am sending two public variables data into a column in DB. while loading a post values. How to validate custom onto that field.
My Code:
public $prefix;
public $mobile;
$model->phone = Yii::$app->request->post('prefix') . '' . Yii::$app->request->post('mobile');
and I want this
['phone, 'unique']
Thanks in advance

Add the rule to the class definition of the model, validate and do with the validation result what you want. E.g. return true when validated true or the error message when validated false.
class YourModel extends ActiveRecord {
public function rules()
{
return [
['phone', 'unique'],
];
}
}
$model->validate();
If you have more validation rules you can get the result for the phone attribute using $model->getErrors('phone').

You need to merge both variables before calling validate function on model.
Your controller action code should be like below :
$model->phone=model->prefix.$model->mobile;
$model->validate();
//rest of code

Related

Newbie question about controller and request in Laravel in my case

I am new in Laravel, what I try to achieve is very simple thing, I would like to use FormRequest provided by Laravel to do validation of the request, but I encounter some puzzles (which I am sure is easy things to solve if you are experienced in Laravel).
Here is what I tried:
I have route maps to controller:
Route::put('user/{name}', 'UserController#show');
I can get the name parameter in show function:
class UserController {
public function show($name)
{
// validtion rules to apply
...
}
}
I have validation rules to apply to the request, so I decided to create form request by php artisan make:request ShowRequest, which creates the form request class:
class ShowRequest extends FormRequest {
public function authorize()
{
return true;
}
public function rules()
{
return [
// my validation rules here
];
}
}
Since I have above request class, so I refactored the show function in controller to receive the ShowRequest .
class UserController {
public function show(ShowRequest $request)
{
// now I don't need validtion rules in this function
// but how can I access the 'name' parameter now
...
}
}
I have two questions to ask:
Inside the refactored show function, how can I now access the route parameter name ?
If we forget about the parameter is a name (please don't focus on what to validate for name, imaging it is an object or value to validate in general). How to add custom logic for handling validation error instead of using Laravel default behaviour. I want to inject code like dummy code below:
if (!$validator->pass())
{
//my custom code for handling validation failure
}
Where to put my custom code for handling validation error now? I mean I don't know where to have this logic, in controller? in the request class? how?
You still can add the parameter $name in the show() method of your controller as it's part of the routed url more than the validated form/data. (recommanded)
class UserController {
public function show(ShowRequest $request, $name)
{
//...
}
}
You can also access it from the request object
class UserController {
public function show(ShowRequest $request)
{
$request->input('name');
}
}
As for the error messages (not the exception) you can add the messages() method to your ShowRequest::class
class ShowRequest extends FormRequest
{
/**
* #return array
*/
public function messages()
{
return [
'name.required' => 'The name is required',
'name.numeric' => 'The name must be a number',
//...
];
}
}
If you instead need to validate that the name catched by the route is only composed of letter OR really exists as a field in your DB (like a slug of a post) you need to add some validation in your route declaration.
Setup a route that catches request only if it is composed of letters.
Route::get('/user/{name}', 'Controller#show')->where(['name' => '[a-z]+']);
Setup a route that catches request only if the "name" exists in DB:
User.php
Class User //..
{
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'name';
}
}
web.php
//
Route::get('/user/{user:name}', 'Controller#show');
And adapt your controller to take a user directly
class UserController {
public function show(ShowRequest $request, User $user)
{
//...
}
}
You can access the values of the Form Request using this
$validated = $request->validated();
The $validated will have all the values which had been validated by the FormRequest.
To answer your second question, if you want to throw custom validation, you can always use the following
throw ValidationException::withMessages(['name' => 'Something is wrong']);

How to pass the entity id to the unique validation in a Form Request on Laravel 5.5?

I have the following route defined:
Route::put('/{organisationId}', 'OrganisationController#update');
And I have the following FormRequest for the update request:
<?php
namespace App\Http\Requests\Organisation;
use Illuminate\Foundation\Http\FormRequest;
class UpdateOrganisationRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'required|min:3|max:60|unique:organisations,name,' . $this->get('organisationId')
];
}
}
And I am trying to use it like this in my controller:
public function update($organisationId, UpdateOrganisationRequest $request)
{
$organisation = $this->organisationRepository->byId($organisationId);
if (!$organisation) {
return $this->error('Organisation not found.', $this::Bad_Request);
}
$this->organisationRepository->update($organisation, $request->validated());
return $this->success(
fractal($organisation, new OrganisationTransformer())
);
}
This appears to trigger the unique validation error, because it doesn't appear to exclude the id I am trying to update.
Any ideas why this isn't working?
Before using FormRequest, this is how I implemented the same functionality above and it was working fine:
https://pastebin.com/raw/CDEg6qLt
I was able to update the same organisation with the same name and the unique validation rule didn't trigger an Validation exception.
All rules defined in a FormRequest's rules method should be in form of a key / value pair that corresponds to an input name and it's validation rule respectively. You missed key here so chances are validator looks for a field named 0 that doesn't exist.
Add name and test result:
return [ 'name' => '....' ];

How to update only a group of fields present in FormRequest rules and ignore rest in laravel 5?

Same table with 2 request files which fills some group of fields respectively
public function update_f1(F1Request $request){
$projecttable->fill($request->all());
$projecttable->save();
}
Another one
public function update_f2(F2Request $request){
$projecttable->fill($request->all());
$projecttable->save();
}
Say f1 fills field_abc1 which is validated in F1Request.
f2 fills field_abc2 which is validated in F2Request.
Now if f2 is called it should fill only field_abc2
and not field_abc1 because its not validated in F2Request even if its fillable. Anyone can add field_abc1 from developers tools.
Yes I can do individually like
$projecttable->field_abc2 = $request->field_abc2
But its better to use fill for large number of fields
$project->fill($request->all())
In short fill only those fields which are present in Request rules and ignore all others even if fillable
You can filter these fields in Your Requests with replace() method.
Like this:
class F1Request extends Request
{
private $rules = [
/* rules goes here */
]
public function authorize()
{
return true;
}
public function rules()
{
$this->filter();
return $this->rules;
}
public function filter()
{
$input = array_intersect_key($this->all(), $this->rules);
$this->replace($input);
}
}
If it's common case, than even move filter() method to Request class.
Works Perfectly :)
public function update_f1(F1Request $request){
$rules = $request->rules();
$validfieldsgroup = array_keys($rules);
$projecttable->fill($request->only($validfieldsgroup));
$projecttable->save();
}
I think what you want is to use
$request->only($request->rules);
where $rules is the array with fields, instead of $request->all();
Source: http://laravel.com/docs/5.0/requests#retrieving-input

Yii Validate an un-bound Variable (non-stored)

Classic problem:
verify that a user accepted the contract terms but the value of the acceptance is not stored (bound) in the database...
Extend CFormModel rather than CActiveForm (because CActiveForm binds
values to DB)
Post a CFormModel to a controller action
Validate a CFormModel
I'm asking this question to answer it because the existing questions end in see the documentation...
extend CFormModle, define the rules and got to validate. With bound variables you validated as part of save. Now you validate() by itself but Validate requires a list of attributes which is not defined in CFormModel. So, what do you do? You do this:
$contract->validate($contract->attributeNames())
Here's the full example:
class Contract extends CFormModel
{
...
public $agree = false;
...
public function rules()
{
return array(
array('agree', 'required', 'requiredValue' => 1, 'message' => 'You must accept term to use our service'),
);
}
public function attributeLabels()
{
return array(
'agree'=>' I accept the contract terms'
);
}
}
Then in the controller you do this:
public function actionAgree(){
$contract = new Contract;
if(isset($_POST['Contract'])){
//$contract->attributes=$_POST['Contract']; //contract attributes not defined in CFormModel
...
$contract->agree = $_POST['Contract']['agree'];
...
}
if(!$contract->validate($contract->attributeNames())){
//re-render the form here and it will show up with validation errors marked!
}
The results:

validate() returns false but getErrors() returns an empty array - Yii

I am building a yii application. Heres the code -:
$id = 2;
$model = Page::model()->findByPk(2);
$model->title = 'HeyMan';
if($model->validate())
{
echo 'Validation retuned true';
}
else
{
$array = $model->getErrors();
$message = 'Validation returned false';
}
And the result is that the validate() returns false while getErrors() returns an empty array. Whats the problem here ? Thanks
Did you use the beforeSave function in your model? Then make sure to return the parent beforeSave:
return parent::beforeSave();
Posible solutions:
Input does not validate. The rules array in your model if configured
in order to validate input. It could theoretically be possible that
title is set to be integer only or something like that. You should
look into what rules you have set.
Model issues. This is more likely because you don't get any errors. All functions in the model must return true otherwise you will get these kind of issues. As far as as return parent::beforeSave() goes, you need to return that because your model extends CActiveRecord and when you create beforeSave() or beforeValidate() or afterSave() you are overriding those methods.
I had the same problem.In the controller after form submitting validate() returns false while getErrors() returns an empty array. I used beforeSave() method in the model the wrong way. When I fixed the usage of beforeSave() the validatin and model saving started working the normal way.
The solution for me was:
// in the model class
public function beforeSave($insert)
{
// some code here ...
return parent::beforeSave($insert);
}
Not only calling the return parent::beforeSave(); ,
but calling with the $insert parameter
like this: return parent::beforeSave($insert);

Categories