Using $model inside a callback function in a view

I’ve followed the example in the yii2 guide to create related models using a junction table.

What I have now are these 3 models/tables :

class Order extends \yii\db\ActiveRecord
{
    public function getOrderItems()
    {
        return $this->hasMany(OrderItem::className(), ['order_id' => 'order_id']);
    }

    public function getItems()
    {
        return $this->hasMany(Item::className(), ['item_id' => 'item_id'])
            ->via('orderItems');
    }
}

class Item extends \yii\db\ActiveRecord
{
    public function getOrderItems()
    {
        return $this->hasMany(OrderItem::className(), ['item_id' => 'item_id']);
    }

    public function getOrders()
    {
        return $this->hasMany(Order::className(), ['order_id' => 'order_id'])
            ->via('orderItems');
    }
}

class OrderItem extends \yii\db\ActiveRecord
{
    public function getOrder()
    {
        return $this->hasOne(Order::className(), ['order_id' => 'order_id']);
    }

    public function getItem()
    {
        return $this->hasOne(Item::className(), ['item_id' => 'item_id']);
    }
}

What I want to do now is display a GridView of the related items in the view.php view file of the selected Order along with an ActionColumn with buttons to view the item and to delete the orderItem (by calling the appropriate action inside their respective controllers).

So now I have the following configuration in order\view.php:

/* @var $model app\models\Order */

$dataProvider = new ActiveDataProvider([
    'query' => $model->getItems(),
]);

echo GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        'item_id',
        'name',
        [
            'class' => 'yii\grid\ActionColumn',
            'template' => '{view} {delete}',
            'buttons' => [
                'view' => function ($url, $item, $key) {
                    return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', ['item/view', 'id' => $item->item_id]);
                },
                'delete' => function ($url, $item, $key) {
                    return Html::a('<span class="glyphicon glyphicon-remove-sign"></span>', ['order-item/delete', 'id' => $item->getOrderItems()->where(['order_id' => $model->order_id])->one()->order_item_id]);
                },
            ],
        ],
    ],
])

With this code I get a Undefined variable: model error message because it seems the $model variable is undefined inside the scope of the callback function.

How can I resolve this issue? Any help is appreciated.

$model should be Order instance however on your callback function parameter you are using different name $item so basically your instance name is changed to $item hence it fails to find $model on your function. just replace $model with $item and it will work.

Hi @libedux, thanks for the reply.

When I replace $model with $item, I get this error message :

Getting unknown property: app\models\Item::order_id

I think it’s because inside the callback $model (or $item) holds a record returned by the query that I configured in the ActiveDataProvider which is :

'query' => $model->getItems(),

Is there a way to still be able to use the original $model (the one that holds a app\models\Order instance) inside the callback function?

I see then you should use it this way

'delete' => function ($url, $item, $key) use ($model) {
                    return Html::a('<span class="glyphicon glyphicon-remove-sign"></span>', ['order-item/delete', 'id' => $item->getOrderItems()->where(['order_id' => $model->order_id])->one()->order_item_id]);
                },

$model variable should be your app\models\Order instance

Exactly what I needed. Thanks a lot.