Z
Z
ZaurK2016-10-21 23:26:32
Yii
ZaurK, 2016-10-21 23:26:32

How to sort by dependent field?

Hello! I broke my head, and googling did not give anything - everything that I found is not very suitable or does not solve the problem. There is a Good.php product model with an external dependency on the Catalog.php model

public function getCatalog()
    {
        return $this->hasOne(Catalog::className(), ['id' => 'catalog_id']);
    }

There is also a view for displaying information on goods, in the third column, respectively, the catalogs to which the goods belong are displayed
<?php

use yii\helpers\Html;
use yii\grid\GridView;

/* @var $this yii\web\View */
/* @var $searchModel backend\models\SearchGood */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = 'Работы';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="good-index">

    <h1><?= Html::encode($this->title) ?></h1>
    <?php // echo $this->render('_search', ['model' => $searchModel]); ?>

    <p>
        <?= Html::a('Добавление работы', ['create'], ['class' => 'btn btn-success']) ?>
    </p>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],

            //'id',
            [
                'attribute'=>'gtitle',
                'label'=>'Заголовок',    
            ],
            'gdescription:ntext',
            [
                'attribute'=>'catalog.ctitle',
                'label'=>'Каталог',
                
                
            ],
            // 'promo',

            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
</div>

There is also SearchGood.php with this code:
<?php

namespace backend\models;

use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use common\models\Good;

/**
 * SearchGood represents the model behind the search form about `common\models\Good`.
 */
class SearchGood extends Good
{
    public function attributes()
    {
    // делаем поле зависимости доступным для поиска
    return array_merge(parent::attributes(), ['catalog.ctitle']);
    }
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['id', 'catalog_id', 'promo'], 'integer'],
            [['gtitle', 'gdescription', 'catalog.ctitle'], '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 = Good::find();

        // присоединяем зависимость `catalog` которая является связью с таблицей `catalog`
        // и устанавливаем алиас таблицы в значение `catalog`
        $query->joinWith(['catalog' => function($query) { $query->from(['catalog' => 'catalog']); }]);
        // добавляем сортировку по колонке из зависимости
        $dataProvider->sort->attributes['catalog.ctitle'] = [
        'asc' => ['catalog.ctitle' => SORT_ASC],
        'desc' => ['catalog.ctitle' => SORT_DESC],
        ];
        
        // add conditions that should always apply here

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

        $this->load($params);

        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
        $query->andFilterWhere([
            'id' => $this->id,
            'catalog_id' => $this->catalog_id,
            'promo' => $this->promo,
        ]);

        $query->andFilterWhere(['like', 'gtitle', $this->gtitle])
            ->andFilterWhere(['like', 'gdescription', $this->gdescription])
            ->andFilterWhere(['like', 'catalog.ctitle', $this->getAttribute('catalog.ctitle')]);

        return $dataProvider;
    }
}

The search works on all columns, the problem is that sorting by the catalog column does not want to work, the "Catalog" link is not clickable.
Please advise how to improve this point?

Answer the question

In order to leave comments, you need to log in

[[+comments_count]] answer(s)
M
Maxim Fedorov, 2016-10-22
@ZaurK

Sorting is not working for you because:

// тут Вы задаете атрибуты сортировки в переменной в которой еще нет объекта провайдера данных
$dataProvider->sort->attributes['catalog.ctitle'] = [
    'asc' => ['catalog.ctitle' => SORT_ASC],
    'desc' => ['catalog.ctitle' => SORT_DESC],
];

// и только потом создаете сам провайдер данных
$dataProvider = new ActiveDataProvider([
    'query' => $query,
]);

those. Initially, you need to create the data provider itself, and only then set sorting attributes for it. Now you are doing the opposite.

D
Dmitry, 2016-10-22
@slo_nik

Goodnight.
You don't have a catalog.ctitle attribute in your googs model, do you ?
Try like this:

'attribute' => ctitle',
                'filter' => Catalog::find()
                                       ->select(['title', 'id']) // Ваши названия полей
                                       ->indexBy('id')
                                       ->column(),
                'value' => 'catalog.title' // Связь getCatalog(), я так понимаю надо вывести название, подставьте вместо title своё значение

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question