Diskuze: Návrh tabulky/ek - odesílání zpráv

PHP PHP Návrh tabulky/ek - odesílání zpráv American English version English version

Avatar
Martin Konečný (pavelco1998):

Ahoj.

Potřebuji navrhnout jednu nebo více tabulek pro odesílání zpráv dvěma způsoby:

  1. uživatel-uživatel
  2. uživatel-skupina

S tím, že uživatel uvidí příchozí, odeslané a skupinové zprávy.
Také bude mít každý uživatel možnost si zprávu smazat.
Když vytvořím jednu tabulku, vypadala by asi takto:

[message] (
id INT
author_id INT
recipient_id INT
subject VARCHAR()
content TEXT -- textový obsah zprávy
time DATETIME
report INT -- 1 = uživateli přijde oznámení, že má novou zprávu (stačí jen jiná barva odkazu)
type INT -- 1 příchozí, 2 odeslané, 3 skupinové
)

V takovém případě se 'subject' a 'content' uloží třeba 30x (když pošlu skupinovou zprávu 30ti lidem), což mi přijde poměrně zbytečné.

Nezná někdo lepší řešení?
Děkuji.

 
Odpovědět 22.12.2012 11:14
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

Zkus to rozdělit na dvě tabulky:

CREATE TABLE message (
   id int,
   subject text,
   content text,
   time datetime,
   type int);

CREATE TABLE cover (
   id int,
   mesage_id int,
   uzivatel_id int,
   type int);

Zpráva bude pouze 1× v tabulce message, vytvoří se k ní záznamy odesílateli i příjemci (resp. příjemcům) do tabulky cover.

S tím reportem bych byl opatrnější, ten se dá uložit přímo do tabulky příjemce ve formě počitadla.

Nahoru Odpovědět 22.12.2012 11:47
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):

Děkuji za návrh. Mohl bys mi, prosím tě, upřesnit, co přesně bude message.type a cover.type?

 
Nahoru Odpovědět 22.12.2012 20:35
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

message.type nebude

cover.type INT -- 1 příchozí, 2 odeslané, 3 skupinové

Odesílatel bude mít type 2, příjemce 1 nebo 3. Ke každému záznamu v message budou 2 záznamy v cover. Když příjemce "smaže zprávu", smaže se jeho záznam v cover. Když odesílatel "smaže odeslanou zprávu", opět se smaže jen jeho záznam v cover. Občas se smažou položky v message, na které není žádný odkaz v cover.

Nahoru Odpovědět 22.12.2012 20:48
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Martin Konečný (pavelco1998):

Jasně, děkuji za vysvětlení!

Editováno 22.12.2012 20:52
 
Nahoru Odpovědět 22.12.2012 20:52
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

Ještě malá ukázka, jak se budou vypisovat přijaté, odeslané a skupinové zprávy:

SELECT subject, content FROM message WHERE id IN (
    SELECT message_id FROM cover WHERE uzivatel_id = $myid AND type = 1
)

Jenom se to bude lišit podmínkou type. Samozřejmě se to dá vylepšit o některé údaje (např. kdo a komu v message), ale to snad zvládneš. Tyto údaje tam vlastně budou 2×. Jednou pro doručování (v cover) a podruhé pro evidenci (v message). V cover se to dá udělat i triggerem, který zároveň u příjemce zvýší počitadlo nepřečtených mailů. Jedinou tvou starostí při odesílání zprávy pak bude zapsat záznam do tabulky message.

Nahoru Odpovědět 22.12.2012 21:19
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):

Co se týká toho počítadla nepřečtených zpráv, pochopil jsem správně, že daný počet bude v nové tabulce?

 
Nahoru Odpovědět 23.12.2012 10:35
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

Nemusí být nová. To počitadlo může být sloupeček v tabulce uživatelů/hráčů.

Nahoru Odpovědět 23.12.2012 11:26
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):

Děkuji za nápad s triggery. Sice jsem s nimi dělal prakticky poprvé, ale nakonec to funguje a funguje to skvěle.

 
Nahoru Odpovědět 23.12.2012 15:40
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

