【小(xiǎo)編推薦】ThinkPHP3.2♦•♠——關聯模型

2014-06-26   | &nb₽←sp; 發布者:梁國(guó)芳&nσβσΩbsp;  |  &nb→≤∞εsp;查看(kàn):3320次

Thinkphp

關聯關系

通(tōng)常我們所說(shuō)的(de)關聯關↓×↑¶系包括下(xià)面三種:

  1. 一(yī)對(duì)一(yī)關聯 ONE_TO_ONE,包括HAS_ONE 和(hé) BELONGS_TO
  2. 一(yī)對(duì)多(duō)關聯 ONE_TO_MANY,包括HAS_MANY 和(hé) BELONGS_TO
  3. 多(duō)對(duì)多(duō)關聯 MANY_TO_MANY

關聯關系必然有(yǒu)一(yī)個(gè)參♦≥☆λ照(zhào)表,例如(rú):

關聯定義

ThinkPHP可(kě)以很(hěn)輕松的(de)完成β♣數(shù)據表的(de)關聯CURD操作(zuò), ☆目前支持的(de)關聯關系包括下(xià)面四種:απ

HAS_ONEBELONGS_TOHAS_MANY和(hé)MANY_TO_MANY

一(yī)個(gè)模型根據業(yè)務模型的(d€₹e)複雜(zá)程度可(kě)以同時(shí)定義多(duō)個(gè)關聯‌™'♥,不(bù)受限制(zhì),所有(yǒu)<♥的(de)關聯定義都(dōu)統一(yī)在模型類的(de) $$₽_link 成員(yuán)變量裡(lǐ)面定義,并且可(kě)以支持✔♦動态定義。要(yào)支持關聯操作(zuò)↕↔,模型類必須繼承Think\Model\RelationModel類,關聯定義的(de)格式是(shì):

  1. namespace Home\Model;
  2. use Think\Model\RelationModel;
  3. class UserModel extends RelationModel{
  4. protected $_link = array(
  5. '關聯1' => array(
  6. '關聯屬性1' => '定義',
  7. '關聯屬性N' => '定義',
  8. ),
  9. '關聯2' => array(
  10. '關聯屬性1' => '定義',
  11. '關聯屬性N' => '定義',
  12. ),
  13. '關聯3' => HAS_ONE, // 快(kuài)捷定義
  14. ...
  15. );
  16. }

下(xià)面我們首先來(lái)分(fēn)析下(xià♠γ®)各個(gè)關聯方式的(de)定義:

HAS_ONE

HAS_ONE關聯表示當前模型擁有(yǒu)一(yī)個(gè)子(zǐ)←↔↔π對(duì)象,例如(rú),每個(gè)員(y☆σ•uán)工(gōng)都(dōu)有(yǒu)一(yī)個(gè)人(rλσ¥✘én)事(shì)檔案。我們可(kě)以建立一(yī)♣∞₹個(gè)用(yòng)戶模型UserMod€≈el,并且添加如(rú)下(xià)關聯定義:

  1. namespace Home\Model;
  2. use Think\Model\RelationModel;
  3. class UserModel extends RelationModel{
  4. protected $_link = array(
  5. 'Profile'=> self::HAS_ONE,
  6. );
  7. }

上(shàng)面是(shì)最簡單的(de)方式,表示其遵循了(l≈≥e)系統內(nèi)置的(de)數(shù)據庫規範,完整的(¶÷de)定義方式是(shì):

  1. namespace Home\Model;
  2. use Think\Model\RelationModel;
  3. class UserModel extends RelationModel{
  4. protected $_link = array(
  5. 'Profile'=>array(
  6. 'mapping_type' => self::HAS_ONE,
  7. 'class_name' => 'Profile',
  8. // 定義更多(duō)的(de)關聯屬性 ¶λ
  9. ……
  10. ),
  11. );
  12. }

關聯HAS_ONE支持的(de)關聯屬性有(yǒu): ♣​♦ mapping_type :關聯類型

