Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][MySQL]Informowanie o nowych postach w temacie.
Forum PHP.pl > Forum > PHP
Kokohelp
Jak w temacie. To podstawa na każdym forum. Jeśli ktoś napisze, a my się zalogujemy to np. obok tematu wyświetla się kopertka, że w temacie pojawił się nowy post. Niby takie oczywiste, ale patrząc od strony kodu dość skomplikowane.
Szukałem tego już naprawdę długo i nic. Pomyślałem, że sam rozpocznę temat z tym pytaniem.

P.S. Piszę forum od samych podstaw. Nie lubię korzystać z gotowców. Jak coś robię, to sam.
zend
Samochód też sam składałeś? Niby co takiego skomplikowanego w kodzie? Skoro masz kilka pomysłów to czemu nie napisałeś ani jednego?
Kokohelp
To jakiś problem, że chcę się czegoś nauczyć? Klikając na serwerze zainstaluj moduł forum, nic się nie nauczę. W kodzie może nic skomplikowanego, bo prototyp napisałem, ale nie do końca taki jaki ma być. Gdybym interesował się samochodami to na pewno też bym go rozłożył i zobaczył co ma w środku. Na razie zostańmy przy programowaniu. To forum pod tytułem "php", a nie "motoryzacja". Jeszcze jakieś propozycje lub algorytmy?

P.S. Odpowiedź na twoje pytanie znajduje się w opisie tematów. Cytat. "Mam kilka pomysłów ale są mało wydajne....".
zend
Pisanie czegoś takiego jak forum na włąsną rękę nie jest dobrym pomysłem, bo to naprawdę duża aplikacja do napisania przez jedną osobę. Czemu napisałeś temat w gotowych rozwiązaniach skoro piszesz własny? Przedstaw pomysły to będzie można coś doradzić
Kokohelp
Tu przyznaje rację. Popełniłem dość błachy błąd, ale tylko tu znalazłem dział związany z forum. Czy ktoś napiszę na temat tego tematu?
A co do pisania samemu. Radzę sobie.
zend
Jeśli napiszesz coś więcej (własne pomysły, kod, sprecyzujesz o co Ci chodzi) to napewno ktoś napisze, a jeśli nie to dalej będę Cię męczył winksmiley.jpg
Kokohelp
A więc... Potrzebuje jakiś przykład powiadamiania o nowym poście w temacie, przez np. wyświetlającą się kopertę obok tematu.
Stworzyłem kod który:
1 Ściąga daty:
- ostatniego wylogowywania
- powstania ostatniego postu
2 Sprawdza czy data ostatniego postu jest "większa" od ostatniego wylogowywania:
- jeśli tak koperta się wyświetla
- jeśli nie to koperta się nie wyświetla

W czym problem? Otóż jeśli wejdziemy do tematu to koperta nie znika. Znika dopiero po wylogowaniu.
Dlaczego więc nie ściągnę daty ostatniego wejścia do tematu?
Odpowiedź jest banalna. Bo nie wiem jak do tematu przypisać daty wejść poszczególnych użytkowników do tematu.
I tu proszę was o pomoc. Jak to zrobić?
zend
Musisz jeszcze zapamiętać np w ciasteczkach że user przeczytał dany temat, choć lepszym wyjściem będzie trzymanie tych danych w bazie, dodajesz tabele z relacją user - wątek, jeżeli ktoś dopisze coś do wątku usuwasz tą relację. A w momencie odczytu pobierasz dane z tej tabelki, jeżeli istnieje odpowiadający rekord to user czytał. Datę ostatniego logowania możesz sobie w tym przypadku odpuścić (tzn sprawdzanie)
Kokohelp
Troszkę jaśniej bym poprosił. O cookies myślałem, ale szukałem jeszcze czegoś innego właśnie z bazą. To co ty piszesz może zadziałać, ale nie do końca rozumiem co chcesz mi przekazać.
Jak wykonać twój pomysł. Jakiś algorytm? Przepis z ogólnymi krokami.
zend
Tworzysz tabelę w której przechowywujesz id użytkownika i id postu oraz status. Użytkownik czyta post to status ustawiasz status na 1 (lub wstawiasz relację oraz ustawiasz status na 1) jako przeczytane, wchodzi inny user, dopisuje posta, to musisz ustawić wszystkie statusy relacji związane z tym wątkiem na 0 wtedy użytkownicy będą wiedzieć że brali udział w wątku oraz że coś się zmieniło. Przy wybieraniu danych sprawdzasz czy status istnieje, jeśli tak to zaznaczas że user brał udział, i sprawdzasz jeszcze czy ktoś coś dopisał (status 1 lub 0)
Kokohelp
No ale dla każdego użytkownika musisz mieć własny rekord w bazie i nie zapomnij o dodawaniu następnych tematów. Jak te problemy rozwiązać?
zend
Cytat(Kokohelp @ 7.06.2010, 21:25:37 ) *
nie zapomnij o dodawaniu następnych tematów. Jak te problemy rozwiązać?

