我有两张桌子:电话,电话
两种型号:呼叫、电话
以及以下代码:

$q = 'select
      c.calling, sp.name as srcname, sp.org as srcorg,
      c.called, dp.name as dstname, dp.org as dstorg
      from Calls c
      left join Phones sp on c.calling = sp.num
      left join Phones dp on c.called = dp.num ORDER BY c.time '
$sql = Yii:$app->db->createCommand($q)
$count = $sql->queryScalar();
$dataProvider = new SqlDataProvider([
   'sql' => $q,
   'pagination' => [
      'pageSize' => 25,
    ],
   'totalCount' => $count,
]);

如何将其转换为ActiveDataProvider查询?
$dataProvder = new ActiveDataProvider([
'query' => Call::find()->...,
'pagination' => [
      'pageSize' => 25,
    ],
]);

最佳答案

我有一些意见也会回答你的问题。
模型而不是原始查询
使用Gii为两个表创建模型。扩展是内置的,您只需在调试模式下调用http://yourproject.com/gii即可打开它。
创建模型时,它还将建立与另一个表的关系。您可以根据Yii2的model-documentationActiveRecord-documentation轻松定制这些。后面还将介绍如何指定关系here
在您的情况下,Call-模型将有两个hasOne-关系:
sourcePhone参考发起呼叫的电话型号
destinationPhone参考接收电话的型号
用于列出调用的数据提供程序和网格视图
现在开始很容易。假设您要列出所有呼叫,可以按如下方式执行:

<?= GridView::widget([
    'dataProvider'=>new ActiveDataProvider(['query'=>Call::find()]),
    'columns'=>[
        'id',
        [
            'label'=>Yii::t('app', 'Source phone'),
            'value'=>function ($model, $key, $index, $column) {
                return $model->sourcePhone->name;
            },
        ],
        [
            'label'=>Yii::t('app', 'Destination phone'),
            'value'=>function ($model, $key, $index, $column) {
                return $model->destinationPhone->name;
            },
        ],
        //more columns as of your requirements...
    ],
]) ?>

现在不仅使用ActiveDataProvider,还使用Yii2的常见方式来显示这些数据(关系等)。分页和内容可以在数据提供程序上进行自定义,就像您在上面所做的那样。
如何在ActiveQuery中使用join-part
这个很简单。一旦调用关系(延迟加载),表的实际连接将自动发生。在上面的例子中,这将发生在这里:
return $model->destinationPhone->name

这将导致另一个查询使用相应的电话实例填充关系。如果希望这与实际的调用查询一起发生,只需将提供的查询扩展到activedataprovider即可:
'dataProvider'=>new ActiveDataProvider([
    'query'=>Call::find()->joinWith(['sourcePhone', 'destinationPhone']),
]),

方法告诉查询获取call对象以及在参数中指定的两个关系。确保您阅读了documentation of this method。我还写了一个answer to a problem I had myself来进一步解释。
如果要访问相关对象的列,只需像访问call对象的属性一样访问相关对象,然后访问属性本身。在上面的示例中,您可以看到我如何访问相关手机型号的joinWith-属性。
如果你需要更多关于某些部件的信息,请告诉我。

08-07 08:10