NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Like systém pro nepřihlášené uživatele

V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Dominik Šnýdr:7.4.2015 20:28

Ahoj,

již delší dobu přemýšlím nad vytvořením "lajkovacího" systému, klasické přidávání plusů / mínusů k jednotlivým příspěvkům, které jsou uloženy v databázi. Tento systém by měl fungovat pro kteréhokoliv návštěvníka stránek, tudíž registrace na stránkách by neměla být podmínkou pro udělení + / - k příspěvku.

Vymýšlel jsem pár situací, které ovšem mají nedostatky:

1.) Počítám s vytvořením dvou tabulek v MySQL: jedna pro příspěvky a druhá pro počty lajků. Propojené to bude přes id_příspěvku. Při každém udělení lajku, by se vytvořil záznam v tabulce s lajkama. Celkový počet lajků k jednotlivým příspěvkům by se získával přes GROUP funkci z tabulky lajků. Je toto vhodné řešení? Nebo by bylo lepší udržovat si pouze jednu tabulku a do ní přidat sloupec "like" a ten by byl navyšován respektive snižován o jedničku?

2.) Vycházejme z předpokladu, že fungují výše popsané vztahy v databázi... Nastává problém, že návštěvník může lajkovat neomezeně. Takže při dlouhém klikání, či obnovování může jednomu příspěvku naklikat x-tisíc lajků za minutu. Což považuju za destruktivní pro celý systém i databázi. Jak ale zabránit tomu, aby člověk (respektive zařízení) mohl jeden konkrétní příspěvek ohodnotit pouze jednou za určité časové období? S tím že to hodnocení by se počítalo pouze právě k tomu jednomu příspěvku => nezabrání mu to hodnotit jiné, které ještě nehodnotil...

Jde toto vůbec nějakým způsobem provést, nebo jsou mé představy naivní?

Opravdu moc děkuji za jakékoliv tipy :) :)

 
Odpovědět
7.4.2015 20:28
Avatar
Adam Ježek
Tvůrce
Avatar
Adam Ježek:7.4.2015 20:39

V případě přidání sloupečku like ke komentářům asi s 2 situací nic neuděláš, maximálně tak do session uložit co lajknul, ale po zavření prohlížeče by moh zase...
Ještě mě napadá tam mít uloženej dlouhej string se všemi ID uživatelů, co již hlasovali, ale to je asi pitomost
Pokud by jsi měl dvě tabulky, tak by to bylo jednoduché, prostě by si při lajku zjistil, jestli v tabulce lajků není řádek, kde je příspěvek s tímto ID a zároveň je u něho záznam s ID uživatele a vynadáš mu že nemůže...

Funkci GROUP neznám, každopádně já bych to řešil pomocí COUNT (spočítal bych záznamy s ID příspěvku, kde je v like true, spočítal záznamy s like false, odečet a hotovo (za předpokladu že tabulka like by měla sloupce id příspěvku, id uživatele a like, kde by bylo T/F, podle toho, jestli dal like/dislike) teď sem v SQL dlouho nedělal, tak to možná bude špatně, ale mělo by to vypadat nějak takhle:

SELECT COUNT(*) FROM likes WHERE prispevekID=$pripevekId and like=True

) . Nevím, co je vhodnější, GROUP neznám, každopádně potřebuješ počet, takže mi COUNT příde logické.
//teď ni dlošlo, že uživatel nemusí být přihlášen, takže když nebude registrován, tak bych místo jeho ID použil aspoň jeho IP. Sice třeba ze školy (která mívá jednu IP pro všechny zařízení) si lajkne jeden člověk, ale je to asi jedinný způsob, jak zamezit tomu nekonečnému lajkování

Editováno 7.4.2015 20:41
Nahoru Odpovědět
7.4.2015 20:39
Počkej chvíli, poradím se s křišťálovou koulí.
Avatar
Jan Lupčík
Tvůrce
Avatar
Odpovídá na Dominik Šnýdr
Jan Lupčík:7.4.2015 20:42

Udělej si ty dvě tabulky. Nemůžeš přeci všechno strkat do jedné. :)

Příspěvky jsou jasné. V druhé tabulce pro "lajky" si udělej sloupce pro to id komentáře, id "lajku", +/-, datum a IP. IP kvůli jedinečnosti. :)
Pak z toho data a IP si to můžeš odvodit a podle toho kontrolovat. No a podle id komentáře budeš počítat like a mínusy. :)

Snad jsem to napsal srozumitelně ...

//EDIT: Ach jo, zas byl někdo rychlejší. :(

Editováno 7.4.2015 20:42
Nahoru Odpovědět
7.4.2015 20:42
TruckersMP vývojář
Avatar
Odpovídá na Dominik Šnýdr
Martin Konečný (pavelco1998):7.4.2015 20:42

Ahoj,

  1. to záleží minimálně na tom, jestli chceš pak zobrazit i další informace o uživateli, co dal like. U přihlášeného třeba jméno, u všech třeba datum, IP apod. V takovém případě se víc hodí druhá tabulka, do které budeš jednotlivé lajky insertovat.

Pokud bys tyto informace nechtěl, pak bych se spíše rozhodl z hlediska výkonu. Myslím, že dělání UPDATE by mělo být o něco rychlejší, než provádění hromady INSERTů každou chvíli. Ale to by se spíš mělo týkat situací, kdy je velký počet liků každou chvíli (třeba jako má FB :D).

