SqlDataProvider 属性中的 Yii2 虚拟属性
Yii2 virtual attribute out of an attribute of a SqlDataProvider
我的地址控制器:
public function actionIndex() {
$searchModel = new AddressSearch;
$dataProvider = $searchModel->search($_GET);
return $this->render('index', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
我的模型地址搜索:
class AddressSearch extends Model {
public function search($params) {
$dataProvider = new SqlDataProvider([
'sql' => '
SELECT
name
FROM...
查看:
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
'name2',
我在这个 dataProvider
中有一个名为 name
的属性。我想通过 preg_replace()
-ing 的几个部分从 name
中创建一个名为 name2
的新虚拟属性。
该功能本身正在运行。我尝试了很多不同的方法,但我仍然无法用数据填充属性 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);
有效!非常感谢你们!很高兴你能在那里提供帮助!!!
问题是您正在使用 SqlDataProvider
table 中的 returns 行作为数组而不是模型实例。所以这就是为什么你的 getter (虚拟属性)在 GridView
中不起作用 - GridView
不适用于 Address
模型实例,但在没有 [=16= 的原始数组上] 字段。
您应该将 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()
。
我的地址控制器:
public function actionIndex() {
$searchModel = new AddressSearch;
$dataProvider = $searchModel->search($_GET);
return $this->render('index', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
我的模型地址搜索:
class AddressSearch extends Model {
public function search($params) {
$dataProvider = new SqlDataProvider([
'sql' => '
SELECT
name
FROM...
查看:
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
'name2',
我在这个 dataProvider
中有一个名为 name
的属性。我想通过 preg_replace()
-ing 的几个部分从 name
中创建一个名为 name2
的新虚拟属性。
该功能本身正在运行。我尝试了很多不同的方法,但我仍然无法用数据填充属性 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);
有效!非常感谢你们!很高兴你能在那里提供帮助!!!
问题是您正在使用 SqlDataProvider
table 中的 returns 行作为数组而不是模型实例。所以这就是为什么你的 getter (虚拟属性)在 GridView
中不起作用 - GridView
不适用于 Address
模型实例,但在没有 [=16= 的原始数组上] 字段。
您应该将 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()
。