[PHP] Kommenteringsystem med trädstruktur

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2005

[PHP] Kommenteringsystem med trädstruktur

Hej,

Jag jobbar på ett kommenteringssystem där användare ska kunna skriva kommentarer och även svara på andras kommentarer. Lätt som en plätt kan man tro, men så var det inte riktigt. Det jag har problem med är hur jag ska få till trädstrukturen på bästa sätt. En konversation kan exempelvis se ut något i stil med det här:

Kommentar 1 - kommentar 2 (svar till kommentar 1) - kommentar 3 (svar till kommentar 1) - kommentar 4 (svar till kommentar 3) Kommentar 5 - kommentar 6 (svar till kommentar 5) - kommentar 7 (svar till kommentar 6) - kommentar 8 (svar till kommentar 7)

Jag behöver alltså få lösningsförslag för hur jag ska hämta och lagra kommentarerna så att de hamnar i rätt ordning. Viktigt att poängtera är att man kan svara på en kommentar när som helst, så även om man svarar på en kommentar som inte ligger sist i ordningen så ska svaret hamna efter den rätta kommentaren. Jag antar att en rekursiv lösning är den bästa här men jag vet ändå inte riktigt hur jag ska göra.

Hoppas ni kan hjälpa mig med det här problemet.

Trädvy Permalänk
Medlem
Plats
Falun
Registrerad
Dec 2003
Citat:

Ursprungligen inskrivet av Superb
Hej,

Jag jobbar på ett kommenteringssystem där användare ska kunna skriva kommentarer och även svara på andras kommentarer. Lätt som en plätt kan man tro, men så var det inte riktigt. Det jag har problem med är hur jag ska få till trädstrukturen på bästa sätt. En konversation kan exempelvis se ut något i stil med det här:

Kommentar 1 - kommentar 2 (svar till kommentar 1) - kommentar 3 (svar till kommentar 1) - kommentar 4 (svar till kommentar 3) Kommentar 5 - kommentar 6 (svar till kommentar 5) - kommentar 7 (svar till kommentar 6) - kommentar 8 (svar till kommentar 7)

Jag behöver alltså få lösningsförslag för hur jag ska hämta och lagra kommentarerna så att de hamnar i rätt ordning. Viktigt att poängtera är att man kan svara på en kommentar när som helst, så även om man svarar på en kommentar som inte ligger sist i ordningen så ska svaret hamna efter den rätta kommentaren. Jag antar att en rekursiv lösning är den bästa här men jag vet ändå inte riktigt hur jag ska göra.

Hoppas ni kan hjälpa mig med det här problemet.

kommentar ========= # kommentar_ID bigint (#) kommentar_parentID bigint kommentar_anvandarID bigint kommentar_timestamp timestamp kommentar_text text

kommentar_parentID = Ska vara null eller 0 om det är en rot-kommentar. Annars så är den respektive ID för den kommentaren denna kommentar ligger under.
Sen blir det lite mer jobb att fixa SQL-koden för att få fram allt.

Om du inte gör lagrade procedurer så är det enklast är att ha en metod som gör loopen för varje "lager". Fast du kanske redan har detta i huvudet?

Edit: Underbart att sweclockers inte kör monospace på CODE-taggen...

ηλί, ηλί, λαμά σαβαχθανί!?

Trädvy Permalänk
Medlem
Plats
Lund
Registrerad
Jan 2005

Vad som direkt kommer upp i huvudet på mig är ju att varje kommentar har ett parent ID. Om IDt inte är något (dvs null) så är det inte en kommentar till en annan kommentar. Men om den har ett parent ID så är den just en kommentar till en annan kommentar.

Typ såhär:
Kommentar 1 : Parent null : ID 222
- kommentar 2 (svar till kommentar 1) : Parent 222 : ID 240
- kommentar 3 (svar till kommentar 1) : Parent 222 : ID 245
- kommentar 4 (svar till kommentar 3) : Parent 245 : ID 290

När du har en sådan här struktur kan man hyffsat enkelt köra en sortering av alla kommentarerna.

Hoppas jag va tydlig nog.

EDIT: Va tydligen inte snabbast på att svara.

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2005

Att ha ett parent_id på kommentarerna som är svar har jag också tänkt på, men det är själva sorteringen som jag lite problem med. Någon som har ett förslag på hur den skulle kunna se ut?

Trädvy Permalänk
Medlem
Plats
Singapore
Registrerad
Okt 2003

En effektiv metod vore att placera kommentarerna i en skog av träd, där varje nod i träden är en länkad lista av kommentarer på en viss nivå i kommentarshierarkin, sorterade i datumordning:

