[PHP] reeds bezochte en nieuwe topics en berichten

Pagina: 1
Acties:
  • 166 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Beste mensen,

Ik zit met het volgende probleem:

Ik ben mijn eigen forum aan het bakken in php.

Nu vraag ik me af hoe ik bij kan houden welke gebruiker welk topic al eens bekeken heeft en of er nieuwe berichten zijn binnen een topic die een bepaalde gebruiker nog niet heeft gezien.

Hoe wordt dit bijv. bij GoT of bij PHPBB gedaan? Is hier gewoon een tabel voor in de database? dat is natuurlijk wel een leuke optie, maar het lijkt me dat dat ERG veel records oplevert.

Is er misschien een andere manier om het bij te houden per gebruiker?

Alvast bedankt!

Acties:
  • 0 Henk 'm!

  • HyperioN
  • Registratie: April 2003
  • Laatst online: 24-05 15:42
Zoek maar eens naar sessies

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Maar een zelfde sessie is toch niet bereikbaar als men later weer het forum benadert?

Of is een sessie met zn variabelen op te slaan ofzo. Dat dan dmv een sessieID per user een eerdere sessie terug te halen is.

Of denk je misschien aan het gebruik van cookies ofzo. Daar moet ik me nog wel even in verdiepen namelijk. Ik weet niet precies hoe die werken.

Acties:
  • 0 Henk 'm!

  • disjfa
  • Registratie: April 2001
  • Laatst online: 03-07 14:47

disjfa

be

Je zou ook de laatste login datum kunnen vastleggen en daaruit verder gaan met de sessies die de meneer boven me al vertelde.

disjfa - disj·fa (meneer)
disjfa.nl


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

React (de forumsoftware op GoT) slaat een sessietijd op voor elke gebruiker. Alle reacties van na de begintijd van een sessie zijn nieuw. Wanneer een gebruiker 30 minuten niet aanwezig is geweest verloopt de sessie, en uiteraard kun je er als gebruiker ook voor kiezen om de sessie te resetten. Als je echt per topic wil kunnen aangeven of iemand het gelezen heeft of niet zul je een aparte tabel moeten maken die bijhoudt welke topics iemand al dan niet bekeken heeft, en daarnaast ook de datum van de laatste reactie in zo'n topic die de gebruiker gelezen heeft, aangezien een nieuwe reactie in een gelezen topic betekent dat het topic weer "nieuw" is.

Persoonlijk zou ik voor de oplossing gaan die React gebruikt. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Als je echt precies zou willen weten zou ik voor een oplossing gaan die 'duur' is tijdens het aanmaken van een nieuw bericht. Je zou dan een dergelijke tabel kunnen opnemen:
user | topic

Als iemand dan een bericht post zet je in bovenstaande tabel voor elke (actieve) gebruiker het topic. Bekijkt een gebruiker een topic dan verwijder je die combi uit de tabel. Je kunt de omvang van de tabel een beetje beperken door bijvoorbeeld een timestamp op te nemen en records ouder dan een bepaalde datum te verwijderen.

Je krijgt dus een soort Stack in je db.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Super bedankt mensen!

Hier kan ik wat mee!

Acties:
  • 0 Henk 'm!

Verwijderd

Volgens mij is dit de meest voorkomende vraag m.b.t. het bouwen van een forum. ;)

Het is best lastig, ik ben er zelf onlangs ook een hele tijd druk mee geweest. Alleen de sessietijd opslaan vind ik niet mooi genoeg, want dan blijft een topic gemarkeerd als nieuw ookal heb je 'm al gelezen. Alle gelezen topics per user in een tabel zetten word je ook niet blij van, want dat wordt met een groot forum een gigantische tabel. In een cookie zetten wil je ook niet want mensen willen op meerdere computers kunnen forummen.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 09:57:
Als je echt precies zou willen weten zou ik voor een oplossing gaan die 'duur' is tijdens het aanmaken van een nieuw bericht. Je zou dan een dergelijke tabel kunnen opnemen:
user | topic

