1. 程式人生 > >例項講解TP5中關聯模型

例項講解TP5中關聯模型

https://blog.csdn.net/github_37512301/article/details/75675054

一、關聯模型
在關係型資料庫中,表之間有一對一、一對多、多對多的關係。在 TP5 中,實現了ORM (Object Relational Mapping) 的思想,通過在模型中建立模型間的關聯,實現建立表與表之間的關聯。

二、文章中用到的表結構

所用的資料表和資料傳到了百度雲

連結:http://pan.baidu.com/s/1hrXwEJa 密碼:9r98

image 表,儲存圖片的位置資訊

banner 推薦位表,儲存推薦位的型別

banner_item 表,推薦位中的資訊條目,可以看到它擁有外來鍵 img_id

theme 表,商品活動主題,包含頭圖,主題圖

product 表,商品表

theme_product 表, theme 與 product 的中間表

 

可以建立以下的 E-R圖,一個 banner可以用有多個 banner_item,一個banner_iten 擁有一個 image;

theme 與 product 是多對多關係,

圖1 表之間關係

 

 

三、從問題出發講解關聯

(1)查詢 banner 幷包含其下的 banner_item

由圖1可知,我們要在 banner 與 banner_item 之間建立一對多的關聯關係

class
Banner extends Model { public function items() { //建立一對多關聯 return $this->hasMany('BannerItem', 'banner_id', 'id'); //關聯的模型,外來鍵,當前模型的主鍵 } public static function getBannerByID($id) { $banner = self::with('items')->find($id); // 通過 with 使用關聯模型,引數為關聯關係的方法名 return
$banner; } }

查詢資料可得以下結果

{
    "id": 1,
    "name": "首頁置頂",
    "description": "首頁輪播圖",
    "items": [
        {
            "id": 1,
            "img_id": 65,
            "key_word": "6",
            "type": 1,
            "banner_id": 1
        },
        {
            "id": 2,
            "img_id": 2,
            "key_word": "25",
            "type": 1,
            "banner_id": 1
        },
        {
            "id": 3,
            "img_id": 3,
            "key_word": "11",
            "type": 1,
            "banner_id": 1
        },
        {
            "id": 5,
            "img_id": 1,
            "key_word": "10",
            "type": 1,
            "banner_id": 1
        }
    ]
}

可以發現,在 items 下為一個數組,說明一個 banner 包含多個  banner_item ,有一個問題, items下面是 img_id,客戶端需要圖片路徑,不需要 img_id,所以我們還需要建立 BannerItem 與 Image 模型間的關係。這時,Banner 與 BannerItem有一對多關聯,BannerItem 與 Image 有一對一關聯,這種關聯在 TP5 中稱為巢狀關聯。繼續完善程式碼。

BannerItem.php

class BannerItem extends Model
{
    protected $hidden = ['delete_time', 'update_time'];
    /**
     * 建立與 Image 表的關聯模型(一對一)
     * @return \think\model\relation\BelongsTo
     */
    public function img() {
        return $this->belongsTo('Image', 'img_id', 'id'); //關聯模型名,外來鍵名,關聯模型的主鍵
    }
}

Banner.php

class Banner extends Model
{
    public function items() {
        return $this->hasMany('BannerItem', 'banner_id', 'id');
    }
 
    public static function getBannerByID($id)
    {
        $banner = self::with(['items', 'items.img'])->find($id); // with 接收一個數組
        return $banner;
    }
}

這裡 items.img 這種語法並不太好理解,我們可以根據語境解釋,在一個 Banner 下需要包含多個 BannerItem,而每個 BannerItem 下面又對應一個 Image。
查詢結果:

