【问题标题】:Yii - CActiveDataProvider using relationsYii - 使用关系的 CActiveDataProvider
【发布时间】:2014-08-20 22:13:28
【问题描述】:

我正在尝试使用关系作为创建CActiveDataProvider 的标准的一部分。我有以下内容:

用户模型:

return array(
        'favourites'=>array(self::HAS_MANY, 'UserFavourite', 'user_id', 'order'=>'added_at DESC'),
);

用户最喜欢的型号:

return array(
        'user'=>array(self::BELONGS_TO, 'User', 'user_id'),
        'listing'=>array(self::BELONGS_TO, 'Listing', 'listing_id'),
);

控制器(查看收藏夹动作):

$user = $this->loadUser(Yii::app()->user->id);

如何在我的用户模型中创建一个CActiveDataProvider,以获取当前用户的所有favourites - 以及每个收藏夹的相关listing 模型数据?所以我想做$favourites = $user->getFavourites();之类的事情。

CActiveDataProvider 应该返回一个由Listing 对象组成的数组。它应该支持分页和排序——默认排序是added_at DESC

我曾尝试使用CDbCriteriawith 选项,但这似乎不起作用...

【问题讨论】:

    标签: php activerecord yii


    【解决方案1】:

    您还没有提供您的数据库架构,但我想这段代码可以工作,

    $criteria=new CDbCriteria();
    $criteria->with=array('favourites'=>array('with'=>'listing'));
    $dataProvider= new CActiveDataProvider('User', array(
            'criteria'=>$criteria,
            'sort'=>array(
                'defaultOrder'=>'t.added_at DESC',
            )));
    

    请确保您的关系正确且符合架构。

    • 事实上,如果你不关心查询的数量,你总是可以调用类似的东西

      $user->收藏夹;

    它会为正确的关系返回正确的数据,你也可以这样做

    为了,把listing model传给view去像这样

    foreach($user->favourites as $fav){
    
      $this->renderPartial("PATH TO YOUR VIEW",array('data'=>$fav->listing));
    
    }
    

    请注意,用户可能有很多收藏夹,因此您需要使用 foreach ,除非您不使用 CListview。 另一种方法是使用 Clistview 用户,在这种情况下您可能需要更改您的查询。让我知道它是如何为您工作的。

    【讨论】:

    • 恐怕这行不通。因为 CActiveDataProvider 正在加载 User 类,但我的视图文件需要 Listing 类。它必须返回Listing 类对象的数组。关系是正确的,我可以按照你的建议通过$user->favourites 获得正确的数据,但问题是它不会让我使用该关系作为我的 CActiveDataProvider 的源。另外我知道我可以创建一个单独的函数,该函数将在不使用关系的情况下返回所需的数据。但我不想重复任何代码。这是我们必须忍受的限制吗?
    • 如果您的视图文件需要列表模型,为什么不直接通过列表模型进行查看,请查看编辑后的答案以了解详细信息。
    • 我其实是在用CListView。所以我无法传入列表模型,我只能指定一个dataProvider 值。
    • 在这种情况下,您需要修改您的查询并为列表创建 Dataprovider,@codeFX 的回答似乎是正确的,为什么不尝试一下。
    【解决方案2】:

    在您的 Listing relations 方法中,您需要与 Users 通过中间表UsersFavourite。关系类型 是 HAS_MANY:

    return array(
             'favourites'=>array(self::HAS_MANY, 'UserFavourite', 'listing_id'),
             'users'=>array(self::HAS_MANY, 'User', array('user_id'=>'id'), 'through'=>'favourites')
    );
    

    在返回CActiveDataProviderUser 方法中:主模型 是Listing,加入到UserFavouriteUser。您必须设置togethertrue 构建一个单一的sql 查询。最后,您必须将 users.id 设置为 User 模型的当前 id 以仅带来与当前用户相关的行。

    $criteria = new CDbCriteria;
    $criteria->with = array( 'favourites','users =>'array('condition'=>"users.id=:user_id"));
    $criteria->together = true;
    $criteria->params = array(':user_id'=>$this->id);
    
    return new CActiveDataProvider('Listing', array(
            'criteria'=>$criteria,
            'sort'=>array('defaultOrder'=>'favourites.added_at DESC')
    ));
    

    我测试了这个答案,并在一个小数据集上正常工作。

    【讨论】:

      【解决方案3】:

      这是我实现所需输出的方式:

      $criteria = new CDbCriteria;
      $criteria->condition = 'uf.user_id = :user_id';
      $criteria->params = array(':user_id'=>$this->id);
      $criteria->join = 'LEFT OUTER JOIN user_favourite uf ON uf.listing_id = t.id';
      $criteria->order = 'uf.added_at DESC';
      
      return new CActiveDataProvider('Listing', array(
          'criteria'=>$criteria,
      ));
      

      最后,我只是在 JOIN 中进行了硬编码,而不是尝试使用该关系,因为它似乎不应该以这种方式工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多