【问题标题】:Yii find models through many_many relationshipYii 通过 many_many 关系查找模型
【发布时间】:2011-08-04 18:15:04
【问题描述】:

我正在使用 Yii 并且有 3 个表:用户、设备,使用 users_devices 表 (user_id, device_id) 来定义它们之间的 MANY_MANY 关系。

我正在寻找的是通过 ActiveRecord 从属于特定用户 (users.id) 的设备 ID (devices.id) 查找设备的最简单方法。

场景是 REST API 正在查询设备,但出于安全原因,我想验证设备是否归用户所有。

这个想法是这样的:

$device = Devices::model()->findByPk($deviceId)->having(
    array('user_id' => $userId));

提前感谢您的帮助,我已经研究了一段时间,但找不到优雅的解决方案。

【问题讨论】:

  • users_devices 是否有 user_id 和 device_id 作为主(复合)键?是这样,不要忘记像here 那样覆盖 prmaryKey()。您可以使用您的定制模型在该表上进行查找,以识别用户-设备关系(或缺少关系)。
  • 你的意思是 MANY_MANY 不是 HAS_MANY。

标签: php mysql activerecord many-to-many yii


【解决方案1】:

在 Yii 论坛上得到了一些帮助,这让我自己弄清楚了:

$device = Device::model()->with('users')->find(array(
    'condition' => 'user_id = :userId AND device_id=:deviceId',
    'params' => array(':userId' => Yii::app()->user->id, ':deviceId' => $_GET['id'])));

【讨论】:

    【解决方案2】:

    拿两个。

    在 Device.php 中:

    // creates a users property within a Device, a container of associated Users
    public function relations()
        {
            return array(
                'users'=>array(self::MANY_MANY, 'User',  // don't use HAS_MANY
                    'user_devices(user_id, device_id)'), // composite key assumed
            );
        }
    

    然后查找请求的设备是否由请求用户拥有:

    $device = Device::model()->findByPk($deviceId);
    if ( $device->users->findByPk($userId) == Null )
        $device = Null; 
    

    这似乎可行,但检索大量不需要的用户记录效率低下,因为您已经知道用户是谁并且可能已经拥有他们的 activeRecord。为了避免这种低效率,Yii 敏捷开发一书在父模型 (Device.php) 中使用原始 SQL 进行 M2M 关系查询:

    // "Agile" uses a $user AR argument, you can use $userId instead
    public function doesUserOwnDevice($userId) 
    {
        $sql = "SELECT user_id FROM user_devices WHERE
        device_id=:deviceId AND user_id=:userId";
        $command = Yii::app()->db->createCommand($sql);
        $command->bindValue(":deviceId", $this->id, PDO::PARAM_INT);
        $command->bindValue(":userId", $userId, PDO::PARAM_INT);
        return $command->execute()==1 ? true : false;
    }
    

    我使用Device 而不是Devices 作为模型名称(同样device 作为表格名称)。如果您剪切和粘贴,请重构。 User 也是如此。同样缺少“tbl_”前缀。

    【讨论】:

      【解决方案3】:

      你必须使用 AR 吗?

      在处理复杂的语句时,我总是更喜欢使用query builder...

      $user = Yii::app()->db->createCommand()
          ->select('id, username, profile')
          ->from('tbl_user u')
          ->join('tbl_profile p', 'u.id=p.user_id')
          ->where('id=:id', array(':id'=>$id))
          ->queryRow();
      

      【讨论】:

      • 我想我必须使用查询生成器,在使用 Yii 的标准处理复杂查询时进行无休止的调试。谢谢
      猜你喜欢
      • 2013-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多