Nie zabaardzo rozumiem o co Ci chodzi.. Ba! Nie jeden, a tyle rekordów ile wątków przeczytał! Nie musisz wybierać zawsze wszystkich relacji, możesz ograniczyć ich ilość korzystając z `topic_id` IN(1,2,3)

Edit
Nie wiem czy dobrze zrozumiałem, ale czy chodzi Ci o sytułację kiedy user nie przeczyta tematu? Wtedy nie musisz dodawać relacji, dobiero jak przeczyta to dodasz/zaktualizujesz
Kokohelp
No mniej więcej wiem. Ja bym to zrobił tak. Tworzę tabele która, przechowuje id_user i is_topic.
1. Ktoś pisze pierwszy raz w temacie. Nic się nie dzieje w bazie (nic nie dodajemy).
2 Jeśli w bazie nie ma nic na temat tego, że temat został przeczytany to koperta się wyświetla.
3. Ktoś wchodzi i dla tego kogoś powstaje rekord w bazie, że on przeczytał.
4. Powtarza się ta sytuacja u innych.
5. Ktoś pisze w tym temacie i zatwierdzając wysłanie usuwa wszystkie rekordy związane z wyświetlaniem koperty z id_topic tego tematu.
6. Sytuacja się potarza.
Jeszcze to troszkę podrasuje. Ale dziękuje nie tyle za natchnienie, bo już o tym myślałem, a bardziej za zmuszenie do troszkę innego spojrzenia na tą sprawę. Na razie temat do zamknięcia.
zend
Nie usuwaj tylko ustawiaj status! Bo stacisz historię kto co czytał!
Kokohelp
Zastanowię się. I tak dziękuję.
thek
Jak dla mnie lepiej podejść "od tyłu". Zapisywać informację w bazie o tym, co jeszcze nieprzeczytane. Bierzesz w momencie założenia konta datę i ustawiasz ją jako "bazową". Co przejście między stronami czy co ile tam się chce należy do tabeli wrzucić posty z datą wyższą niż bazowa i bazową ustawić na czas gdy było sprawdzenie. Posty uchwycone jako nowe dla owego usera umieszczamy w tablicy z nieczytanymi. Jeśli dany temat (strona) zostanie obejrzany, usuwa się z tabeli należące do niego nieczytane posty. W sytuacji gdy przy przejściach liczba przekroczy określoną granicę, przykładowo 300 nieprzeczytanych, usuwa się najstarsze i informuje o tym użytkownika. To ostatnie oczywiście ze względów wydajnościowych. Wyobraź sobie choćby kilkuset userów i po 500 możliwych postów dla każdego... 500*500 = 250.000 rekordów możliwych w tej tablicy.
Ta tabela jest mocno używana, więc od jej wydajności wiele zależy i tu właśnie trzeba kombinować... Jak nie przeciążyć bazy przy wielu userach. Tabela postów oraz postów nieczytanych będzie bowiem mocno użytkowana. Notoryczne odczyty postów wymagają wręcz proszą się o jakiś indeks na polu czasu zapisu/aktualizacji posta. Tabela nieczytanych z kolei prosi się o indeks na polu usera.
Taki układ pozwala na ciągle porównywanie "daty bazowej" i tabeli postów pod kątem nowych. Łatwo też zrobić czyszczenie konkretnych podfor i całego forum z nieprzeczytanych.
Jest to dość obciążające rozwiązanie, ale dobre przemyślenie sprawy pozwoli na pewne optymalizacje zapytań i redukcję obciążenia. Trudno liczyć tu na cache bazy lub jakikolwiek inny bo po prostu dane są zbyt zmienne. Tutaj pomaga wszelka optymalizacja odczytu i zapisu w bazie. Ja rzuciłem pomysł. Implementacja należy do Ciebie smile.gif
Dodam, że sam pomysł to tylko analiza działania kilku for z jakimi miałem do czynienia, bez spojrzenia w ich kod źródłowy. Programista powinien umieć "widzieć" sposoby rozwiązania, analizując zachowanie nie swojego kodu. Mam nadzieję, że z czasem zaczniesz widzieć głębiej smile.gif
Kokohelp
Też dobre rozwiązanie. Rozwiązać jest, dużo, ale chyba łatwiejszym i mniej obciążającym serwer będzie mój pomysł. W którym jak ktoś wejdzie to zostawia po sobie ślad, a jeśli ktoś napisze to ten ślad usuwa. Chciałbym zauważyć, że korzystam z darmowego serwera friko.pl. Jak wiadomo darmowe bazy nie zawsze są szybkie.
thek
Zauważ, że ten "ślad" tyczy każdego tematu i jedyna informacja jaką posiadasz to "który temat ma ślad aktywności". Przy rozrastaniu się forum liczba ta zacznie się robić coraz większa. W pewnym momencie liczba tematów oznaczonych jako przeczytana zrobi się znacznie większa niż nieprzeczytanych. Stąd też lepsze jest "oznaczanie" tematów nieprzeczytanych. Problem z tym, jak aktywny ma być Twój system. Zauważ, że gdy operację sprawdzenia postów opisaną przeze mnie ograniczymy do momentu logowania jedynie to upraszcza się ona tak naprawdę do tego co Ty opisałeś jako zostawianie śladu. Nie jest powiedziane, że musisz koniecznie co przeładowanie strony uruchamiać sprawdzanie nowych postów. Możesz w sesji ustawić licznik, który tę operację będzie przeprowadzał raz na X przejść. Ja opisałem by robić co przejście, ale tylko dlatego, że użytkownik może obejrzeć wtedy temat najaktualniejszy. Poza tym może się okazać, że od czasu sprawdzenia mógł odwiedzić temat z nowymi postami, ale następna operacja sprawdzenia ten temat mu pokaże jako z nowymi, choć de facto już go on czytał. Liczba więc co ile się odświeża tabele z nowymi postami powinna być względnie niska.
Kokohelp
No twój pomysł wydaje się dobry, ale przyznam, że nie za bardzo go rozumiem. Tak jak wcześniej mówiłem dopiero się uczę. Bardzo bym prosił o jakieś jaśniejsze przedstawienie pomysłu.
thek
Ok... Wezmę napisze krok po kroku innymi słowami smile.gif
W profilu lub którejś z głównych tabel powinna być informacja o tym, kiedy ostatnio zaszło sprawdzanie pod kątem nieczytanych postów, nazwijmy ją "czasem bazowym". Jeśli to nówka konto to jest to data założenia, by nie wypełniać niepotrzebnie tabelki która za to odpowiada, a inaczej pisząc - user startuje z czystym kontem smile.gif
Tabela nieczytanych ma wpis z id_usera i id posta. Resztę można w sumie doJOINować i uzyskać, ale dla szybkości można też dorzucić kosztem miejsca choćby id_tematu.
Gdy następuje sprawdzenie to wyciągamy z tabeli postów wszystkie, których data powstania lub aktualizacji (to z aktualizacją nie jest obligatoryjne i można odpuścić sobie) jest większa bądź równa "czasowi bazowemu". Posty te umieszczamy w tabeli nieczytanych i zmieniamy "czas bazowy" na czas, kiedy nastąpiło sprawdzenie. Nawet jeśli posty nie zostały znalezione. Czas ten można dla szybkości dodatkowo jeszcze trzymać w sesji, by nie pobierać go za każdym razem z bazy przy zapytaniach. Jeśli user odwiedzi jakiś temat z nieczytanym postem, usuwamy wpis tyczący tego posta u tego usera. Jeśli topic ma dużo stron, trzeba będzie określić czy wszedł na właściwą stronę, co niestety odbije się nieco na wydajności. Ale można to odpuścić i wejście po prostu na temat można ostatecznie uznać za przeczytanie go.
Sprawdzenie można w różnym czasie przeprowadzić. Na pewno podczas logowania się i... kiedy chcemy tak naprawdę smile.gif Można robić to co każde przejście na podstronach, można raz na ileś takich przejść. Zależy jak mamy mocno zamiar używać bazy i jak aktualne dane muszą być. Można porobić linki w stylu "Oznacz temat/subforum/forum jako przeczytane" i ważne by określić limit postów. Nie chcesz chyba by ktoś wchodząc po roku miał kilka tysięcy takich winksmiley.jpg Zostawiasz wtedy tylko najstarsze (przepraszam... najświeższe, najnowsze) z iluś dni lub do określonego limitu
Plusem tego rozwiązania jest rozbicie całego procesu na w sumie proste zapytania i całość jest dość łatwa w implementacji. Minusem niestety jednak obciążenie bazy dużą ilością prostych zapytań.

