🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 关系型 Active Record # https://www.yiichina.com/doc/guide/1.1/database.arr BELONGS_TO(属于): 如果表 A 和 B 之间的关系是一对多,则 表 B 属于 表 A (例如 Post 属于 User); HAS_MANY(有多个): 如果表 A 和 B 之间的关系是一对多,则 A 有多个 B (例如 User 有多个 Post); HAS_ONE(有一个): 这是 HAS_MANY 的一个特例,A 最多有一个 B (例如 User 最多有一个 Profile); MANY_MANY: 这个对应于数据库中的 多对多 关系。 由于多数 DBMS 不直接支持 多对多 关系,因此需要有一个关联表将 多对多 关系分割为 一对多 关系。 在我们的示例数据结构中,tbl_post_category 就是用于此目的的。在 AR 术语中,我们可以解释 MANY_MANY 为 BELONGS_TO 和 HAS_MANY 的组合。 例如,Post 属于多个(belongs to many) Category ,Category 有多个(has many) Post. ## 项目示例 D:\wamp\www\weike.test\weiketest\protected\models\weike\wkeTeachingV3.php ``` public function tableName() { return WK::DBweike.'.tbTeachingV3'; } public function relations() { return array( 'prepare' => array(self::BELONGS_TO, 'wkePrepare', 'fdPrepareID'), 'class'=>array(self::BELONGS_TO,'wkeClass','fdClassID') ,//by liupf 2016/7/9 'record'=>array(self::HAS_MANY,'wkeTeachingV3Student','fdTeachingV3ID'),//by liupf 2016/9/28 'content'=>array(self::BELONGS_TO,'Content','fdPrepareID'),//by liupf 2016/9/28 'user'=>array(self::BELONGS_TO,'User','fdTeacherID'),//by liupf 2016/10/19 'operations' => array(self::HAS_MANY,'wkeTeachingV3Operation','fdTeachingV3ID') , 'schoolMap'=>array(self::HAS_ONE,'SchoolMap','','on'=>'t.fdTeacherID = schoolMap.fdUserID'), ); } ``` D:\wamp\www\weike.test\weiketest\protected\models\weike\wkePrepare.php ``` public function tableName() { return WK::DBweike . '.tbPrepare'; } public function relations() { return array( 'user' => array(self::BELONGS_TO, 'User', 'fdTeacherID'), 'prepareItems' => array(self::HAS_MANY, 'wkePrepareItem', 'fdPrepareID'), 'itemCnts' => array(self::HAS_MANY, 'wkePrepareItemContent',array('id'=>'fdPrepareItemID'),'through'=>'prepareItems'), 'bookTag' => array(self::BELONGS_TO, 'Tag', 'fdTextbookID'), 'tag' => array(self::BELONGS_TO, 'Tag', 'fdTagID'), 'content' => array(self::BELONGS_TO, 'Content', 'fdContentID'), 'cntPreHw' => array(self::STAT, 'wkeAssignment', 'fdPrepareID', 'condition' => 't.fdType=' . WK::PREPARE_ITEM_TYPE_PREVIEW), 'cntAssHw' => array(self::STAT, 'wkeAssignment', 'fdPrepareID', 'condition' => 't.fdType=' . WK::PREPARE_ITEM_TYPE_ASSIGNMENT), 'cntTch' => array(self::STAT, 'wkeInClass', 'fdPrepareID'), 'groupMap' => array(self::HAS_MANY, 'wkePrepareGroupMap', 'fdPrepareID'), 'boards' => array(self::HAS_MANY, 'wkePrepareBoard', 'fdPrepareID'), 'ctnTagIndex' => array(self::HAS_MANY, 'wkeCtnTagIndex', '', 'on' => 't.fdContentID=ctnTagIndex.fdContentID'), ); } ``` ## 多对多关联模型 **D:\wamp\www\xue.test\xuetang\protected\models\service\User.php** ``` public function relations(){ 'usercourse' => array(self::MANY_MANY, 'xtCourse', 'wkxuetang.tbCourseStudent(fdUserID, fdCourseID)'), } ``` **D:\wamp\www\xue.test\xuetang\protected\modules\courseCenter\controllers\StuCourseController.php** ``` /** * 获取当前用户的课程 */ public function actionGetMyCourse() { $userId = RequestUtils::getNormalRequest('userId'); //19 if (!$userId) { ResponseUtils::json(null, 1, 'fail'); } $criteria = new CDbCriteria(); $criteria->with = ['usercourse']; $criteria->addCondition("t.id=" . $userId); $list = User::model()->findAll($criteria); if ($list) { ResponseUtils::json($list); } ResponseUtils::json(null, 1, 'fail'); } ``` ### SQL ``` SELECT `t`.`id` AS `t0_c0`, `t`.`fdNumber` AS `t0_c1`, `t`.`fdLogin` AS `t0_c2`, `t`.`fdName` AS `t0_c3`, `t`.`fdRealName` AS `t0_c4`, `t`.`fdPassword` AS `t0_c5`, `t`.`fdActive` AS `t0_c6`, `t`.`fdQuestion` AS `t0_c7`, `t`.`fdAnswer` AS `t0_c8`, `t`.`fdPortrait` AS `t0_c9`, `t`.`fdGender` AS `t0_c10`, `t`.`fdApprove` AS `t0_c11`, `t`.`fdApproverID` AS `t0_c12`, `t`.`fdCreate` AS `t0_c13`, `t`.`fdStatus` AS `t0_c14`, `t`.`fdTypeID` AS `t0_c15`, `t`.`fdCardID` AS `t0_c16`, `t`.`fdPoints` AS `t0_c17`, `t`.`fdMoney` AS `t0_c18`, `t`.`fdCash` AS `t0_c19`, `t`.`fdDisabled` AS `t0_c20`, `t`.`fdShutup` AS `t0_c21`, `t`.`fdExpired` AS `t0_c22`, `t`.`fdRgType` AS `t0_c23`, `t`.`fdVipType` AS `t0_c24`, `t`.`fdOutsideUID` AS `t0_c25`, `t`.`fdOutsideHost` AS `t0_c26`, `t`.`fdIsXuetang` AS `t0_c27`, `t`.`fdTeacherID` AS `t0_c28`, `t`.`fdParentID` AS `t0_c29`, `t`.`fdTeamType` AS `t0_c30`, `t`.`fdOutsideUUID` AS `t0_c31`, `usercourse`.`id` AS `t1_c0`, `usercourse`.`fdUserID` AS `t1_c1`, `usercourse`.`fdName` AS `t1_c2`, `usercourse`.`fdCourseType` AS `t1_c3`, `usercourse`.`fdSubjectID` AS `t1_c4`, `usercourse`.`fdSchoolTypeID` AS `t1_c5`, `usercourse`.`fdViewType` AS `t1_c6`, `usercourse`.`fdDiff` AS `t1_c7`, `usercourse`.`fdFee` AS `t1_c8`, `usercourse`.`fdThumb` AS `t1_c9`, `usercourse`.`fdVideo` AS `t1_c10`, `usercourse`.`fdVideoThumb` AS `t1_c11`, `usercourse`.`fdInfo` AS `t1_c12`, `usercourse`.`fdStatus` AS `t1_c13`, `usercourse`.`fdCreate` AS `t1_c14`, `usercourse`.`fdUpdate` AS `t1_c15` FROM `wksvc`.`tbUser` `t` LEFT OUTER JOIN `wkxuetang`.`tbCourseStudent` `usercourse_usercourse` ON ( `t`.`id` = `usercourse_usercourse`.`fdUserID` ) LEFT OUTER JOIN `wkxuetang`.`tbCourse` `usercourse` ON ( `usercourse`.`id` = `usercourse_usercourse`.`fdCourseID` ) WHERE (t.id = 19) ``` ### 图示 ![](./img/2018-11-21_180305.png) ![](./img/2018-11-21_180346.png)