{
    "id": 1,
    "name": "首頁置頂",
    "description": "首頁輪播圖",
    "items": [
        {
            "id": 1,
            "img_id": 65,
            "key_word": "6",
            "type": 1,
            "banner_id": 1,
            "img": {
                "url": "http://z.cn/images/banner-4a.png"
            }
        },
        {
            "id": 2,
            "img_id": 2,
            "key_word": "25",
            "type": 1,
            "banner_id": 1,
            "img": {
                "url": "http://z.cn/images/banner-2a.png"
            }
        },
        {
            "id": 3,
            "img_id": 3,
            "key_word": "11",
            "type": 1,
            "banner_id": 1,
            "img": {
                "url": "http://z.cn/images/banner-3a.png"
            }
        },
        {
            "id": 5,
            "img_id": 1,
            "key_word": "10",
            "type": 1,
            "banner_id": 1,
            "img": {
                "url": "http://z.cn/images/banner-1a.png"
            }
        }
    ]
}

這樣的結果就可以被客戶端處理了。

(2)hasOne 與 belongsTo 的區別

一對一關係,存在主從關係(主表和從表 ),主表不包含外來鍵,從表包含外來鍵。

hasOne 和 belongsTo 都是一對一關係,區別:
在主表的模型中建立關聯關係,用 hasOne
在從表模型中建立關聯關係,用 belongsTo
所以,我們在 BannerItem 中建立與 Image 的關係,用的是 belongsTo ,而不是 hasOne。相反,如果想在 Image 中查詢到 BannerItem 的內容,需要用 hasOne 。

(3)查詢 theme 幷包含其下的 product
為了讓查詢的主題包含圖片,所以我們要建立 theme 與 product 和 image 的關聯關係,theme 中 topic_img_id 和 head_img_id 與 image 的 id 都是一對一的關係,theme 與 product 是多對多關聯。

class Theme extends Model
{
    
    /**
     * 建立 theme 表中 topic_img_id 與 image 表 id 的一對一關係
     * @return \think\model\relation\BelongsTo
     */
    public function topicImg()
    {
        return $this->belongsTo('Image', 'topic_img_id', 'id');
    }
 
    public function headImg()
    {
        return $this->belongsTo('Image', 'head_img_id', 'id');
    }
 
    /**
     * 建立多對多關聯模型
     * @return \think\model\relation\BelongsToMany
     */
    public function products()
    {    
    //關聯模型名,中間表名,外來鍵名,當前模型外來鍵名
        return $this->belongsToMany('Product', 'theme_product', 'product_id', 'theme_id'); 
    }
         /** * 返回 theme和poducts * @id theme id * @return theme資料模型 */
    public static function getThemeWithProducts($id) 
    {
         $theme = self::with('products,topicImg,headImg') ->find($id); return $theme; 
    }
}

查詢結果為

[
    {
        "id": 1,
        "name": "專題欄位一",
        "description": "美味水果世界",
        "topic_img_id": 16,
        "delete_time": null,
        "head_img_id": 49,
        "update_time": "1970-01-01 08:00:00",
        "topic_img": {
            "url": "http://z.cn/images/[email protected]"
        },
        "head_img": {
            "url": "http://z.cn/images/[email protected]"
        }
    },
    {
        "id": 2,
        "name": "專題欄位二",
        "description": "新品推薦",
        "topic_img_id": 17,
        "delete_time": null,
        "head_img_id": 50,
        "update_time": "1970-01-01 08:00:00",
        "topic_img": {
            "url": "http://z.cn/images/[email protected]"
        },
        "head_img": {
            "url": "http://z.cn/images/[email protected]"
        }
    },
    {
        "id": 3,
        "name": "專題欄位三",
        "description": "做個幹物女",
        "topic_img_id": 18,
        "delete_time": null,
        "head_img_id": 18,
        "update_time": "1970-01-01 08:00:00",
        "topic_img": {
            "url": "http://z.cn/images/[email protected]"
        },
        "head_img": {
            "url": "http://z.cn/images/[email protected]"
        }
    }
]

可以看到,有的屬性前端並不需要使用,比如 topic_img_id,delete_time等,所以還需要隱藏欄位

 

在 Theme.php 中加入

protected $hidden = ['topic_img_id', 'head_img_id', 'delete_time', 'update_time'];

這裡只是結合例子,講了關聯模型的簡單使用。祝大家學習愉快。