1)Definetely是,ID的應該是自動自動遞增,除非你提供一個主鍵的不同手段這是獨一無二的。你得到的插入或者與從MySQL直接mysql_insert_id()
或LAST_INSERT_ID()
的ID,所以要張貼一些連接的信息,你可以做任何
mysql_query("INSERT INTO table1 ...")
$foreign_key=mysql_insert_id(); //this gives you the last auto-increment for YOUR connection
或者,但只有當你絕對肯定沒有其他人寫入表在平均時間或有過交易的控制,插入後做:
$foreign_key=mysql_query("SELECT LAST_INSERT_ID()")
INSERT INTO table2 message_id=$foreign_key
,或者不拉FK到PHP,都在同一個交易(我也建議包裹SQL作爲交易太)的東西如:
"INSERT INTO table1...; INSERT INTO table2 (message_id,...) VALUES(LAST_INSERT_ID(),...)"
根據您的語言和mysql庫,您可能無法發出多重查詢方法,因此您最好使用第一種方法。
2)這可以有很多方法,取決於你是否也需要回復所有接收者(例如會議),以線程/類似論壇的方式答覆,客戶端是否可以存儲上次檢索消息/ ID(例如,在cookie中;也影響你是否真的需要「讀」字段)。
「私人聊天」方法是最簡單的方法,那麼您可能更好的方法是將消息存儲在一個表中,並將來自到的關係存儲到另一個表中(或使用JOIN),或者只是重新填充在一個表中的消息(因爲現在存儲便宜)。因此,簡單的模型是一個表:
table: message_body,from,to
$recepients=array(1,2,3..);
foreach($recepients as $recepient)
mysql_query("INSERT INTO table (...,message_body,from,to) VALUES(...,$from,$recepient)");
(複製消息等,只有recepient變化)
或
message_table: id,when,message_body
to-from-table: id,msg_id,from,to
$recepients=array(1,2,3,...);
mysql_insert("INSERT INTO message_table (when,message_body) VALUES(NOW(),$body)");
$msg_id=mysql_insert_id();
foreach($recepients as $recepient)
mysql_query("INSERT INTO to-from-table (msg_id,from,to) VALUES($msg_id,$from,$recepient)");
(消息中插入一次,存儲關係和FK對於所有收信人)
然後每個客戶端存儲他/她接收到的最後一個message_id(默認爲0),並且假設所有先前的消息已經被讀取):
"SELECT * FROM message WHERE from=$user_id OR to=$user_id WHERE $msg_id>$last_msg_id"
,或者我們只需要注意最後的輸入時間從用戶和然後查詢任何新的消息:
"SELECT * FROM message WHERE from=$user_id OR to=$user_id WHERE when>='".date('Y-m-d H:i:s',$last_input_time)."' "
如果你需要一個更會議室套裝或論壇胎面類似的方法,並且需要跟蹤誰讀取或不讀取消息,您可能需要跟蹤所有涉及的用戶。
假設在一個「多用戶會議」中不會有數百人蔘加會議,我會用一張桌子來發送消息,並使用「逗號分隔和包裹列表」技巧,我用它來存儲標籤。
id autoincrement (again, no need for a separate message id)
your usual: sent_at, title (if you need one), content
sender (int)
recepients (I'd go with varchar or shorter versions of TEXT; whereas TEXT or BLOB gives you unlimited number of users but may have impact on performance)
readers (same as above)
爲受助/讀者場的祕訣是填充它們以逗號分隔的ID列表,再敷在逗號(我會dulge到爲什麼後來)。
因此,您必須再次將收件人的id收集到數組中,例如, $受助=陣列(2,3,5)和修改插入:
"INSERT INTO table (sent_at,title,content,sender,recepients) VALUES(NOW(),'$title','$content',$sender_id,',".implode(',', $recepients).",')"
你表中的行狀
...發件人| recepients
... 1 | ,2,//單用戶消息
... 1 | ,3,5,//多用戶消息
選擇具有的$ USER_ID = 2你去
SELECT * FROM table WHERE sender=$user_id OR INSTR(recepients, ',$user_id,')
以前我們包裹受助的內爆列表中的ID,例如用戶的所有郵件'5,2,3'變成',5,2,3',並且INSTR在這裏告訴'2,'是否作爲子字符串被包含在某處 - 自從尋求'2','2'或'2' '可能會給你錯誤的肯定例如' 34,56','1 **,2 34','9,45 2,** 89'相應地 - 這就是爲什麼我們必須首先包裝清單。
當用戶讀取/接收他/她的消息,則其ID添加到讀者列表,如:
UPDATE table SET readers=CONCAT(',',TRIM(TRAILING ',' FROM readers),',$user_id,') WHERE id=${initial message_id here}
導致:
...發件人| recepients |讀者
... 1 | ,2, | ,2,
... 1 | ,3,5, | ,3,5,2,
或者我們現在可以修改初始查詢添加一列「is_read」陳述用戶是否事先閱讀信息,或不:
SELECT * FROM table WHERE INSTR(recepients, ',$user_id,'),INSTR(readers, ',$user_id,') AS is_read
收集信息的IDS結果並一次性更新「recepients」字段
"UPDATE table SET readers=CONCAT(',',TRIM(TRAILING ',' FROM readers),',$user_id,') WHERE id IN (".implode(',' ,$received_msg_ids).")"
感謝您的答覆,我還挺喜歡‘包裝清單’的把戲,不過,我有一個問題:使用這種方法,我怎樣才能跟蹤郵件實際被讀取的時間戳,換句話說,除了跟蹤「is_read」,我還想跟蹤每個收件人的「when_read」。 – Dodinas 2009-07-29 21:54:08