Hämta alla kommentarer.
För varje kommentar, kolla om den passar in i något av de nuvarande träden, dvs om något träd innehåller kommentarens parent (tänk på datumordningen för snabb sökning).
Om den passar in i ett träd, placera den i det trädet.
Om den inte passar in i ett träd, skapa ett nytt träd med den kommentaren som rot.
Kolla om några träds rötter har den nyinlagda kommentaren som parent. Om så är fallet, kombinera träden till ett och samma träd.
Gå till nästa kommentar.

Borde ju finnas färdigskrivna lösningar för sånt här tycker man.

edit: kom på att om kommentarerna hämtas från en databas lär de ju redan vara placerade i princip i datumordning, så då är det rätt onödigt att kolla datumordningen i sökalgoritmen..

Trädvy Permalänk
Medlem
Plats
Falun
Registrerad
Dec 2003
Citat:

Ursprungligen inskrivet av Superb
Att ha ett parent_id på kommentarerna som är svar har jag också tänkt på, men det är själva sorteringen som jag lite problem med. Någon som har ett förslag på hur den skulle kunna se ut?

Just hierarktiskt struktur (även kallad trästruktur) är ett problem som jag hade förut när jag skulle göra en blogg till tjejen. Det var just comment/reply-funktionen jag hade problem med. Jag kom så långt till att ha parent_id och sådär, men projektet dog strax efter det.

Nu när du nämner det igen så väcktes mitt intresse igen. Jag satt 3h igår efter jag kommenterade och googlade och testade och gjorde allt.

Slutsatsen jag nu kan dra är att mysql inte har stöd för recursiva querys (alltså stöd för att hämta ut hierarktisk data). De har en artikel om det, men jag skulle mer se det som en fullösning.

http://dev.mysql.com/tech-resources/articles/hierarchical-dat...

MS SQL och Oracle har såklart stöd för detta, men jag tippar på att det är mysql du kommer använda?

Jag har hittat ett antal lösningar att kunna hämta ut hierarktiskt data ur mysql utan hjälp av stored procedures:

Första lösningen är att spara datat som jag skrev tidigare och köra en select * på rubbet och sen göra en user defined sort pattern med hjälp av usort() i php.

Andra lösningen är mer omständig och kräver flera querys men de är däremot små. Först hämta ut alla med parent_id 0 (vi kallar dessa PARENTS) och sen hämtar man ut alla med parent_id = PARENT.current_id (vi kallar dessa CHILDREN). Sen fortsätter man så tills det inte finns några kvar. Jag tycker att usort() i php blir bra mycket enklare.

Tredje lösningen står under länken jag postade där man med hjälp av JOIN querys skriver ut datat.

Kort och gott: Det går inte att göra recursiva sql-querys i mysql. Det går att göra det på databassidan med hjälp av lagrade procedurer men enklast är helt enkelt att göra det i php.

ηλί, ηλί, λαμά σαβαχθανί!?

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2005
Citat:

Ursprungligen inskrivet av Leedow
Just hierarktiskt struktur (även kallad trästruktur) är ett problem som jag hade förut när jag skulle göra en blogg till tjejen. Det var just comment/reply-funktionen jag hade problem med. Jag kom så långt till att ha parent_id och sådär, men projektet dog strax efter det.

Nu när du nämner det igen så väcktes mitt intresse igen. Jag satt 3h igår efter jag kommenterade och googlade och testade och gjorde allt.

Slutsatsen jag nu kan dra är att mysql inte har stöd för recursiva querys (alltså stöd för att hämta ut hierarktisk data). De har en artikel om det, men jag skulle mer se det som en fullösning.

http://dev.mysql.com/tech-resources/articles/hierarchical-dat...

MS SQL och Oracle har såklart stöd för detta, men jag tippar på att det är mysql du kommer använda?

Jag har hittat ett antal lösningar att kunna hämta ut hierarktiskt data ur mysql utan hjälp av stored procedures:

Första lösningen är att spara datat som jag skrev tidigare och köra en select * på rubbet och sen göra en user defined sort pattern med hjälp av usort() i php.

Andra lösningen är mer omständig och kräver flera querys men de är däremot små. Först hämta ut alla med parent_id 0 (vi kallar dessa PARENTS) och sen hämtar man ut alla med parent_id = PARENT.current_id (vi kallar dessa CHILDREN). Sen fortsätter man så tills det inte finns några kvar. Jag tycker att usort() i php blir bra mycket enklare.

Tredje lösningen står under länken jag postade där man med hjälp av JOIN querys skriver ut datat.

Kort och gott: Det går inte att göra recursiva sql-querys i mysql. Det går att göra det på databassidan med hjälp av lagrade procedurer men enklast är helt enkelt att göra det i php.

