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 的新虚拟属性。 该功能本身正在运行。我尝试了很多不同的方法,但我仍然无法用数据填充属性 name2name2 始终为空。你能给我指出正确的方向吗?非常感谢!

更新:基于@Imaginaroom 和@rob006 的绝妙想法,我做了以下事情:

有效!非常感谢你们!很高兴你能在那里提供帮助!!!

问题是您正在使用 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()