Není zač. Triggery by se měly používat všude tam, kde se dělala denormalizace databáze.

Nahoru Odpovědět 23.12.2012 15:54
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

Ještě taková drobnost. Občas se řeší, že před uložením záznamu je nutné některý údaj vyhledat v jiné tabulce a záznam přidat pouze v případě, že je v té tabulce nalezen. Řešení v SQL je celkem jednoduché:

INSERT INTO message (author_id, recipient_id, subject)
    SELECT :myid, recipient_id, :subject FROM users
        WHERE name LIKE :recipient LIMIT 1;

-- :myid => id odesílatele
-- :subject => předmět zprávy
-- :recipient => jméno příjemce, které se má nahradit jeho id

A teď otázka: Dá se tato trivialita řešit v Dibi a podobných frameworcích nebo se to musí dělat více SQL dotazy? Jak by to asi vypadalo?

Nahoru Odpovědět 24.12.2012 13:44
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Kit
Kit:

Tak nic, už jsem to našel. SQL mi připadá přehlednější.

Nahoru Odpovědět 24.12.2012 14:01
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):

Dobrý nápad, nicméně mám stále v těchto dvou tabulkách problém, jak vložit ta data závisle na tom, zda existuje daný uživatel.
Prvně musím vložit do tabulky message a poté do tabulky cover (jejíž sloupec message_id se bude rovnat message.id). Jenže to první vložení musí proběhnout jen tehdy, že ten uživatel existuje, což je trochu zamotané.

 
Nahoru Odpovědět 24.12.2012 16:54
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

To první vložení do message bude viz výše. Ověřuje se tam proti tabulce users. Pokud adresát neexistuje, zpráva se nevloží, protože výsledek selectu bude prázdný. V případě úspěchu nastoupí trigger navázaný na message a vloží dva patřičné záznamy do cover.

Nahoru Odpovědět 24.12.2012 17:03
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

A aby toho nebylo málo, na cover bude navázán další trigger, který v případě přidání záznamu typu přijatá nebo skupinová pošta inkrementuje příjemci čítač došlé pošty v users.

Nahoru Odpovědět 24.12.2012 17:26
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):

Hmm, stále mě nenapadá způsob, jak to aplikovat, když v tabulce messsage jsou sloupce id, subject, content a time. Pokud použiji ten SELECT, hlásí mi databáze chybu, že se snažím vybrat více hodnot, než kolik mohu vložit.
Možná je to triviální řešení, ale za boha nemohu přijít, jak to udělat.

 
Nahoru Odpovědět 24.12.2012 17:40
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):

Ten trigger na čítač mám již hotový a funguje (když jsem to zkoušel vložit manuálně v Admineru). Jen mám teď problém s vložením té zprávy od uživatele.

 
Nahoru Odpovědět 24.12.2012 17:41
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

Za INSERT INTO máš v závorce 3 parametry. Za tím SELECTem musí být výběr 3 sloupců z druhé databáze. Některé můžeš nahradit konstantou nebo subselectem, ale počet musí souhlasit.

Místo čísla 3 si dosaď jakékoli jiné číslo.

Asi tam přece jen budeš muset přidat i sloupce author_id a recipient_id, aby se ten trigger měl čeho chytit.

Nahoru Odpovědět 24.12.2012 17:46
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Odpovídá na Kit
Martin Konečný (pavelco1998):

Tak jo, děkuji za pomoc. Jestli by nebylo nakonec nejlepší vše udělat prostě do jedné tabulky s tím, že se ten předmět a obsah bude opakovat.

 
Nahoru Odpovědět 24.12.2012 17:55
Avatar
Kit
Redaktor
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Kit:

Uvědom si, že jsme tady řešili víc problémů, než jen duplicitu jednoho záznamu. Jeden INSERT je vždy rychlejší než dva a máš garantovánu konzistenci. Kromě toho se normalizace hodí vždy.

Nahoru Odpovědět 24.12.2012 18:04
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 20 zpráv z 20.