Det var ett tag sen jag kollade den här tråden, projektet har stått still ett tag. Jag gillar dina lösningsförslag och tackar så mycket för ett bra inlägg (även från er andra).

Att hämta datan rekursivt från databasen hade ju varit bra, men eftersom jag använder MySQL så är det inget alternativ. Ditt andra lösnings förslag - att hämta kommentarerna en del i taget låter bra; nackdelen är ju förstås som du säger att det blir relativt många frågor.

Förslaget om att använda usort() låter mycket intressant men jag förstår inte riktigt hur jag skulle kunna definiera sorteringsfunktionen. Som jag förstår det så ska sorteringsfunktionen returnera 0, större än 0 , eller mindre än 0 beroende på om första argumentet är just lika med, större än eller mindre än det andra, men hur ska jag kunna använda det på sorteringen av hierarkiskt data? Kom gärna med ett förslag.

Trädvy Permalänk
Medlem
Plats
Falun
Registrerad
Dec 2003
Citat:

Ursprungligen inskrivet av Superb
Det var ett tag sen jag kollade den här tråden, projektet har stått still ett tag. Jag gillar dina lösningsförslag och tackar så mycket för ett bra inlägg (även från er andra).

Att hämta datan rekursivt från databasen hade ju varit bra, men eftersom jag använder MySQL så är det inget alternativ. Ditt andra lösnings förslag - att hämta kommentarerna en del i taget låter bra; nackdelen är ju förstås som du säger att det blir relativt många frågor.

Förslaget om att använda usort() låter mycket intressant men jag förstår inte riktigt hur jag skulle kunna definiera sorteringsfunktionen. Som jag förstår det så ska sorteringsfunktionen returnera 0, större än 0 , eller mindre än 0 beroende på om första argumentet är just lika med, större än eller mindre än det andra, men hur ska jag kunna använda det på sorteringen av hierarkiskt data? Kom gärna med ett förslag.

Tjena. Jo jag hade problem med usort() ett tag. Jag har ingen fungerande lösning då jag var tvungen att börja pilla med andra grejer. Jag ska ta min tid att fixa detta snart.

Om du kikar på php's dokumentation över usort() så finns det en kommentar där som tar upp rekursiv multisort (vilket vi behöver). Men den kan vi inte implementera rakt av, tror jag.

Säg att vi har följande i en mysql-tabell (id, parent):
1 0
2 0
3 1
4 3
5 2
6 5
7 3

Då vill vi att den ska se ut på detta vis:
1 0
3 1
4 3
7 3
2 0
5 2
6 5

Det _borde_ gå att göra detta med usort() jag har bara inte haft tid att sätta mig in i sorteringen. Det går ju att göra rekursiva metoder för detta också, om usort() blir för jobbigt att förstå.

Pseudokod:
Leta efter alla idn med parent = 0 // Dessa kallar vi X
Leta efter alla idn med parent = X // Dessa kallar vi för Y
Leta efter alla idn med parent = Y // Dessa kallar vi för Z
Leta efter alla.... osv.

Det går att göra dynamiskt med metoder, alltså att vi inte behöver en metod för varje underkategori/nivå.

Som sagt, jag ska ta min tid att försöka fixa detta på något bra sätt.

ηλί, ηλί, λαμά σαβαχθανί!?

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2005

Jag använder mig av tillvägagångssättet att hämta kommentarerna med flera databasfrågor nu. Jag kör med det tills vidare. Jag har inte lyckats komma på någon algoritm för sorteringen ännu, tyvärr.

Trädvy Permalänk
Medlem
Plats
Östersund
Registrerad
Aug 2007

Om du använder mysql kan du köra frågor med "self join" det är lite klurigt, men det går, jag håller på att göra ett foruim med det

mobo Asus M4A88TD-M EVO/USB3 cpu 1100T kylare Noctua NH-D14
gpu RX 460 passive ram 16GB DDR3 1600MHz ssd Samsung 850 EVO 250GB
psu Corsair AX 850 skärmar 3 * 40" NEC P401

Trädvy Permalänk
Hedersmedlem
Plats
Stockholm
Registrerad
Dec 2002

Här är en ren och snygg lösning i PHP: http://www.jongales.com/blog/2009/01/27/php-class-for-threade...

Vim
Kinesis Classic Contoured (svart), Svorak (A5)
Medlem i signaturgruppen Vimzealoter.

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2005
Citat:

Ursprungligen inskrivet av m0REc
Här är en ren och snygg lösning i PHP: http://www.jongales.com/blog/2009/01/27/php-class-for-threade...

Det tackar vi ödmjukast för

Man känner sig ganska dum när man ser lösningen framför sig, det var ju inte så komplicerat ändå.