Как в GridView использовать вызов функции только один раз?

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Федор Досумов
Сообщения: 1
Зарегистрирован: 2021.10.05, 12:01

Как в GridView использовать вызов функции только один раз?

Сообщение Федор Досумов »

Сразу упомяну, что использовать чистый array я не могу, только Active Record.

Есть грид и его колонки:

Код: Выделить всё

    $gridColumns = [
    	['class' => SerialColumn::class],
    	[
    		'attribute' => 'cap',
    		'label' => 'Всего, Зан., Св.',
    		'format' => 'raw',
    		'value' => function($model) {
    			$data = Yii::$app->db->createCommand("SELECT * FROM dbFunction({$model->point_id}")->queryOne();
    			$html = <<< HTML
    <div class="item">{$data['capacity']}</div>
    <div class="item">{$data['occupied']}</div>
    <div class="item">{$data['free']}</div>
    HTML;		
    			return $html;
    		},		
    	],	
    ];
    
    echo GridView::widget([
    	'id' => 'my-table',
    	'columns' => $gridColumns,
    	'dataProvider' => $dataProvider,
    	'filterModel' => $searchModel,	
    	'rowOptions' => function($model) {
    		$data = Yii::$app->db->createCommand("SELECT * FROM dbFunction({$model->point_id}")->queryOne();		
    		
    		$class = $data['free'] === 0 ? 'free-point' : '';
    				
    		if ($data['capacity'] === 0 && $data['occupied'] === 0 && $data['free'] === 0)
    			$class = 'd-none';
    		
    		return [
    			'data-id' => $model->id,
                'class' =>  $class,
    		];
    	},
    ]);

Всё работает, но проблема в том, что функция dbFunction на каждую строчку выполняется по два раза (один раз для ячейки и один раз для определения условий отрисовки самой строки). А функция очень тяжеловесная.

Вопрос: можно ли где-то её вызвать единожды (для итерации) и использовать результат в обоих местах? Не имею понятия как сделать, потому что для columns внутри движка идёт свой цикл, и для rowOptions видимо тоже что-то отдельное. А как это скомпановать?

P.S. На js я могу перенести условия для rowOptions, но тогда получится что написано "отображается 30 записей из 60", а на деле будет отображено 5. Поэтому хотелось бы решить это так же на бэке.
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Как в GridView использовать вызов функции только один раз?

Сообщение unknownby »

Федор Досумов писал(а): 2021.10.05, 12:04 Вопрос: можно ли где-то её вызвать единожды (для итерации) и использовать результат в обоих местах? Не имею понятия как сделать, потому что для columns внутри движка идёт свой цикл, и для rowOptions видимо тоже что-то отдельное. А как это скомпановать?

P.S. На js я могу перенести условия для rowOptions, но тогда получится что написано "отображается 30 записей из 60", а на деле будет отображено 5. Поэтому хотелось бы решить это так же на бэке.
Пробуйте через dataProvider передать значение и потом его использовать уже в двух местах. Чтобы не выполнять два раза dbFunction
Аватара пользователя
SiZE
Сообщения: 2813
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Как в GridView использовать вызов функции только один раз?

Сообщение SiZE »

Вынести получение всех данных в контроллер и передавать уже в представление значение.

Код: Выделить всё

// Контроллер

$dbFunctionResults = [];
$rowOptions = [];
foreach ($dataProvider->getModels() as $model) {
    $dbFunctionResults[$model->id] = Yii::$app->db->createCommand("SELECT * FROM dbFunction({$model->point_id}")->queryOne();
    
    $rowOptions[$model->id] = [
        'data-id' => $model->id,
        'class' => $dbFunctionResults[$model->id]['capacity'] === 0 && $dbFunctionResults[$model->id]['occupied'] === 0 && $dbFunctionResults[$model->id]['free'] === 0
                          ? 'd-none'
                          : ($dbFunctionResults[$model->id]['free'] === 0 ? 'free-point' : '')
    ];
}

$this->view->renderView('bla-bla-bla', [
    'dbFunctionResuls' => $dbFunctionResults,
    'rowOptions' => $rowOptions,
]);

Код: Выделить всё

// Представление

$gridColumns = [
    ...
    'value' => function($model) use ($dbFunctionResults) {
        $data = $dbFunctionResults[$model->id];
        ...
    }
    ...
];

echo GridView::widget([
	...
	'rowOptions' => function($model) use ($rowOptions) {
	    return $rowOptions[$model->id];
	}
	...
]);
Ответить