Při situaci s INSERTy pak stačí akorát COUNT(*) AS pocetLiku WHERE comment_id = ...

  1. U nepřihlášených uživatelů to zřejmě nejde 100% zamezit. Můžeš si ukládat např. čas a IP a "blokovat" udělování liků dané IP na určité časové období (což by vyžadovalo řešení s druhou tabulkou a INSERTy).

V tomto případě nepůjde použít unikátní klíč, ale můžeš použít trigger BEFORE INSERT a zkontrolovat, zda v daném časovém období již like z dané IP nepřibyl.

Daný INSERT pak můžeš pomocí triggeru zastavit pomocí signálu:

https://dev.mysql.com/…/signal.html

Něco ve smyslu

CREATE TRIGGER nazev BEFORE INSERT ON tabulka_s_liky
BEGIN:

SET @actualTime = NOW();

-- mělo by vytáhnout záznam s posledním časem pro danou IP
SET @lastLikeTime = (
  SELECT `time` FROM `like`
  WHERE `ip` = NEW.ip
  ORDER BY `time` DESC
  LIMIT 1
);

IF DATE_ADD(@lastLikeTime, INTERVAL tvoje_casove_obdobi SECOND) > @actualTime THEN
  SIGNAL SQLSTATE '045000'
  SET MESSAGE_TEXT = 'V tomto komentáři jsi likoval nedávno';
END IF;

END;

Psal jsem to z hlavy, takže to syntakticky nemusí být správně. Návodů na triggery je na netu hromada :)

Nahoru Odpovědět
7.4.2015 20:42
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
adas
Tvůrce
Avatar
Odpovídá na Dominik Šnýdr
adas:7.4.2015 20:46

1.) Je lepší to dát do jedné tabulky se sloupečkem "like". Však ty potřebuješ jenom výsledné hodnocení příspěvku, ne?

2.) Založ si tabulku, kde budeš ukládat, který návštěvník lajkoval. Tam bys ukládal buď IP adresu, nebo pokud by byl přihlášený, tak id uživatele a samozřejmě id příspěvku.
//EDIT: Ups. někdo už odpovídal. No, snad příště.

Editováno 7.4.2015 20:49
 
Nahoru Odpovědět
7.4.2015 20:46
Avatar
Dominik Šnýdr:7.4.2015 20:59

Děkuju mnohokrát :) Jste fakt šikulové :) !!

Funkce GROUP se používám v SQL pro vytvoření právě té skupiny, ze které chci počítat COUNT()... :) V MySQL to asi není nutné.. to teď nevím z hlavy :)

Vytvoření té druhé tabulky s IP a časem bude asi nejlepší varianta :) Jinak, když už jsem vznesl dotaz... IP adresa je jediný identifikátor nepřihlášeného uživatele, který jde pro tyto účely použít, chápu to správně? :)

 
Nahoru Odpovědět
7.4.2015 20:59
Avatar
Jan Lupčík
Tvůrce
Avatar
Odpovídá na Dominik Šnýdr
Jan Lupčík:7.4.2015 21:04

Ano, akorát někdo se může připojit ze školy, kde ty počítače mají stejnou IP. Tam v tom je problém, ale jinak v pohodě. :)

Nahoru Odpovědět
7.4.2015 21:04
TruckersMP vývojář
Avatar
Adam Ježek
Tvůrce
Avatar
Odpovídá na Dominik Šnýdr
Adam Ježek:7.4.2015 21:05

Pokud se nepletu, tak existuje v PHP i funkce gethostname(), která ti vrátí název počítače, na kterém je uživatel připojen, ale pokud budeš mít sérii BFU, kteří si nechali počítač jak je z výroby, tak by se moh u všech jmenovat třeba HP (netuším jak si to výrobci pojmenovávaj), nebo někteří tam zase mají franta-pc, a frantů může bejt víc.
Možná, pokud se s tim chceš patlat, tak bych ještě při shodě IP zkusil rozdíl názvu počítače (tím vyřadíš to že v celé škole si lajkne jeden člověk)

Nahoru Odpovědět
7.4.2015 21:05
Počkej chvíli, poradím se s křišťálovou koulí.
Avatar
Richard
Člen
Avatar
Richard:8.4.2015 0:15

Řešení je jednoduché, použít jak celkový počet, kde budeš při hlasování přidávat odebírat 1 a zvláštní tabulku, kde budeš uchovávat informace o hlasování (uživatel, ip, id příspěvku, atd) jak tu už někdo psal. Tedy při hlasování ověříš, zda ten člověk již nehlasoval (nepoužívat pouze ověření ip, vhodné je připojit i cookies, otisk prohlížeče a třeba i hostname), pokud nehlasoval, zapíšeš do tabulky a u příspěvku přidáš, odebereš hodnotu.

Důležitá věc co tu nezazněla - nepoužívat count, ani group, jednoduše proto, protože je to zbytečné, tím že budeš uchovávat aktuální stav (+12, -6 atd) se vyhneš vypočítávání při každém požadavku. Ano, existují indexy a ty funkce jsou rychlé, při pár tisících hodnot je to stále rychlé, nicméně pokud systém nabobtná a těch záznamů bude najednou milion a na jedné stránce zobrazíš 50 příspěvků, začneš pociťovat problémy s výkonem, při desítkách requestů za sekundu budeš mít opravdový problém.

Každý kdo tyto a podobné hodnoty vypočítává online, nechť si dá facku. Nehledě na to že když se bude uchovávat hodnotu v tabulce u příspěvku, ušetří se jeden sql dotaz.

Editováno 8.4.2015 0:16
Nahoru Odpovědět
8.4.2015 0:15
$action = $_GET['Life']; | Když dáš mínus, napiš proč!
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 9 zpráv z 9.