Yii validation rules for an array - php

Is there a way to require an array of elements in the rules() method of a Yii model?
For example:
public function rules()
{
return array(
array('question[0],question[1],...,question[k]','require'),
);
}
I have been running into situations where I need to validate several arrays of elements
coming from a form and I can't seem to find a good way of going about it other than doing the above. I have the same problem when specifying attributeLables(). If anyone has some advice or a better way of doing this I would really appreciate it.

You can use the CTypeValidator aliased by type
public function rules()
{
return array(
array('question','type','type'=>'array','allowEmpty'=>false),
);
}

With array('question','type','type'=>'array','allowEmpty'=>false), you can just verify that you receive exactly array, but you don't know what inside this array. To validate array elements you should do something like:
<?php
class TestForm extends CFormModel
{
public $ids;
public function rules()
{
return [
['ids', 'arrayOfInt', 'allowEmpty' => false],
];
}
public function arrayOfInt($attributeName, $params)
{
$allowEmpty = false;
if (isset($params['allowEmpty']) and is_bool($params['allowEmpty'])) {
$allowEmpty = $params['allowEmpty'];
}
if (!is_array($this->$attributeName)) {
$this->addError($attributeName, "$attributeName must be array.");
}
if (empty($this->$attributeName) and !$allowEmpty) {
$this->addError($attributeName, "$attributeName cannot be empty array.");
}
foreach ($this->$attributeName as $key => $value) {
if (!is_int($value)) {
$this->addError($attributeName, "$attributeName contains invalid value: $value.");
}
}
}
}

Related

Laravel - associative Array validation in a custom request

I have a customer request as follows:
<textarea name="intro[en]"></textarea>
<textarea name="intro[fr]"></textarea>
<textarea name="intro[de]"></textarea>
I am validating it with a custom request:
class UpdateProfileRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'intro.*' => 'required|max:100'
];
}
}
The validator is not working. I think this is because the .* only works for numbered arrays, rather than associative arrays?
I'm not sure how to go about doing this.
Is there a way to do it with a custom request like this? If so what is the syntax?
Otherwise, what should I do. I already wrote some custom code inside the controller method like this:
$hasIntro = false;
$hasBio = false;
foreach($request->get('intro') as $language => $localIntro)
{
if(!empty($request->get('intro')[$language]))
{
$hasIntro = true;
}
}
if(!$hasIntro or !$hasBio)
{
return redirect()->back()->withErrors('You must enter at least 1 Bio and 1 Intro');
}
Which I think might be one manual way of going about this. Though I believe withErrors requires a validator, so I'm back to the same problem... Though perhaps there is a way to do this manually?
My ideal solution is to find the associative array syntax, if that indeed exists?
I'm not sure about the right way
but my idea is something like this
public function rules($inputs)
{
$rules = [];
foreach ($inputs as $key => $val) {
if ( strpos($key, "intro") === 0 ){
$rules[$key] = 'required|max:100';
}
}
return $rules;
}
class UpdateProfileRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'intro.*' => 'required|max:100'
];
}
/**
* #param Validator $validator
*
* #return mixed
*/
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
}
You have below same name so make sure it's different or remove one, change name.
<textarea name="intro[fr]"></textarea>
<textarea name="intro[fr]"></textarea>
public function rules()
{
$rules = [];
$intro = $this->request->get('intro');
if (!empty($intro)) {
foreach ($intro as $index => $doc) {
$rules[sprintf('intro.%d', $index)] = 'required|max:100';
}
}
return $rules;
}

Is that possible to have multiple rules function in single Request class?

I have request class like below.
class CategoryRequest extends Request
{
public function response(array $errors){
return \Redirect::back()->withErrors($errors)->withInput();
}
public function authorize()
{
return false;
}
public function rules()
{
return [
'Category' => 'required|unique:tblcategory|max:25|min:5'
];
}
}
There is rules function.
In the controller, there are multiple methods that have Request as a Parameter. Most of them vary in the validation point of view. I mean, if I am admin,. I can update 4 fields. If I am manager, I can update 3 and if I am normal user, I can update 2. So validation will change according to roles.
Is that possible to have multiple rules function in Request class ?
You can use here any conditions you want, so you you could do something like this:
public function rules()
{
$rules = [];
if (Auth::user()->isAdmin()) {
$rules['Category'] = '...';
}
elseif (Auth::user()->isManager()) {
$rules['Category'] = '...';
}
return $rules;
}
Of course you need to create isAdmin and isManager in your User model