Tak przy okazji przeniosę temat, bo nie tyczy on gotowych rozwiązań. Piszesz własny skrypt i pytasz o sposoby implementacji w PHP, więc do tego działu on przynależy.
set4812
Może ja cos zaproponuje ale nie wiem czy jest mozliwe tongue.gif
To kazdego tematu w bazie jest pole gdzie sa przechowywane id uzytkownikow którzy czytali dany temat tongue.gif nowy post w temacie edycja uzytkowników którzy czytali. Jak to edytowac, moze wyciagnac z sesji id i uzytkownik gdy czyta dodaje swoje id do reszty tongue.gif
thek
Kilkuset userów i kilkaset teatów. Widzisz problem? Nie To rzucę inny motyw. Ktoś czytał temat. Zostało to oznaczone jako przeczytane. Ktoś dodał nowy post. Co robimy? Czyścimy owo pole? Czy robimy coś innego? Jak uzyskamy teraz zestawienie dla usera, że ma nieprzeczytanych X postów? Możemy najwyżej nieprzeczytane wątki policzyć, a i tak musielibyśmy jakiś silnik mieć pozwalający zadecydować czy temat był czytany czy nie. Serializowana tablica? Relacja wiele-do-wielu. Wiesz.. Łatwo się rzuca pomysły, ale spójrz nieco jeszcze na późniejszą implementację. Nie wszystkie pomysły mają sens smile.gif Jak sobie wyobrażasz oznaczenie całego forum jako przeczytanego? Pobrać id wszystkich topiców i... rozwiązanie z wiele-do-wielu... dodać X rekordów z id tego usera i topiców. Wersja straszna z serializowaniem - odczytać wszystkie serializowane tablice tematów, zrobić unserialize, dodać id-usera, serializować, zapisywać. baza przeżyje jeszcze gorszy horror niż w przypadku kontroli nowych postów co przejście usera między stronami. Po prostu ją zajedziesz.
Kokohelp
Teraz czaję. No ale jak ustawić limit . Jest na to sposób, czy muszę co jakiś czas czyścić bazę?
P.S. O przeniesienie sam miałem poprosić smile.gif
P.S.2 haha.gif Ten post tyczy się twojej poprzedniej wypowiedzi, tej z informacją, że przenosisz temat.
thek
Limit to po prostu odgórna liczba. Najprościej zrobić to tak, że podczas sprawdzania istnienia nowych postów automatycznie sprawdzasz też liczbę już w tabeli będących. Na podstawie tej ilości nadmiar wyrzucasz.
Kokohelp
Dobra. To już tam pestka. Ok dzięki za odp. Długo z tym problemem chodziłem, a teraz niedługo wakacje i mam trochę czasu na to.
Temat do zamknięcia.
thek
To podpowiem Ci JAK szybko zrobić usuwanie do określonego limitu używając do tego DELETE. Normalnie DELETE posiada także LIMIT, ale nie w postaci LIMIT od, ile tylko niestety LIMIT ile. Dlatego nie można zrobić choćby w DELETE (...) LIMIT 500, jakaś_ogromna_liczba. Da się jednak to obejść naokoło. Wystarczy wiedzieć ile user w danej chwili ma postów i... odwrócić kolejność oraz posłużyć się odejmowaniem winksmiley.jpg Jeśli wiemy, że user ma nieprzeczytanych 754 posty w sumie a limit ustawimy na 400 to z tabeli nieprzeczytanych musimy usunąć 354 najstarsze. Ustawiamy więc kolejność tak, by najstarsze były pierwsze i LIMIT ustawiamy na 354. A jakie posty są najstarsze? Te z najniższymi id. Robimy więc:
DELETE FROM nieczytane WHERE id_usera = ileś_tam ORDER BY post_id ASC LIMIT różnica_między_limitem_a_liczbą_nieczytanych_w_sumie
Wystarczy to uruchamiać kiedy suma nieczytanych jest większa od limitu gdzieś na samym końcu operacji sprawdzania nieczytanych postów.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.