這(zhè)個(gè)在HAS_ONE 關聯裡(lǐ)面必須使用(yòng'αΩ )HAS_ONE 常量定義。

class_name :要(yào)關聯的(de)模型類名

例如(rú),class_name 定義為(wèi∏"α')Profile的(de)話(huà)則表示和← ←•(hé)另外(wài)的(de)Profile模型類關聯,這(zσ£±×hè)個(gè)Profile模型類是(shì)無需定義¶¶★的(de),系統會(huì)自(zì)動定位到(dào)相(xià₹δ‌≈ng)關的(de)數(shù)據表進行(xíng)關聯。

mapping_name :關聯的(de)映射名稱,用(yòng)于★‍βφ獲取數(shù)據用(yòng)

該名稱不(bù)要(yào)和(hé)當前模型的(de)字段有(yǒ‌​u)重複,否則會(huì)導緻關聯數(shù€$€ε)據獲取的(de)沖突。如(rú)果mapping_name沒σΩλ‌有(yǒu)定義的(de)話(huà),會(hu  ↑ì)取class_name的(de)定義作(zuò)為(wèi)mapping¶×_name。如(rú)果class_nam↓♦e也(yě)沒有(yǒu)定義,則以數(shù)組的(de)索引作φ (zuò)為(wèi)mapping_name。

foreign_key : 關聯的(de)外(wài)鍵名稱

外(wài)鍵的(de)默認規則是(shì)當前數(shù)據對(d¶♠±↔uì)象名稱_id,例如(rú): UserModel對(duì)應的(de←™♣ε)可(kě)能(néng)是(shì)表&§♠think_user (注意:think隻是(shì)一(yī)個(gè)表前↔✘綴,可(kě)以随意配置) 那(nà)麽thinkδ™§_user表的(de)外(wài)鍵默認為(wèi) user_id,如(‌≠•rú)果不(bù)是(shì),就(jiù)必須在定義關€γ聯的(de)時(shí)候顯式定義 foreign_key 。

condition : 關聯條件(jiàn)

關聯查詢的(de)時(shí)候會(huì)自(zì)動帶上₩∑ε♣(shàng)外(wài)鍵的(de)值,如(rú)果有(y∞σγǒu)額外(wài)的(de)查詢條件(jiàn↔ ™),可(kě)以通(tōng)過定義關聯的(×<​↕de)condition屬性。

mapping_fields : 關聯要(yào)查詢的(de)字Ω Ω≈段

默認情況下(xià),關聯查詢的(de)關聯數(shù)據×↓♠σ是(shì)關聯表的(de)全部字段,如(rú)₹☆Ω果隻是(shì)需要(yào)查詢個(gè)别字段,可(kě)以定£απ♥義關聯的(de)mapping_field<"​₹s屬性。

as_fields :直接把關聯的(de)字段值映射成數®α↔★(shù)據對(duì)象中的(de)某個(gè)字段

這(zhè)個(gè)特性是(shì)ONE_TO_ONE 關聯特Ω€有(yǒu)的(de),可(kě)以直接把關聯數(shù)據映射到(dào)αβ₹✘數(shù)據對(duì)象中,而不(bù)是(shì)作(z≥¶∑uò)為(wèi)一(yī)個(gè)關聯數(shù)據。當關聯數(s♦©✔hù)據的(de)字段名和(hé)當前數(sh≠↑ ±ù)據對(duì)象的(de)字段名稱有(yǒu)沖突時(™βshí),還(hái)可(kě)以使用(yòng)映射定義。≠ ¶←

BELONGS_TO

Belongs_to 關聯表示當前模型從<‍¥→(cóng)屬于另外(wài)一(yī)個(εΩσgè)父對(duì)象,例如(rú)每個(gè)用(yòng)戶都(dōu↑β)屬于一(yī)個(gè)部門(mén)。我們可(kě)以做(∞φzuò)如(rú)下(xià)關聯定義。

  1. 'Dept' => self::BELONGS_TO

完整方式定義為(wèi):

  1. 'Dept' => array(
  2. 'mapping_type' => self::BELONGS_TO,
  3. 'class_name' => 'Dept',
  4. 'foreign_key' => 'userId',
  5. 'mapping_name' => 'dept',
  6. // 定義更多(duō)的(de)關聯屬性
  7. ……
  8. ),

關聯BELONGS_TO定義支持的(de)關聯屬性有(yǒu):♦✔

屬性 描述
class_name 要(yào)關聯的(de)模型類名
mapping_name 關聯的(de)映射名稱,用(yòng)于獲取數(shù)據用(yòng) 該πγ≤σ名稱不(bù)要(yào)和(hé)當前模型的(de)字段有(yǒu)重複, ≈≈否則會(huì)導緻關聯數(shù)據獲取的(de)沖突←‍"↑。
foreign_key 關聯的(de)外(wài)鍵名稱
mapping_fields 關聯要(yào)查詢的(de)字段
condition 關聯條件(jiàn)
parent_key 自(zì)引用(yòng)關聯的(de)關聯字段 默認為(wèi)♣σ≠parent_id 自(zì)引用(yòng)關聯是(shì)一(yī)種比λ©‌較特殊的(de)關聯,也(yě)就(jiù)是(shì)關聯表β'σ就(jiù)是(shì)當前表。
as_fields 直接把關聯的(de)字段值映射成數(shù)據對(duì)象中的(de)σ>某個(gè)字段

HAS_MANY

HAS_MANY 關聯表示當前模型擁有(yǒu)多(duō)個(gè‌₹'↕)子(zǐ)對(duì)象,例如(rú)每個( וgè)用(yòng)戶有(yǒu)多(duō)篇文(wén)章(zhān♣∑g),我們可(kě)以這(zhè)樣來(lái)定義:

  1. 'Article' => self::HAS_MANY

完整定義方式為(wèi):

  1. 'Article' => array(
  2. 'mapping_type' => self::HAS_MANY,
  3. 'class_name' => 'Article',
  4. 'foreign_key' => 'userId',
  5. 'mapping_name' => 'articles',
  6. 'mapping_order' => 'create_time desc',
  7. // 定義更多(duō)的(de)關聯屬性
  8. ……
  9. ),

關聯HAS_MANY定義支持的(de)關聯屬性有(yǒu):

屬性 描述
class_name 要(yào)關聯的(de)模型類名
mapping_name 關聯的(de)映射名稱,用(yòng)于獲取數(shù​&$)據用(yòng) 該名稱不(bù)要(yào)和(hé)當前☆↓模型的(de)字段有(yǒu)重複,否則會β∞(huì)導緻關聯數(shù)據獲取的(de)沖突。
foreign_key 關聯的(de)外(wài)鍵名稱
parent_key 自(zì)引用(yòng)關聯的(de)關聯字段 默認為(wèi)p₽φ₩arent_id
condition 關聯條件(jiàn) 關聯查詢的(de)時(↓÷Ω™shí)候會(huì)自(zì)動帶上(shàng)外( ♠λwài)鍵的(de)值,如(rú)果有(®∑¥​yǒu)額外(wài)的(de)查詢條件(jiàn),可(kě)以通(tōng ×ε∞)過定義關聯的(de)condition屬性。
mapping_fields 關聯要(yào)查詢的(de)字段 默認情況下(xià),關聯查詢的(∑"∏ de)關聯數(shù)據是(shì)關聯表的(de)全部字段,如(rú)果隻是®σ≥♠(shì)需要(yào)查詢個(gè)别字段,可(kě)以定義≥→關聯的(de)mapping_fields屬性。
mapping_limit 關聯要(yào)返回的(de)記錄數(shù)目
mapping_order 關聯查詢的(de)排序

外(wài)鍵的(de)默認規則是(shì)當前數(shù)據對(duì)¶♦¶象名稱_id,例如(rú):UserModel對(duì)應的(de)可(₩α₽kě)能(néng)是(shì)表think_uε>ser (注意:think隻是(shì)一(yī÷↑↕π)個(gè)表前綴,可(kě)以随意配置)‍<₽↕  那(nà)麽think_user表的(de)外(wài)鍵默∑δ‍認為(wèi) user_id,如(rú)果不(bù)是(shì),就(ji↔★≠₽ù)必須在定義關聯的(de)時(shí)候£÷≥定義 foreign_key 。

MANY_TO_MANY

MANY_TO_MANY 關聯表示當前模型可(kě)λ<$γ以屬于多(duō)個(gè)對(duì)象,而父☆♥♠&對(duì)象則可(kě)能(néng)包含∏÷有(yǒu)多(duō)個(gè)子(zǐ)對(duì)象,通(tōng)常兩σ♠者之間(jiān)需要(yào)一(yī)個₹®(gè)中間(jiān)表類約束和(hé)關÷₩ €聯。例如(rú)每個(gè)用(yòng)戶可(kě÷Ωβ)以屬于多(duō)個(gè)組,每個(gè)組可(kě)以有✔<φ≥(yǒu)多(duō)個(gè)用(yòng)戶:

  1. 'Group' => self::MANY_TO_MANY

完整定義方式為(wèi):

  1. 'Group' => array(
  2. 'mapping_type' => self::MANY_TO_MANY,
  3. 'class_name' => 'Group',
  4. 'mapping_name' => 'groups',
  5. 'foreign_key' => 'userId',
  6. 'relation_foreign_key' => 'groupId',
  7. 'relation_table' => 'think_group_user' //此處應顯式定義中間(jiān)表名稱,且不(bù)能(nén ₩•g)使用(yòng)C函數(shù)讀(dú)取表前綴
  8. )

MANY_TO_MANY支持的(de)關聯屬性定義有(yǒu):

屬性 描述
class_name 要(yào)關聯的(de)模型類名
mapping_name 關聯的(de)映射名稱,用(yòng)于獲取數♦÷(shù)據用(yòng) 該名稱不(bù)要(yào)和(hπ₽§€é)當前模型的(de)字段有(yǒu)重複,否則會(✔÷huì)導緻關聯數(shù)據獲取的(de)沖突。
foreign_key 關聯的(de)外(wài)鍵名稱 外(wài'←δσ)鍵的(de)默認規則是(shì)當前數(shù)據•©✘對(duì)象名稱_id
relation_foreign_key 關聯表的(de)外(wài)鍵名稱 默認的(de)關聯表的(d∑↕βe)外(wài)鍵名稱是(shì)表名_id
mapping_limit 關聯要(yào)返回的(de)記錄數(shù±↕✔Ω)目
mapping_order 關聯查詢的(de)排序
relation_table 多(duō)對(duì)多(duō)的(de)中間(Ω↔★jiān)關聯表名稱

多(duō)對(duì)多(duō)的(de)中間(jiān)表默認表規則是♠€✘¥(shì):數(shù)據表前綴_關聯操作(zuò)的(de)主表名_₽ε∑π關聯表名

如(rú)果think_user 和(hé) thin→<k_group 存在一(yī)個(gè)對(​₹βduì)應的(de)中間(jiān)表,默認的(de)表名應該是(shì)‍δ✔ 如(rú)果是(shì)由group來(lái)操作(zuò)關聯≥♥↔表,中間(jiān)表應該是(shì) think_gβλ≥roup_user,如(rú)果是(shì)從(cóng)₩♥Ω×user表來(lái)操作(zuò),那( ®☆•nà)麽應該是(shì)think_user_group,也(yě)就(≥±✘≥jiù)是(shì)說(shuō),多(duō)♣←對(duì)多(duō)關聯的(de)設置,必須有(yǒu)一↕₽✘(yī)個(gè)Model類裡(lǐ)面需要(yào)顯式定義中間(₽™↔¥jiān)表,否則雙向操作(zuò)會(h£"‌uì)出錯(cuò)。 中間(jiān)表無需另外(wàiλ×)的(de)id主鍵(但(dàn)是(s♠←∏hì)這(zhè)并不(bù)影(yǐng)響中間(jiān)表的( ≈™de)操作(zuò)),通(tōng)常隻是(shì)由 ∑✔ ♦user_id 和(hé) group_id 構成∑$&。 默認會(huì)通(tōng)過當前模型的(de)getRelat​σδ​ionTableName方法來(lái)自(z∏&♥ì)動獲取,如(rú)果當前模型是(shì)Use∞♣÷r,關聯模型是(shì)Group,那(n•€↓☆à)麽關聯表的(de)名稱也(yě)就(←≥jiù)是(shì)使用(yòng) user_group這(zh"&è)樣的(de)格式,如(rú)果不(bù≠± ↑)是(shì)默認規則,需要(yào)指定relation_tabσ×‍Ωle屬性。

3.2.2版本開(kāi)始,relation_table定義支持簡化(h"$ uà)寫法,例如(rú):

  1. 'relation_table'=>'__USER_GROUP__'

關聯查詢

由于性能(néng)問(wèn)題,新版取消了(le)♦"  自(zì)動關聯查詢機(jī)制(zhì),而統一(yī)使用$∑★ (yòng)relation方法進行(xíng)關聯操作(zuò),r$€elation方法不(bù)但(dàn)可(kě)以啓用(yòng)關&β聯還(hái)可(kě)以控制(zhì)局&✘↔®部關聯操作(zuò),實現(xiàn)了(le)關聯操作(♣≥λzuò)一(yī)切盡在掌握之中。

  1. $User = D("User");
  2. $user = $User->relation(true)->find(1);

輸出$user結果可(kě)能(néng)是(shì)類似于下(xià←↔★∑)面的(de)數(shù)據:

  1. array(
  2. 'id' => 1,
  3. 'account' => 'ThinkPHP',
  4. 'password' => '123456',
  5. 'Profile' => array(
  6. 'email' => 'liu21st@gmail.com',
  7. 'nickname' => '流年(nián)',
  8. ),
  9. )

我們可(kě)以看(kàn)到(dào),用(yòng)戶的(de)關聯數↓←≈×(shù)據已經被映射到(dào)數(shù)據對(duì)÷φ象的(de)屬性裡(lǐ)面了(le)。其中Profile就(jγ∑iù)是(shì)關聯定義的(de)mapping_name屬性。

如(rú)果我們按照(zhào)下(xià)面的(d♦< e)方式定義了(le)as_fields屬性的(de)話(huà•π),

  1. protected $_link = array(
  2. 'Profile'=>array(
  3. 'mapping_type' => self::HAS_ONE,
  4. 'class_name' => 'Profile',
  5. 'foreign_key' => 'userId',
  6. 'as_fields' => 'email,nickname',
  7. ),
  8. );

查詢的(de)結果就(jiù)變成了(le)下αΩ× (xià)面的(de)結果

  1. array(
  2. 'id' => 1,
  3. 'account' => 'ThinkPHP',
  4. 'password' => 'name',
  5. 'email' => 'liu21st@gmail.com',
  6. 'nickname' => '流年(nián)',
  7. )

email和(hé)nickname兩個(gè)字段已經作(zuò)為(≥™φ wèi)user數(shù)據對(duì)象的(de)字段來(lái)顯 ‍‌示了(le)。

如(rú)果關聯數(shù)據的(de)字段名和(hé)當前數(♦× shù)據對(duì)象的(de)字段有(yǒu)沖突的(de)話(h↔>'uà),怎麽解決呢(ne)?

我們可(kě)以用(yòng)下(xià)面的(de)方式來(lái)變≠γ©‍化(huà)下(xià)定義:

  1. 'as_fields' => 'email,nickname:username',

表示關聯表的(de)nickname字段映射成當前數(shù)據對(duì) §★₽象的(de)username字段。

默認會(huì)把所有(yǒu)定義的(de)關聯數(shù)據  "都(dōu)查詢出來(lái),有(yǒ→™₹u)時(shí)候我們并不(bù)希望這Ωσδ(zhè)樣,就(jiù)可(kě)以給relation方法傳入參數(£¥≠γshù)來(lái)控制(zhì)要(yào✔•±)關聯查詢的(de)。

  1. $User = D("User");
  2. $user = $User->relation('Profile')->find(1);

關聯查詢一(yī)樣可(kě)以支持select方法,如∑•&≥(rú)果要(yào)查詢多(duō)個(gè)數(shù)據,并同時♠↓≈(shí)獲取相(xiàng)應的(de)關聯數(>↑λshù)據,可(kě)以改成:

  1. $User = D("User");
  2. $list = $User->relation(true)->Select();

如(rú)果希望在完成的(de)查詢基礎之上(shàng)↕↕₽• 再進行(xíng)關聯數(shù)據的(de)查詢,可(kě)以¥©→使用(yòng)

  1. $User = D("User");
  2. $user = $User->find(1);
  3. // 表示對(duì)當前查詢的(de)數(shù)據對(duì)象進行(xí™→εng)關聯數(shù)據獲取
  4. $profile = $User->relationGet("Profile");

事(shì)實上(shàng),除了(le)當前λ∞♥≤的(de)參考模型User外(wài),其他(≈∏‍tā)的(de)關聯模型是(shì)不(bù)需要(yào)創建的βε(de)。

關聯操作(zuò)

除了(le)關聯查詢外(wài),系統也(yě)支持關聯數(∑  shù)據的(de)自(zì)動寫入、更新和(h€ ₹σé)删除

關聯寫入

  1. $User = D("User");
  2. $data = array();
  3. $data["account"] = "ThinkPHP";
  4. $data["password"] = "123456";
  5. $data["Profile"] = array(
  6. 'email' =>'liu21st@gmail.com',
  7. 'nickname' =>'流年(nián)',
  8. );
  9. $result = $User->relation(true)->add($data);

這(zhè)樣就(jiù)會(huì)自(zì)✔δ♥‍動寫入關聯的(de)Profile數(shù)據。

同樣,可(kě)以使用(yòng)參數(±>₩shù)來(lái)控制(zhì)要(yào)關聯寫入的($γde)數(shù)據:

  1. $result = $User->relation("Profile")->add($data);

當MANY_TO_MANY時(shí),不&σ∑®(bù)建議(yì)使用(yòng)關聯插入。

關聯更新

數(shù)據的(de)關聯更新和(hé)關聯寫入類似

  1. $User = D("User");
  2. $data["account"] = "ThinkPHP";
  3. $data["password"] = "123456";
  4. $data["Profile"] = array(
  5. 'email' =>'liu21st@gmail.com',
  6. 'nickname' =>'流年(nián)',
  7. );
  8. $result = $User-> relation(true)->where('id=3')->save($data);

Relation(true)會(huì)關聯保存User♥±模型定義的(de)所有(yǒu)關聯數(shù)據,如(rú)果隻需要(yà₩←≈∞o)關聯保存部分(fēn)數(shù)據,可(kě)以¥₩®使用(yòng):

  1. $result = $User->relation("Profile")->save($data);

這(zhè)樣就(jiù)隻會(huì)同時(shí)更新關聯的(de)Pro↑σλ€file數(shù)據。

關聯保存的(de)規則:

HAS_ONE: 關聯數(shù)據的(de)更新直接賦值

HAS_MANY: 的(de)關聯數(shù)據如(rú)果傳入主鍵的£‌(de)值 則表示更新 否則就(jiù)表示新增

MANY_TO_MANY: 的(de)數(shù)據更新是(shì)删除之前的(de)數(£§shù)據後重新寫入

關聯删除

  1. //删除用(yòng)戶ID為(wèi)3的•↑(de)記錄的(de)同時(shí)删除關聯數(shù)$€據
  2. $result = $User->relation(true)->delete("3");
  3. // 如(rú)果隻需要(yào)關聯删除部分(fēn)數(shù)據,可✔✘(kě)以使用(yòng)
  4. $result = $User->relation("Profile")->delete("3");