Als iemand dan een bericht post zet je in bovenstaande tabel voor elke (actieve) gebruiker het topic.
Oef, ik weet niet of dat nou wel zo'n handige aanpak is. Je bent dan niet voor 1 user aan het bijhouden (wat op zich al moeilijk genoeg is), maar voor alle users! Als je 3000 users hebt dan knal je in één keer 3000 records in je tabel, en dan hebben we het nog maar over 1 topic!
Je kan je veel beter richten op 1 user en naar de datums kijken.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 11:10:
Alle gelezen topics per user in een tabel zetten word je ook niet blij van, want dat wordt met een groot forum een gigantische tabel.
Vandaar dat ik voosrtelde om alle ongelezen topics per user in een tabel te zetten. Dergelijke tabellen kun je namelijk redelijk klein houden door er bijvoorbeeld een tijd maximum op te zetten van 30 dagen.

Hierbij is posten een intensieve handeling maar lezen niet.
Verwijderd schreef op donderdag 09 maart 2006 @ 11:14:
Oef, ik weet niet of dat nou wel zo'n handige aanpak is. Je bent dan niet voor 1 user aan het bijhouden (wat op zich al moeilijk genoeg is), maar voor alle users! Als je 3000 users hebt dan knal je in één keer 3000 records in je tabel, en dan hebben we het nog maar over 1 topic!
Je kan je veel beter richten op 1 user en naar de datums kijken.
Per user administratie is natuurlijk onvermijdelijk als je per gebruiker de exacte nieuwe topics wilt laten zien. Dus hoe je het ook doet, de hoeveelheid informatie die je moet opslaan blijft gelijk. Want hoe zou jij het dan oplossen?

