I just started learning Yii 2 yesterday and I have a problem that I don't understand. It's working well with this code, but if I uncomment the 2 lines
I have this error:
[...]a rule must specify both attribute names and validator type.
<?php
namespace app\models\customer;
use yii\db\ActiveRecord;
class CustomerRecord extends ActiveRecord
{
public static function tableName()
{
return 'customer';
}
public function rules()
{
return [
//['name' => 'string'],
//['name' => 'required'],
['birth_date', 'date', 'format' => 'd-m-Y'] ,
['birth_date', 'required'] ,
['notes', 'safe'] ,
];
}
}
I made some researches before posting here.
You list single attribute or array of attributes for the rule, then name of validator, then validator parameters so it should be:
['name', 'string'],
['name', 'required'],
Related
I'm trying to validate two different types of data in a single axios call: Profile and ProfileSocial. The problem is, when I create a ProfileSocialRequest based on the second model and try to validate it, it returns Call to a member function validated() on null; if I return the data before attempting to validate it, it returns a valid object.
ProfileSocial
class ProfileRequest extends FormRequest
{
public function rules()
{
return [
'name' => [
'required',
'string',
],
...
'socials' => [
'required',
'array',
'min:1',
],
];
}
}
ProfileSocialRequest
use Illuminate\Foundation\Http\FormRequest;
class ProfileSocialRequest extends FormRequest
{
public function rules()
{
return [
'profile_id' => [
'required',
'integer',
],
'social_type_id' => [
'required',
'integer',
],
'handle' => [
'required',
'string',
],
];
}
}
ProfileController
public function store(ProfileRequest $request)
{
$data = $request->validated(); // this (ProfileRequest) works fine
$sosicalReq = new ProfileSocialRequest($request['socials'][0]); // This returns a valid object: {"social_type_id":1,"handle":"mySocialNetworkHandle","profile_id":1000}
$socialReqData = $sr->validated(); // ERROR: Call to a member function validated() on null
...
}
My question is, why is $socialReq being read as null when calling validated() if every step of the way it returns a complete object?
I'm not sure what you want to achieve, to but to manually create validation class instead of
$sosicalReq = new ProfileSocialRequest($request['socials'][0]);
you should use:
$sosicalReq = app()->make(ProfileSocialRequest::class);
but it will validate the whole input not just $request['socials'][0]
In Laravel (5.8) controller, i try to make update() function for my User model.
I validate data with using my own class UpdateRequest. When i put variable $user in this class, i have error Undefined variable: user.
<?php
namespace App\Http\Requests\Users;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class UpdateRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required|string|alpha_dash|max:255|min:6',
'email' => ['required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore($user->id)],
];
}
}
public function update(User $user, UpdateRequest $request)
{
$user->update($request->only(['name', 'email']));
return redirect()->route('users.index');
}
But if I use validate function in controller update() method, all works fine.
public function update(User $user, Request $request)
{
$this->validate($request, [
'name' => 'required|string|alpha_dash|max:255|min:6',
'email' => 'required|string|email|max:255|unique:users,id,' . $user->id,
]);
$user->update($request->only(['name', 'email']));
return redirect()->route('users.index');
}
In your custom request class, you don't have the $user initialized and you try to use it, while in the controller method the $user is passed as a parameter.
Note $this->user in the Request returns the currently authenticated user, so make sure that you always want to use his ID, instead of an ID of the passed in user, hence the reason I am using request('user') to get the user id from the URL.
So try this instead:
public function rules()
{
return [
'name' => 'required|string|alpha_dash|max:255|min:6',
'email' => ['required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore(request('user'))],
];
}
You need to change $user->id to $this->user->id and it should work properly. Check below:
return [
'name' => 'required|string|alpha_dash|max:255|min:6',
'email' => ['required',
'string',
'email',
'max:255',
Rule::unique('users')->ignore($this->user->id)],
];
Hope it helps you!!
User class instance is missing in UpdateRequest class constructor or you can try with $this->user->id. It may help you.
In my Laravel application, I have this model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Division extends Model
{
protected $fillable = [
'name','company_id', 'location_id'
];
protected $casts = [
'name' => 'string',
'company_id' => 'integer',
'location_id' => 'integer'
];
public function company()
{
return $this->belongsTo(Company::class);
}
public function location()
{
return $this->belongsTo(Location::class);
}
}
$division->company returns a collection
$division->location returns an array
Why this two relations has different results? (Sorry for bad formating....)
As you've just shown in the comments (and then edited), you're using it with get(). That's why you're getting a collection and not an object.
$division->company returns an object. Then you're running another query with $division->company->anotherRelationship()->get() which returns a collection of related objects.
In Yii2 I trying to write a standalone validator, but it's doesn't work. Below my code:
Standalone validator:
namespace app\components;
use yii\validators\Validator;
class UsernameValidator extends Validator {
public function validateAttribute($model, $attribute)
{
$this->addError($model, $attribute, 'Test.');
}
}
Model code:
namespace app\models;
use Yii;
use yii\base\Model;
use app\components\UsernameValidator;
class SignUpForm extends Model {
public $username;
public $password;
public $confirmPassword;
public function rules(){
return [
[['username', 'password', 'confirmPassword'], 'required'],
['password', 'compare', 'compareAttribute' => 'confirmPassword', 'operator' => '=='],
['confirmPassword', 'compare', 'compareAttribute' => 'password', 'operator' => '=='],
['username', UsernameValidator::className(), 'skipOnEmpty' => false],
];
}
}
skipOnempty, skipOnError don't fix that problem. Please, who experienced this? help me fix.
I am trying to setup the filter for related model in Yii2's GridView widget, but I am keep getting the error like the filter value must be an integer.
I have followed this question. Now, I have a two models Services.php and ServiceCharge.php.
In ServiceCharge.php the relation is setup like:
public function getServiceName()
{
return $this->hasOne(Services::className(),['id'=>'service_name']);
}
In the ServiceChargeSearch.php the code is like this:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\ServiceCharges;
/**
* ServiceChargesSearch represents the model behind the search form about `app\models\ServiceCharges`.
*/
class ServiceChargesSearch extends ServiceCharges
{
/**
* #inheritdoc
*/
public function attributes()
{
// add related fields to searchable attributes
return array_merge(parent::attributes(), ['serviceName.services']);
}
public function rules()
{
return [
[['id'], 'integer'],
[['charges_cash', 'charges_cashless'], 'number'],
[['id', 'serviceName.services', 'room_category'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = ServiceCharges::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->sort->attributes['serviceName.services'] = [
'asc' => ['serviceName.services' => SORT_ASC],
'desc' => ['serviceName.services' => SORT_DESC],
];
$query->joinWith(['serviceName']);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'id' => $this->id,
// 'service_name' => $this->service_name,
'room_category' => $this->room_category,
'charges_cash' => $this->charges_cash,
'charges_cashless' => $this->charges_cashless,
])
->andFilterWhere(['LIKE', 'serviceName.services', $this->getAttribute('serviceName.services')]);
return $dataProvider;
}
}
and in my Gridview it is setup like this:
[
'attribute'=>'service_name',
'value'=>'serviceName.services',
],
Which is showing the services name from the related model correctly.
I am not able to see what I am doing wrong, but the filter field for the attribute for service is not showing at all.
Actually it is much simpler than it seems.
add the column_name to safe attribute.
Note: this should be relation Name
add the join with query - like - $query->joinWith(['serviceName','roomCategory']);
add the filter condition like:
->andFilterWhere(['like', 'services.services', $this->service_name])
->andFilterWhere(['like', 'room_category.room_category', $this->room_category]);
if like to add sorting add the code like:
$dataProvider->sort->attributes['service_name'] = [
'asc' => ['services.services' => SORT_ASC],
'desc' => ['services.services' => SORT_DESC],
];
$dataProvider->sort->attributes['room_category'] = [
'asc' => ['room_category.room_category' => SORT_ASC],
'desc' => ['room_category.room_category' => SORT_DESC],
];
5 you should also set the relation name say public $roomCategory
That's it. Both sorting and filtering for related table works perfectly.
Note: Remove default validation like integer for related column and default filtering generated by gii otherwise it will generate an error.
Update on Latest version:
Adding Public $attribute is not needed.
Adding safe attribute for relation is also not needed.
but the attribute in your current model, which you want filter is
to added to safe attribute that is a must.
and most importantly in your gridview, the related attribute has to
be in closure format.
that is example
[
'attribute=>'attribute_name',
'value=function($data){
return $data->relationname->related_table_attribute_name
}
],
remember it you are using relation_name.related_table_attribute_name filter somehow doesn't work for me.
There is a fairly comprehensive set of instructions on the Yii Framework website. The only thing to note is that the search model complains about the following lines, but everything appears to work as intended without them:
$this->addCondition(...);
For a model, PaymentEvent (table: subs_payment_event), which has a currency_id field linked to model Currency, this is the complete set of additional code (using the Basic template):
In the main model, PaymentEvent.php:
public function getCurrencyName()
{
return $this->currency->name;
}
In the search model, PaymentEventSearch.php:
public $currencyName;
In its rules:
[['currencyName'], 'safe'],
In the attributes of its setSort statement, include:
'currencyName' => [
'asc' => ['subs_currency.name' => SORT_ASC],
'desc' => ['subs_currency.name' => SORT_DESC],
'label' => 'Currency'
],
Before the grid filtering conditions:
$query->joinWith(['currency' => function ($q) {
$q->where('subs_currency.name LIKE "%' . $this->currencyName . '%"');
}]);
Finally, in the GridView columns array in the view (including my usual link across to the related model records):
[
'attribute' => 'currencyName',
'label' => 'Currency',
'format' => 'raw',
'value' => function ($data) {
return Html::a($data->currency->name, ['/currency/' . $data->currency_id]);
},
],