Yii: ClassName and its behaviors do not have a method or closure named "getRandomPlayers"

i am facing a strange problem. i have a function defined in model which i have been using from weeks now, is suddenly giving me error
ClassName and its behaviors do not have a method or closure named "getRandomPlayers"
following is my code:
Model
public function getRandomPlayers($params)
{
$criteria_obj= new CDbCriteria;
$criteria_obj->order="random()";
$criteria_obj->condition="user_id!=".$params['user_id'];
$criteria_obj->limit=7;
$random_users= Users::model()->findAll($criteria_obj);
if(!empty($random_users))
return $random_users;
else
return false;
}
Controller
public function actionInviteRandom()
{
$body_data = $this->getRequest()->getRawBody();
$data_posted = json_decode($body_data);
if(!empty($data_posted->user_id))
{
$check_valid_user=Users::model()->findByPk($data_posted->user_id);
if(empty($check_valid_user))
{
$this->sendResponse(200, array("status_code" => "002",
"status_message" => Yii::t('strings', 'User does not exist'),
)
);
}
else
{
$params=array(
"user_id"=>$data_posted->user_id,
);
$get_users= Users::model()->getRandomPlayers($params);
$count=0;
if(!empty($get_users))
{
die("here");
}
}
}
}
please check. Thanks in advance
add static to functions name :
public static function getRandomPlayers($params){ ...
UPDATE:
then you can use it like :
$get_users= Users::getRandomPlayers($params);

Yii Dynamic Model Rule

I would like to make a Yii Model rule dynamic, according to an attribute.
It's not giving error but also not working.
Am I doing something wrong? There any easier way to do it?
Model.php (Attributes: NAME, TYPE)
public function rules()
{
return array(
// Name is only required when Type is equal 1.
$this->type==1 ? array('name', 'required') : null,
);
}
Change to ( use scenario):
public function rules()
{
return array(
array('name', 'required','on'=>'typeTrue')
);
}
And in controller
public function actionSome() {
$model = new Model();
if ( $model->type == 1 ) {
$model->setScenario('typeTrue');
}
}
I found the answer and I would like to share.
For it need to use Yii rules scenarios.
Model.php:
public function rules()
{
return array(
array('name', 'required', 'on'=>'type1'),
);
}
Controller.php:
...
if ($model->type==1) {
$model->scenario = 'type1';
}
....

yii CFormModel dynamic properties

i got such form
class CC extends CFormModel
{
public $static_field;
public $fields;
public function rules()
{
return array(
array('static_field, testF', 'required')
);
}
public function getForm()
{
return new CForm(array(
'showErrorSummary'=>true,
'elements'=>array(
'static_field'=>array(),
'testF'=>array(),
),
'buttons'=>array(
'submit'=>array(
'type'=>'submit',
'label'=>'Next'
)
)
), $this);
}
public function attributeLabels()
{
return array(
'static_field' => 'static_field'
);
}
public function __get($name)
{
if (isset($this->fields[$name]))
return $this->fields[$name];
else
return '';
}
public function __set($name, $value)
{
$this->fields[$name] = $value;
}
}
i want to add dynamical field testF
i try to use __get\__set and array for values, but nothing work. any ideas?
If by dynamic you mean not required, you can add it as a property just as you have done with static_field. All attributes, or fields, are encapsulated member data of your FormModel class. So, if you wanted to add your dynamic_field attribute, you could add it in this manner:
class CC extends CFormModel
{
public $static_field;
public $dynamic_field;
public function rules()
{
return array(
array('static_field','required'),
array('dynamic_field','safe'),
);
}
}
Also, you're not exactly following the dominant usage pattern for this type of class. If I were you, I would suggest creating some CRUD through gii and examining the usage patterns for models and forms.

Categories