[ Voor 41% gewijzigd door Verwijderd op 09-03-2006 11:19 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Ik hou het bij in een klein veldje in ieders userprofiel. Dat profiel wordt toch al ingelezen bij elke pageview, dus het kost dan niet eens een extra db-query.

Acties:
  • 0 Henk 'm!

Verwijderd

Wanneer je gaat werken met cookies kun je natuurlijk per user bepalen welk topic al gelezen is. Het bijhouden van wijzigingen kan dan gebeuren door een soort van 'versie_id' per topic in te stellen. Per wijziging van een topic wordt dit getalletje gewoon geupdate. Dit betekent slechts 1 extra veld in de database per topic.

( let wel op exclusive locks/mutual exclusion, als je echt wilt gaan mierenneuken )

In de usercookie krijg je dan gewoon een arraytje met topic-versie combinaties welke al gelezen zijn door de gebruiker. Op deze manier kunnen gewijzigde topics toch getoond worden en hoef je geen uitgebreide databasetabellen aan te maken.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 11:23:
Ik hou het bij in een klein veldje in ieders userprofiel. Dat profiel wordt toch al ingelezen bij elke pageview, dus het kost dan niet eens een extra db-query.
Hoe moet ik dat zien? Wat sla je dan precies op?
(ps het gaat er dus om dat je exact kunt bijhouden welke topics gelezen zijn en welke niet)
Verwijderd schreef op donderdag 09 maart 2006 @ 11:28:
In de usercookie krijg je dan gewoon een arraytje met topic-versie combinaties welke al gelezen zijn door de gebruiker. Op deze manier kunnen gewijzigde topics toch getoond worden en hoef je geen uitgebreide databasetabellen aan te maken.
Dit is zeer beperkt. Cookies zijn geloof ik maximaal 4kb, dus veel topics kun je er niet kwijt. En je moet met cookies aangeven wat je wel hebt gelezen.

[ Voor 39% gewijzigd door Verwijderd op 09-03-2006 11:31 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Een mogelijkheid om het in een veld in een userprofiel op te slaan is natuurlijk er een array van te maken en die in de tabel neer te zetten. Php krijgt dit prima voor elkaar. ( natuurlijk weer een topic-versie array, zoals ik eerder schetste , misschien een mogelijkheid? )

Verder over de beperkingen van een cookie: 4kb is nogsteeds vrij vertaald 400 topics, als dat al de limiet van de grootte. Onthoudt nogsteeds dat je per domein/server meestal 20 cookies kunt plaatsen, als je perse uit wilt breiden.

Misschien is een Sessie bijhouden en op de server opslaan bij het uitloggen wel een optie, maar bij het at random sluiten van vensters wordt deze procedure natuurlijk niet juist doorgelopen.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Even door op het idee om in de db op te slaan welke topics een user nog niet bekeken heeft (en elke keer als er een nieuwe post in een topic komt heeft een topic dus weer de status 'niet bekeken'). Alleen dan weet je het niet per post maargoed. Misschien dat dat ook nog in te bakken is.


Je zou per user maar 1 record en maar 1 kolom nodig hebben voor ALLE nog niet bekeken topics door het op te slaan met een binaire achtergrond. Als volgt:

Als je nu aan elk topic een speciaal ID geeft:

het eerste topic 1
tweede topic 2
derde topic 4
vierde topic 8
vijde topic 16
enz.
En dan in die nieuwe cel de optelling voor een gebruiker zet van al deze ID's voor alle topics die nog NIET bekeken zijn. Dan kun je later door steeds door de groote macht van 2 te delen, zien welke topics nog niet gezien zijn.
Dan houd je je db erg klein, alleen heb je iets meer rekenwerk in je phpfiles.

Je zou het ook kunnen toepassen op berichten, maar ik vermoed dat het dan een te groot rekenwerkje wordt, en dan wordt je op te slagen getal echt VERSCHRIKKELIJK groot

Om precies te zijn: als je 100 onbekenen topics hebt, zit je al snel aan een getal richting de 10^30

[ Voor 6% gewijzigd door Verwijderd op 09-03-2006 11:49 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 11:28:
[...]

Hoe moet ik dat zien? Wat sla je dan precies op?
Zo dus:
Verwijderd schreef op donderdag 09 maart 2006 @ 11:37:
Een mogelijkheid om het in een veld in een userprofiel op te slaan is natuurlijk er een array van te maken en die in de tabel neer te zetten. Php krijgt dit prima voor elkaar.
Je werkt bij het opbouwen van je topics en topiclists met een array (met last-visit datums per nieuw topic), die serialize je en stop je in je usertabel. Bij terugkeer even unserializen en je hebt je array alweer. :)

De truc is natuurlijk om die array opgeschoond te houden.

Acties:
  • 0 Henk 'm!

Verwijderd

@ PaNo

Met alleen opslaan welke topics nog NIET bekeken zijn ben je er niet. Je moet ook weten welke topics al WEL bekeken zijn, want er kan nadat je die bekeken hebt een nieuw bericht bij zijn gekomen.

De truc hier is dus niet te kijken naar WEL of NIET, maar naar WANNEER.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 11:45:
Je werkt bij het opbouwen van je topics en topiclists met een array (met last-visit datums per nieuw topic), die serialize je en stop je in je usertabel. Bij terugkeer even unserializen en je hebt je array alweer. :)

De truc is natuurlijk om die array opgeschoond te houden.
Ja dat brengt dus een vele malen grotere overhead met zich mee als hetgeen ik voorstel. Je moet nu immers gaan bijhouden wat je reeds hebt gelezen. Dat is bij een groot forum een hoop nutteloze informatie.
Verwijderd schreef op donderdag 09 maart 2006 @ 11:49:
Met alleen opslaan welke topics nog NIET bekeken zijn ben je er niet. Je moet ook weten welke topics al WEL bekeken zijn, want er kan nadat je die bekeken hebt een nieuw bericht bij zijn gekomen.

De truc hier is dus niet te kijken naar WEL of NIET, maar naar WANNEER.
Onjuist. De truuk is enkel bijhouden wat je nog niet hebt bekeken. Dat is de enige informatie die interessant is. Heb je een bepaald item bekeken kun je het uit je lijstje schrappen. Een nieuwe post levert een nieuwe notificatie van een ongelezen item op.

[ Voor 36% gewijzigd door Verwijderd op 09-03-2006 11:54 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Ja, maar dan ga je dus uit van de aanpak waarbij je bij een nieuwe post van een willekeurige user bij ALLE users moet gaan updaten. Lijkt me niet echt fijn als je een groot forum hebt met meerdere posts per seconde.

Mijn aanpak is:

- welke topics heeft nieuwe berichten sinds mijn vorige bezoek? (het GoT sessie verhaal)
- welke daarvan heb ik al gelezen (en bevatten ze geen nieuwe berichten sinds ik ze gelezen heb)?
- welke topics had ik nog niet gelezen uit mijn vorige bezoek?

Ik hou dus in feite ook alleen de topics bij die ongelezen zijn, maar je moet wel rekening houden met punt 2; topics kunnen nieuwe berichten krijgen NADAT jij ze gelezen hebt.

Gooi zo'n array in een veld achter het userprofiel en je bent slechts een paar kb kwijt, i.p.v. een hele tabel met duizenden records.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 11:51:
De truuk is enkel bijhouden wat je nog niet hebt bekeken. Dat is de enige informatie die interessant is. Heb je een bepaald item bekeken kun je het uit je lijstje schrappen. Een nieuwe post levert een nieuwe notificatie van een ongelezen item op.
Dát is inderdaad de manier die je moet gaan toepassen.
Stel je hebt een forum met 500 gebruikers en het forum is nog helemaal leeg (voorbeeld-case, niet realistisch natuurlijk).

Nu komt er een gebruiker die een thread opent. Met dat hij/zij dit gedaan heeft, maak je de volgende records aan in je tabel die je hier voor gaat gebruiken:

- voor iedere gebruiker maak je een row aan in je tabel, waarin je het thread-id opslaat. Hiermee geef je in het systeem aan dat die gebruikers de thread nog niet gezien hebben.

Wat doe je vervolgens? Als een bezoeker de thread opent, dan voer je de volgende query uit;
code:
1
DELETE FROM tabelnaam WHERE thread_id=x and user_id=y


Als je een overzicht laat zien van alle threads, dan kun je aangeven met een mooi kleurtje/icoontje welke threads de user nog niet gezien heeft door een query uit te voeren als;
code:
1
SELECT * FROM tabelnaam WHERE user_id=y


En je hebt bereikt wat je wilt.
Op deze wijze krijg je nooit een mega-ubertabel, want je kunt maximaal het volgende aantal rows in je tabel hebben staan;

aantal_users * aantal_threads

(voorbeeld: 1.000 users * 100 threads = 100.000 rows; en dat is bij een goed geoptimaliseerde tabel geen enkel probleem - zelfs niet bij het tien- of honderdvoudige).

Als er een gebruiker komt die een reply geeft op een thread/topic, dan voer je de volgende query uit, waardoor gebruikers er weer op geattendeerd worden dat er iets gebeurd is in het topic:

code:
1
2
// eerst checken of de entry niet al voorkomt in de tabel
INSERT thread_id, user_id INTO tabelnaam

[ Voor 9% gewijzigd door Verwijderd op 09-03-2006 12:08 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 12:03:
Gooi zo'n array in een veld achter het userprofiel en je bent slechts een paar kb kwijt, i.p.v. een hele tabel met duizenden records.
Je vergelijking klopt van geen kant, want jij hebt simpelweg ook diezelfde "duizenden" gebruikers die nu ook extra informatie hebben die nog steeds achteraf werk aan het doen is. Jij moet nu achteraf allerlei vergelijkingen uitvoeren op de posts en threads die het hele systeem nodeloos traag maken. Ik kies liever voor een doelgerichte strategie waarbij je niets aan de vergelijking over laat. Een paar records is evoor een database een peule-schil, daar is het voor bedoeld.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 12:06:
[...]

Dát is inderdaad de manier die je moet gaan toepassen.

[heel verhaal]
En ik ben de enige die dat een omslachtige manier vindt?

Je zal 10.000 topics en 5000 users hebben....

Waarom wordt deze methode dan niet door alle grote forums toegepast?

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 12:09:
[...]
Je vergelijking klopt van geen kant, want jij hebt simpelweg ook diezelfde "duizenden" gebruikers die nu ook extra informatie hebben die nog steeds achteraf werk aan het doen is. Jij moet nu achteraf allerlei vergelijkingen uitvoeren op de posts en threads die het hele systeem nodeloos traag maken. Ik kies liever voor een doelgerichte strategie waarbij je niets aan de vergelijking over laat. Een paar records is evoor een database een peule-schil, daar is het voor bedoeld.
Trust me, hij klopt en hij werkt als een trein.

Ik maak ook geen vergelijkingen achteraf, ik heb bij het opbouwen van m'n topiclist al in een array staan of een topic nieuw is of niet.

Jullie doen:
- een hele grote query bij elke post (duizenden records invoegen)
- een query om te kijken of een topic nieuw is
- een query om het record te verwijderen uit de ongelezen-tabel

Ik doe:
- 1 query om de array uit het profiel te halen (die query doe je sowieso al want je moet username e.d. weten)
- 1 query om de geupdate array er weer in te zetten wanneer een topic gelezen is


Imho is mijn methode stukken efficiënter, maar er zijn meer wegen die naar Rome leiden, natuurlijk. :)

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 12:13:
[...]

En ik ben de enige die dat een omslachtige manier vindt?

Waarom wordt deze methode dan niet door alle grote forums toegepast?
Ik denk dat jij niet inziet dat welke oplossing je ook kiest je altijd een extra druk legt op het systeem. En jouw oplossing heeft nog eens extra overhead.

Laten we wel wezen, geen van beide methodes worden toegepast op grote fora. Het legt simpelweg een te grote druk op het systeem. Je vraag is dus aanzet tot een drogredenatie :)

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 12:06:
[...]

code:
1
2
// eerst checken of de entry niet al voorkomt in de tabel
INSERT thread_id, user_id INTO tabelnaam
Hoe doe je dit dan? Moet je dan eerst voor elke user gaan kijken of de entry al voorkomt, of doe je een REPLACE INTO?

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 12:21:
[...]

Laten we wel wezen, geen van beide methodes worden toegepast op grote fora. Het legt simpelweg een te grote druk op het systeem. Je vraag is dus aanzet tot een drogredenatie :)
True, maar wel leuk om even over te brainstormen, toch? :)

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 09 maart 2006 @ 12:13:
[...]
En ik ben de enige die dat een omslachtige manier vindt?
Je zal 10.000 topics en 5000 users hebben....
Waarom wordt deze methode dan niet door alle grote forums toegepast?
Je moet niet vergeten dat het een proces betreft - het toevoegen van nieuwe rows - dat geleidelijk wordt doorgevoerd. Kortom, als je 5.000 users hebt en er wordt een nieuw topic geplaatst, dan worden er 5.000 rows toegevoegd (en dat is een relatief lichte bewerking op je database). Als er 3 seconden later wederom een topic wordt toegevoegd, herhaald dit proces zich. Etcetera, etcetera. Wat ik bedoel te zeggen is dat hoe groot de getallen ook zijn (duizenden users, duizenden topics) er niet dermate grote handelingen worden verricht; dit gebeurd geleidelijk en dat is een groot verschil.

