Виртуальный атрибут Yii2 вне атрибута SqlDataProvider
Мой AddressController:
public function actionIndex() {
$searchModel = new AddressSearch;
$dataProvider = $searchModel->search($_GET);
return $this->render('index', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
Моя модель AddressSearch:
class AddressSearch extends Model {
public function search($params) {
$dataProvider = new SqlDataProvider([
'sql' => '
SELECT
name
FROM...
Посмотреть:
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
'name2',
У меня есть атрибут с именем name
в этом dataProvider
, Я хотел бы создать новый виртуальный атрибут с именем name2
снаружи name
от preg_replace()
несколько частей этого. Сама функция работает. Я пробовал много разных вещей, но до сих пор не могу сделать это, чтобы заполнить атрибут name2
с данными. name2
всегда пусто Можете ли вы указать мне правильное направление? Большое спасибо!
ОБНОВЛЕНИЕ: основываясь на блестящих идеях @Imaginaroom и @rob006, я сделал следующее:
- переехал
getName2()
и атрибуты, которые я заполняюSqlDataProvider
от базовой моделиAddress
вAddressSearch
- удалил пустую базовую модель
Address
потому что мне это все равно не нужно. Меньше - больше! в
search()
Я добавил:foreach ($dataProvider->getModels() as $row) { $model = new AddressSearch; $model->setAttributes($row, false); $models[] = $model; } $dataProvider->setModels($models);
Оно работает! Большое спасибо, ребята! Это здорово, что ты там и помогаешь!!!
2 ответа
Проблема в том, что вы используете SqlDataProvider
который возвращает строки из таблицы в виде массива вместо экземпляра модели. Вот почему ваш геттер (виртуальный атрибут) не работает в GridView
- GridView
не работает на Address
экземпляр модели, но на необработанном массиве без name2
поле.
Вы должны изменить свой SearchModel
использовать ActiveQuery
:
$dataProvider = ActiveDataProvider([
'query' => Address::find()->select(['name']) //and whatever your query contains besides this
])
...
ОБНОВЛЕНИЕ: Если вы не хотите делать это так, вы можете добавить свою логику прямо в GridView
вот так:
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'header' => 'Name 2',
'value' => function($model) {
if (isset($this->_name2)) {
return $this->_name2;
}
return $this->_name2 = preg_replace([...
}
]
Если вам действительно нужно Address
экземпляр модели и использование SqlDataProvider
в то же время вы можете вручную преобразовать массив в экземпляр модели:
$models = [];
foreach ($dataProvider->getModels() as $row) {
$model = Address::instantiate($row);
Address::populateRecord($model, $row);
$models[] = $model;
}
$dataProvider->setModels($models);
Вы можете разместить это в AddressSearch::search()
или создать кастом SqlDataProvider
и переопределить prepareModels()
,