您在這裡

關聯式內容類型的問題

yosia's 的頭像
yosia 在 2012-10-02 (二) 20:35 發表

如果我有三種Content Type ,假設為A,B,C,因為A跟B之間是多對多關係,
且擁有相同的分類taxonomy
我需要C去記錄這兩者之間的關係,所以C包含兩個 reference field 分別指向A及B。
現在我利用Views 在A的頁面中產生一個區塊block去展示相同子分類的term的B

問題來了,
我希望能夠在區塊中針對每一筆B設定一個連結,點擊連結可以直接跳到建立C的編輯頁面,
且自動在C中分別填入對應A及B的reference field
請問目前有什麼作法呢?
請各位高手不吝指點迷津,感激不盡!!

抱歉,說明的不太清楚,
因為我的實際案例比較抽象,舉個例說明,
我的三種content type分別為 A 是「司機」,B是「汽車」,C是「汽車使用記錄」
汽車使用記錄有兩個reference field 分別對應 A 跟 B,假設是re_fieldA跟re_fieldB

A跟B共同有個類別叫做「駕照種類」, 我現在希望在檢視「司機」A的頁面中放一個block,當中會顯示相同「駕照種類」的「汽車」列表
列表中的每台汽車旁邊有個「新增記錄」的按鈕(連結),使用者點擊後,直接新增一筆「汽車使用記錄」,

例如我的司機Tom他只有機車駕照,旁邊的block中的列表顯示的是
sym 野狼125 新增記錄
kymco金勇125 新增記錄

當我按下sym野狼125旁邊的新增記錄時,就自動新增一筆使用記錄
而此筆記錄的re_fieldA 內容為Tom , re_fieldB的內容為sym 野狼125

以上,好像講的有點複雜,不曉得這樣的功能可不可行呢?

自動填表單的部份,你或許可以考慮用看看這個:http://drupal.org/project/nodereference_url (如果你是用 node reference)或 http://drupal.org/project/entityreference_prepopulate (如果你是用 entity reference)

至於怎麼樣點選「汽車」就新增一筆目前檢視之「駕駛」的「使用紀錄」,沒試過,不過光憑空推想,可以考慮用 views 做個區塊,先撈出具有同類駕照的「汽車」標題,改寫標題項目的連結為 "add/[使用紀錄類型機讀名稱]/[汽車 nid]",把車輛的 nid 附在網址尾端送出到表單,就可以讓新增「使用紀錄」表單透過 nodereference_url 模組自動連到你要的車輛去。

不清楚一個表單中的兩個 nodereference_url 或 entityreference_prepopulate 能否分別處理不同層次的網址後綴 argument。
如果可以的話,可以在改寫標題連結的時候,把當前「駕駛」的 nid 也一起送出去,這樣就可以同時連結到兩個不同類型的 node 去了。

tky

我想你 A, B 之間的關連已經會做了,也建立了 views block,
應該利用一下 node reference 的預設值,搭配 arg(),就可以達成目的。

假設使用紀錄的 Content Type 叫做 record
然後已經有兩個 reference field : [A ref.] 用來記錄 A 的 nid, [B ref.] 用來記錄 B 的 nid
如同 tky 在第二段提到的,把你的 「新增記錄」 這個連結製作成 /node/add/record/[A:nid]/[B:nid]

把 A ref. 的預設值以 PHP code 方式寫入:

return array(
0=> array('value'=> arg(3))
);

同理,B ref. 裡寫入

return array(
0=> array('value'=> arg(4))
);

上面所用到的 arg() 這個函式可以很方便的幫你取得 drupal 路徑中的元素,
他的介紹在: http://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/arg/7

從第一個開始為 arg(0) ,所以用 arg(3) 跟 arg(4) 就可以幫你把兩個 nid 傳回作為預設值囉。

謝謝tky 以及 amouro 兩位先進的指導
不好意思,這麼久才回...
我試了好久,還是沒有成功
想再請教一下:
1.我目前利用views的contextural filter的功能,在「司機」的頁面產生一個block view,這個view可以撈出相同「駕照類型」的「汽車」
但這個view好像只能撈出「汽車」的nid,而沒辦法抓出「司機」的nid,所以沒辦法生成如amouro所提到的連結"/node/add/record/[A:nid]/[B:nid]"