Rest mij de nadruk te leggen op het feit dat er nooit en te nimmer honderden miljoenen rows ontstaan omdat het een interactief proces is dat constant in gebruik is. Oók niet bij grote hoeveelheden topics en users. Ik ben er wel degelijk van overtuigd dat, ondanks eerder anders werd geopperd, deze methode uiterst effectief kan zijn, ook bij de grote partijen/fora. Zeker gezien het argument dat je totaal niets van de user vraagt: je laat geen cookie achter op zijn of haar pc, maar handelt alles zelf, server-side, af. Een puur gebruiksvriendelijke oplossing.

Het is ook maar hoe je zaak bekijkt. Hoeveel fora zijn daadwerkelijk zó groot dat het honderden zoniet duizenden malen per seconde wordt aangeroepen? Ga er dus vanuit dat de oplossing die ik probeer aan te dragen wel degelijk werkt bij de fora die wij hier met z'n allen zouden kunnen ontwikkelen en dat het doemdenken genoemd mag worden als je er vanuit gaat dat je forum tienduizenden threads ontvangt binnen een korte termijn.

Daarnaast zou je kunnen werken met batching op een tweede server. Dit neemt de load weg bij je eindgebruiker en zorgt voor een identieke, hetzij met een vertraging, oplossing.

[ Voor 30% gewijzigd door Verwijderd op 09-03-2006 13:27 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Ik wil er nog even aan toevoegen dat je het in je verhaal alleen hebt over topics aanmaken, maar het moet natuurlijk ook bij het plaatsen van posts. Zelfs op een klein forum kun je een behoorlijk aantal posts per minuut hebben.

Jij schrijft dat je een paarduizend rijen invoegen/manipuleren bij ELK bericht wat er geplaatst wordt een relatief lichte handeling vind, maar ik kan me niet voorstellen dat het lichter is dan een array serializen in PHP en 1 enkel recordje updaten voor 1 enkele user.

Het argument "mijn forum is toch niet zo groot" is voor mij persoonlijk niet genoeg om zulke concessies te doen.

Acties:
  • 0 Henk 'm!

  • _js_
  • Registratie: Oktober 2002
  • Laatst online: 18-08 21:31
In plaats van moeilijk te doen in de database, kun je er ook voor kiezen om het door de browser van de gebruiker te laten doen. Browsers onthouden welke link geklikt is en welke niet, dus je hoeft alleen maar in de link het id van de laatste post mee te geven in de thread, of het tijdstip van de laatste wijziging, dan hoef jij verder niks bij te houden.
Pagina: 1