Diskuze: Návrh tabulky/ek - odesílání zpráv
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.
Tvůrce
Zobrazeno 20 zpráv z 20.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.
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 report
em bych byl opatrnější, ten se dá uložit
přímo do tabulky příjemce ve formě počitadla.
Děkuji za návrh. Mohl bys mi, prosím tě, upřesnit, co přesně bude
message
.type
a
cover
.type
?
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
.
Jasně, děkuji za vysvětlení!
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
.
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?
Nemusí být nová. To počitadlo může být sloupeček v tabulce uživatelů/hráčů.
Děkuji za nápad s triggery. Sice jsem s nimi dělal prakticky poprvé, ale nakonec to funguje a funguje to skvěle.
Není zač. Triggery by se měly používat všude tam, kde se dělala denormalizace databáze.
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?
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é.
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
.
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
.
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.
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.
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.
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.
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.
Zobrazeno 20 zpráv z 20.