2. node reference 好像沒辦法設定用php產生預設值的樣子,還是我搞錯了什麼呢?

1 的部分,你應該還需要加上一個 Relationship ,幫助把關聯的司機 nid 給叫出來。方便把你的 Views 畫面貼來看看嗎?

2 的話,我研究了一下,在D6 CCK 時有這個功能,但是 D7 的 Field 便不包含了。
即使安裝了 CCK for D7 也只能讓 List 類型的欄位使用。Node/User References 還是無解
但是針對 References 的部分,我找到一篇文章使用 hook_form_alter 的方式將運算過的值做為該欄位的預設值。
http://drupal.org/node/1028096
參考看看。

這是你一開始的規劃和要求:

A跟B共同有個類別叫做「駕照種類」, 我現在希望在檢視「司機」A的頁面中放一個block,當中會顯示相同「駕照種類」的「汽車」列表
列表中的每台汽車旁邊有個「新增記錄」的按鈕(連結),使用者點擊後,直接新增一筆「汽車使用記錄」,

例如我的司機Tom他只有機車駕照,旁邊的block中的列表顯示的是
sym 野狼125 新增記錄
kymco金勇125 新增記錄

以下是可能的作法:
1. 既然是在「司機」頁面置放區塊,撈出的資料就應該是「車輛」類型的內容才對。所以「過濾條件」那邊應該要改成「車輛」。
2. 你的「上下文過濾器」設定用網址或節點中的類別 tid 來過濾資料,這可以正確過濾出與該司機有同樣類別的「車輛」資料。
3. 但是你需要改寫「欄位」中的「標題」網址,把該司機與車輛兩者的 nid 填到網址結構中。由於你撈出的資料為「車輛」類型,所以你拉出 nid 欄位是屬於「車輛」的 nid。還要另外拉出當前司機的 nid。
4. 當前司機的 nid 用「關聯」是拉不出來的,而就算拉出來也會因為變成重複資料而沒有鑑別性(無法區別是司機還是車輛的 nid)。應該要利用當前司機頁面網址會帶有的 nid,取得司機的 nid。
5. 但是如何取得當前頁面 nid 會是一個問題。作法有很多種,我想到最無腦的一個方法就是再增加一個無用的「上下文過濾器」:內容: Nid
5.1 增加內容: Nid 這個上下文過濾器時,要將 When the filter value is NOT available 這個項目的值設成 "Display all results for the specified field"。這樣做的目的是確保因為用司機的 nid 作為過濾值而撈不到資料時(這是肯定撈不到任何資料的,因為「過濾條件」撈的「車輛」的內容,怎麼可能用「司機」的 nid 會撈的到呢)仍會顯示出所有區塊內容(車輛標題)。如此我們即能在不妨礙現有內容的情況下取得目前司機的 nid。
6. 在改寫車輛「標題」欄位的網址結構時,你現在應該可以看到「替換匹配模式」最底下會多出 %2、!2 兩個 token,前者是個代換符,會將第二個上下文過濾器(也就是當前頁面的 nid)置換成文章標題,後者則單純是過濾器的輸入值。這裡要選用 !2,因為我們要把 nid 的值傳出去。
7. 所以你改寫過後的網址結構應該會是像這樣: node/add/record/[nid]/!2 或者 node/add/record/!2/[nid],取決於你如何制定「紀錄」類型如何接收網址參數的順序。

這樣應該就可以了。試試看吧。

tky

感謝tky的熱心解惑,一直沒搞懂!2跟%2的作用,真是聽君一席話勝讀十年書啊!!
以下附上我在nid的設定,有類似需求的人可以參考一下
抱歉,我搞錯了,欄位那邊我填到!1,所以最後抓出來的是tid,不過設定為!2之後會抓不出值來
不過我另外發現一個方式,提供給大家參考
Contextual filter提供了一個filter,可以不影響原來的filter而取值,如下圖:
null filter
而這個filter的設定則可選擇"Content ID From URL",即可抓取原始頁面的nid了,設定如下:
null filter setting

我那 1-7 是空想,沒有實作過,很高興你可以自己嘗試不同的作法並回過來貢獻給社群。(因此才知道原來 context filter 也有 null 的項目可用,以前都沒注意過)

希望你能夠順利完成「自動填入表單」那部份的實作啦!(有成功的話可以回饋一下社群)

tky