Yii2 Custom Filter Rule without Anonymous Function - yii2

I am attempting to filter a piece of input data but would like to do so without an anonymous function. The first example below works but the second example returns the error listed. I don't want the couple dozen lines of validation code sitting directly inside my rules so I would like a way to break it out (as in the second example I am trying to implement.
Example 1 (works but is not what I want to do)
public function rules()
{
return [
['roles', 'filter', 'filter' => function ($value) {
// Do some stuff to remove invalid roles
return $value;
}];
}
Example 2 (does not work but is what I would like to do)
public function rules()
{
return [
['roles', 'filter', 'filter' => 'checkRoles'],
];
}
public function checkRoles($value)
{
// Do some stuff to remove invalid roles
return $value;
}
Error returned for Example 2 above
call_user_func() expects parameter 1 to be a valid callback,
function 'validateRoles' not found or invalid function name
Why does the second example above not work? Or rather, more importantly, what do I need to change to get the second example to work?

You should use a valid callback, e.g. :
public function rules()
{
return [
['roles', 'filter', 'filter' => [$this, 'checkRoles']],
];
}
Read more : http://php.net/manual/language.types.callable.php

You may have to use a structure like this:
'filter' => array( $this, 'checkRoles' )

Related

Yii2: Filter query by pivot table when using `joinWith()`

Take the following sample Cart model. It has a CartItem "pivot record/table" which links it to Item.
class Cart extends ActiveRecord {
public function getCartItems() {
return $this
->hasMany(CartItem::class, ['cart_id' => 'id'])
->inverseOf('cart');
}
public function getItems($callback = null) {
return $this
->hasMany(Item::class, ['item_id' => 'id'])
->via('cartItems', $callback);
}
}
(Example #1) At this point I would be able to filter either by Item's activequery or CartItem's query like so:
$booksAddedToCartSinceYesterday = $cart
->getItems(function($cartItemQuery) {
$cartItemQuery->andWhere('cartItem.created_at > NOW()');
})
->andWhere(['item.category' => 'books']);
(Example #2) But how do I accomplish the same when I use the static find() method in combination with joinWith()? In the following example I am only able to filet by Item's ActiveQuery, but I no longer have any reference to the CartItem's ActiveQuery object:
$booksAddedToCartSinceYesterday = Cart::find()
->andWhere(['cart.user_id' => $some_user_id])
->joinWith([
'items' => function($itemQuery) {
$itemQuery->andWhere(['item.category' => 'books']);
},
]);
How do I modify the code above so that I am able to filter CartItem junction table records like I did in my example #1? How do I access the junction ActiveQuery object so that I can call $cartItemQuery->andWhere('cartItem.created_at > NOW()');?
you can pass any variable value in anonymous function with use keyword link below
make your magic code here for filter or any
->joinWith([
'items' => function($itemQuery) use ($var1,$var2){
$itemQuery->andWhere(['item.category' => 'books']);
$itemQuery->andWhere(['some_condition' => $var1]); <<<---------
},
]);

Return URL image in Laravel API

I need to return URL path and name image from database.
This my call method to get data from database:
public function index(){
$rav=Rav::select('id','image','nameravs')->get('image');
return $this->sendResponse($rav->toArray(),'rav show is succesfuly');
}
Output data it look like this:
{
"id": 88,
"image": "1579781806.png",
"nameravs": "asdad"
},
But I want to return image with path URL like this:
"image": http://127.0.0.1:8000/images_ravs/1579781806.png
You can use Eloquent Accessor
add the image url attribute in Rav.php Model like below. then you can access it any place.
public function getImageUrlAttribute($value)
{
return env('APP_URL'). '/images_ravs/' . $this->image;
}
And don't forget to Add Appends property inside the Model
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = ['image_url'];
then you can access it like below.
$rav->image_url
Define An Accessor in your model like this example :
public function getImageAttribute($value)
{
return env('APP_URL') . Storage::url($value);
}
Try this:
public function index(){
$rav = Rav::select('id','image','nameravs')->get('image');
return $this->sendResponse(
[
'id' => $rav->id,
'image' => URL::to('/').'/images_ravs/'.rav->image,
'nameravs' => $rev->nameravs
],'rav show is succesfuly');
}
You can use selectRaw or select with DB::raw and just concat that path as a prepended string infront of your image column in your query:
Rav::select(DB::raw("id, nameravs, CONCAT('/images_ravs/', image) as image"))->get()->toArray();
No need to include the URL (unless for some reason you have some type of CDN in front of it) in which case you can just escape the string and add it if necessary.
I would do something like this: Try to use as many od Laravel's built-in functions as possible. In most cases you don't need to reinvent the wheel.
public function index(){
$ravs = Rav::select('id','image','nameravs')->get();
$results = [];
foreach($ravs as $rav){
$rav->image = env('APP_URL') . '/images_ravs/' . $rav->image;
array_push($results, $rav);
}
return response()->json($results);
}
In the Model you can create getAttribute:
public function getImageAttribute()
{
return $this->attributes['image'] ? URL::to('/uploads/' . $this->attributes['image']) : null;
}
Or you can create custom casts file:
protected $casts = [
'image' => ImageCast::class,
'created_at' => 'datetime',
'updated_at' => 'datetime',
];

Custom Yii2 validator not firing

I have custom form where I am trying to write a custom validator, but its not firing. The model is returned as valid every time submit button is hit:
class DeactivateForm extends Model {
public $deactivate_reason;
public function rules() {
return [
[ 'deactivate_reason', 'reasonValidator' ],
];
}
public function reasonValidator( $attribute, $params ) {
$this->addError( 'deactivate_reason', 'Error !!!' );
}
public function attributeLabels() {
return [
'deactivate_reason' => 'Reason for deactivating',
];
}
}
The actual form is plain jane:
$form = ActiveForm::begin( [
'id' => 'deactivate-form'
] );
When using [ 'deactivate_reason', 'required' ] in the rules, the required rule works fine, custom rule is still ignored...
I am not sure but to forcefully run validation on empty field, add following property.
skipOnError=>false and skipOnEmpty=>false
[
['deactivate_reason', 'reasonValidator', 'skipOnError' => false,'skipOnEmpty'=>false],
]
Try this,add return like below
public function reasonValidator( $attribute, $params ) {
return $this->addError( 'deactivate_reason', 'Error !!!' );
}

Yii Gridview show image from related data

i have table feedback and user, i am trying to show user's image on feedback page.
i am using grid view, this is my gridview.
[ 'attribute' => 'iduser.photo',
'headerOptions' => ['width' => '20px'],
'format' => 'image',
'value'=> function($data) { return $data->imageurl; },
],
and the model
public function getImageurl()
{
return \Yii::$app->request->BaseUrl.'/../../'.$this->hasOne(User::className(), ['photo' => 'photo']);
}
i get right url but the photoname is wrong the result is "photo", i want getting the data form entity photo?
Inside your model you should have a way to get the User related to your feedback like this:
public function getUser() {
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
Then your getImageurl method should look something like this:
public function getImageurl()
{
return \Yii::$app->request->BaseUrl.'/../../'.$this->user->photo;
}
I would recommend checking out Aliases, you can use them instead of \Yii::$app->request->BaseUrl. For example, this is the implementation i use to get a file url to show to the user:
public function getFileUrl() {
return Yii::getAlias('#web/uploads/'.$this->fileName);
}

Yii2 model custom rules and validations for attribute which is array

Being trying to sort this out but going nowhere with it. I have got an array as attribute for a model and I am trying to create custom validation for some of the keys in the array as required. Or even can't figure out how the attribute labels will work? Here is my code:
MODEL
...
public $company = [
'name' => '',
'trading_name' => '',
'type' => '',
];
public function attributeLabels(){
return [
'company[name]' => 'Company Name',
];
}
public function rules(){
return [
[['company[name]','company[trading_name'], 'safe'],
[['company[name]'], 'return_check','skipOnEmpty'=> false],
];
}
public function return_check($attribute, $params){
$this->addError($attribute ,'Required ');
return false;
}
...
I have even tried to pass the whole array and check in the validator method for the keys and values but the custom validator is not even triggered.
I think you need separated model for company.
I've used custom rule functions, and they all worked. Try removing the return clause at the end of the return_check function.
Here's what has worked for me:
class Essid extends ActiveRecord {
public function rules() {
return [
['network_name', 'checkNetworkName']
]
}
public function checkNetworkName($attribute, $params){
if (!$this->hasErrors()) {
if ( !ctype_alnum($this->network_name) )
$this->addError($attribute, Yii::t('app', 'Not a valid Network Name'));
}
}
}
Hope it helps