PHP Forum programmiern: Ungelesenes anzeigen

    ACHTUNG dies ist das ALTE Forum!!

    Das neue gibt es unter https://discourse.bohramt.de!

      PHP Forum programmiern: Ungelesenes anzeigen

      Hab gegoogled, aber nur schwer was gefunden.

      Also ich progge grad eine PHP Forum. Habe also eine Tabelle mit allen Beiträgen.

      Jetzt soll beim Login, natürlich angezeigt werden, was man noch nicht gelesen hat. Und wenn man ein paar gelesen hat, sollen die restlichen immernoch angezeigt werden.

      Hier mal 2 Ideen, wovon ich die 2te bevorzuge. Kennt wer eine(oder DIE) bessere Variante?!

      Folgende Ideen:
      1. ( die etwas aufwändigere Variante)

      Man hat eine Tabelle Ungelesene. Darin speichert man beim Erzeugen eines neuen Beitrags/Antwort für jeden User die threadID und UserID.
      Beim Lesen entfernt man den entsprechenden Eintrag. Ebenfalls entfernt man zu alte Einträge, damit die Tabelle sauber bleibt. (Kann man anhand Threaddatum auslesen)

      Nachteil: Bei 1000en Usern wird bei jedem erstellten Beitrag erstmal schön die Tabelle Ungelesene vollgeschaufelt. Ist bestimmt auch ne Menge Datenverschleiß.

      2. (die etwas bessere Variante)

      Man hat wieder eine Tabelle Ungelesene. Diese wird jedoch erst bei jedem Login eines Users mit seinen ungelesenen Beiträgen gefüllt. (anhand des letzten Logoutdatums)
      Während des Lesens werden einzelne Einträge entfernt.
      Beim Login werden zuerst alle Einträge entfernt, damit bisher ungelesene Beiträge nicht weiterhin als neu gekennzeichnet sind.


      Also die 2te Variante ist gar nicht so schlecht. Man schaufelt wesentlich weniger Einträge und man schaufelt auch nur, wenn es nötig ist und für die Leute, die es nötig wird.

      Jemand Erfahrung?
      Danke!
      wie in der $_SESSION speichern.
      bei mir läuft ein cron-job welcher aller 30 min nachschaut ob irgendwelche dateien in /var/lib/php5 älter als die vorgegebene lifetime ist.
      wenn ja wird die datei dort gelöscht und die session verfällt somit.
      ich habe auch schon mal getestet mit serialisieren die daten seperat abzuspeichern.
      würde aber bei einem forum auch auf ne datenbank zugreifen.
      interessant wäre sich ne probe zu schreiben welche die abfrage mal ein bisschen stressen tut. einfach um ne kontrolle für sich zu haben wie es so läuft.
      EDV - Einer Der Verdächtigen
      Man kann durchaus sessions auf laenger leben lassen (und anders persistieren als durch eine serialisierung und Ablage im Filesystem). In PHP ist aber das Session-Handling etwas unkomfortabel und bei groesserer Datenmenge unpeformant. Es gibt da durchaus Sprachen um stabile (langlebige) Sessions und Hibernating zu betreiben, bei PHP wuerde ich aber nicht versuchen alles in die Session abzulegen.
      du speicherst doch sicherlich den Beginn einer jeden Usersession, bzw, den Startzeitpunkt der letzten Usersession an sich.

      Auch ein Thread/Post hat ein Erstellungsdatum.

      Beim Login müsstest du nun zu sehen, dass du mit einer SQL-Query nun die Beiträge, bzw. übergeodnete Threads, raussuchst, die der Benutzer noch nicht gelesen hat.

      Diese zeigst du dann auf z.B. der Startseite an.

      Fertich is!
      Original von Plugstar
      du speicherst doch sicherlich den Beginn einer jeden Usersession, bzw, den Startzeitpunkt der letzten Usersession an sich.

      Auch ein Thread/Post hat ein Erstellungsdatum.

      Beim Login müsstest du nun zu sehen, dass du mit einer SQL-Query nun die Beiträge, bzw. übergeodnete Threads, raussuchst, die der Benutzer noch nicht gelesen hat.

      Diese zeigst du dann auf z.B. der Startseite an.

      Fertich is!


      im prinzip funktioniert es so.
      nun liest der user aber irgendeinen beitrag. dann möchte ich, dass auf der startseite die restlichen als ungelesen angezeigt werden. das geht nur in dem gespeichert wird, welcher von den ungelesenen threads schon gelesen wurde.
      und genau das mach ich in einem array welches ich in $_SESSION ablege.

      und nix mit session persistieren ;)
      nach der session ist natürliches alles weg und somit erstmal wieder allllllles gelesen, was bis zum Logout/Timeout noch neu war.

      hier wie ich es jetzt erstmal implementiert habe:

      PHP-Quellcode

      1. // diese funktion im konstruktor der Forumklasse aufrufen.
      2. // damit auch threads/beiträge, die während der session erstellt werden in unser array kommen.
      3. // Forumklasse wird dann auch auf Übersichtsseite benötigt
      4. // wo man z.B. die Anzahl ungelesener Threads anzeigen möchte.
      5. function fillThreadread() {
      6. global $session;
      7. $lastlogout = $session->userinfo["LastLogout"];
      8. $query = "SELECT ID FROM forum WHERE PID = ID AND LastPost > '$lastlogout'";
      9. $result = mysql_query($query, $this->connection);
      10. if(!$result || (mysql_numrows($result) < 1)){
      11. return NULL;
      12. }
      13. while ($row = mysql_fetch_array($result)) {
      14. $id = $row["ID"];
      15. if ($_SESSION["threadread"][$id] != READ) {
      16. $_SESSION["threadread"][$id] = UNREAD;
      17. }
      18. }
      19. }


      PHP-Quellcode

      1. // in der funktion getThreads()
      2. // ungelesen?
      3. $id = $row["ID"];
      4. if ($_SESSION["threadread"][$id] == UNREAD) {
      5. $row["unread"] = true;
      6. };
      7. $dbarray[] = $row;
      8. //... und am ende
      9. return $dbarray;
      10. };


      PHP-Quellcode

      1. // in der funktion getThread($id):
      2. if ($_SESSION["threadread"][$id] == UNREAD) {
      3. $_SESSION["threadread"][$id] = READ;
      4. }


      fehlt nur noch:
      in der funktion newReply bzw. newThread muss man die ThreadID auslesen und im SESSION-threadread array auf gelesen setzen, damit der Autor diese nicht als neue angezeigt bekommt ;)
      global $session

      das is doch aus php4 oder? deshalb hatte ich angenommen es wäre php4.
      auch dort gibt es klassen und man kann ein konstruktor benennen.

      in php5 würde ich eine zugriffsfunktion machen um dann auf die variable zugreifen zu können.

      class test{
      private $session=array();
      .....
      .....
      private functon set_session(){
      $this->session="meine_werte";
      }

      public function get_session(){
      return $this->session;
      }
      }

      ... im scripte zum erhalt
      $test=new test;
      $session=$test->get_session();

      ich weiss nicht ob es in diesem sinne wäre, aber das is so meine ding wie ich es versuche sowas umzusetzten, um global zu vermeiden.
      EDV - Einer Der Verdächtigen
      jo is ganz normales php 4 :)

      das mit dem $_SESSION ist, damit das array auch beim aufrufen von neuen seiten bestehen bleibt. beim seitenwechsel wird ja alles andere gelöscht. nur $_SESSION bleibt.

      so wie hier im example 1 und 2 (gehört zusammen)

      php.net/manual/en/function.session-start.php

      auch wenn ich das array im forum konstruktor scheinbar jedes mal neumache....es wird aber nur geupdated in der funktion fillthread, nicht komplett neugemacht.

      und mit dem global vermeiden...das global mach ich ja um in der einen instanz auf eine instanz einer anderen klasse zuzugreifen.

      naja wie auch immer....es geht ja vor allem um die idee mit dem ungelesenen ;) in welcher sprache man es implementiert is ja egal.
      ja ich schweife mal wieder ab es ging ja um die updatefunktion. :D
      aber kurz das noch, um das global in php5 zumachen würde ich eventuell eine von der testklasse welche die werte aufnimmt, abgeleitete klasse nehmen.
      zb

      class test{
      protected $session = array();
      .. werte aufnehmen und bereitstellen
      protected function get_session(){
      return $this->session;
      }
      }

      class threat extends test{
      private $use_session = array();
      ...
      ...
      public funtion show_test(){
      ... hier brauche ich $session
      $this->use_session = parent::get_session();
      }
      }

      dann bräuchte ich mich in der klasse thread hier nicht um die variablenprüfung mehr kümmern, das würde alles in die elternklasse reingepackt und wäre aufgeräumt.
      EDV - Einer Der Verdächtigen
      ah jetzt versteh ich so langsam was du meinst.

      global $session;
      $lastlogout = $session->userinfo["LastLogout"];

      diese zwei Zeilen, gelle?

      also erstmal, wäre es eleganter, wenn man nicht direkt auf die variablen zugreift, sondern wie du sagst über eine get-funktion. (wegen variablenprüfung)
      aber wer hält sich schon immer daran :D

      also z.B. so:

      global $session;
      $lastlogout = $session->getUserinfo();

      und jetzt zum global.
      nebenbei: ich progge in php4, weil äh weil ich noch ned allzu doll der profi in php bin...und wollte nicht schon wieder wat neues anfangen. php5 ist ja schon etwas anders. obwohl wie ich grad gesehn habe, php5 näher an den ottonormalprogrammiersprachen (c#, java, ...) angelehnt ist. das wär ja dann auch zu langweilig, wenn alles wie in den anderen ist :P

      so zurück zum global.
      nebenbei2: ich hab bei diesem projekt, dass erste mal php klassen verwendet. und zwar hab ich anfangs das login zeug nachprogrammiert. und da geguckt wie "er"/man klassen verwendet. ansonsten hab ich, dass bisher nur in anderen skripten gesehen und ned weiter drauf geachtet.

      meine frage. ist das global in php4 notwendig?:

      hab meine 2 seperaten klassen:

      $session = new Session();
      $forum = new Forum();

      ah ich merk grade... mit dem global zwing ich mich ja die $session instanz zu benutzen.

      also entweder wie du machen, mit abgeleiteten klassen oder wie wärs so (php4):

      $session = new Session();
      $forum = new Forum();
      $forum->setSession($session);

      class Forum {
      var $sessionRef;
      function setSession (&$sessionReferenz) {
      $this->sessionRef = $sessionReferenz;
      }

      function tuIrgendwas() {
      $userinfo = $this->sessionRef->getUserinfo();
      }

      }
      weiß grad ned ob es funktioniert, aber so in der art verstehst? so dass erst zur laufzeit die session-instanz übergeben wird.

      im prinzip ist die Beziehung zwischen Forum und Session ja eine USE-Beziehung, keine IST-Beziehung (so wie bei deinem beispiel)

      btw: das mit dem ungelesen ist ja erstmal ausdiskutiert :)
      das mit dem global ist jetzt interessanter :)
      dachte die ganze zeit du redest von dem $_SESSION ;)
      ja ich hatte das mit der $session gemeint. :D
      ahja darüber hatte ich mir noch gar keine gedanke gemacht, das mit ist oder use beziehung. wenn du da mal ein beispiel hättest, daß das versanschaulicht wäre net schlecht.

      zu dem, das $session objekt als parameter einer anderen funktion, geht.
      aber bevor ich mich in php4 vertiefen würde, würde ich gleich php5 nehmen.

      mit refernzen da bin ich auch kein spezialist, aber in dem fall arbeitet php5 ein bisschen anders als das php4.
      in php5 ist eine instanz eine referenz auf den codeblock der klasse im speicher, wogegen in php4 eine kopie des ganzen codeblockes im speicher gemacht wird.
      wenn ich das so richtig verstanden habe, wenn ich nun in php4 ein klasse 5 mal mit new aufrufe gibt es 5 codeblockbereiche der klasse sowie 5 datenbereiche für die variablen im speicher.
      in php5, nun 5 mal new machen, ergibt nur ein codeblock der klasse im speicher und dafür 5 zeiger auf den codeblock, aber das ist pro zeiger nicht mehr als 4 byte und 5 datenbereiche für die variablen.

      würde sage der umstieg würde sich lohnen.
      ich habe mir auch schon mal überlegt mit konstanten was zu machen.
      da http zustandslos ist, ist jeden anfrage eine komplett neue variablenzuweisung.
      dort das nutzen und die $session als konstant deklarieren und den wert zuweisen. somit wäre die konstante in jeder klassel aufrufbar, da konstanten global sind.
      und beim nächsten aufruf wir die konstante wieder neu mit werten belegt.
      EDV - Einer Der Verdächtigen
      Ein Mercedes ist ein Auto. Ein Auto hat Räder. Ein Auto benutzt einen Fahrer.

      "IS A"- , "HAS A"-, "USES A" - beziehungen


      class Rad {
      var durchmesser;
      function Rad(durchmesser) {
      $this->durchmesser=durchmesser;
      }
      }

      class Fahrer {
      var name;
      function Fahrer(name) {
      $this->name = name;
      }

      function getName() {
      return $this->name;
      }

      }

      class Auto {
      var rad1;
      var rad2;
      var rad3;
      var rad4;
      var fahrer;

      function Auto() {
      rad1 = new Rad(5);
      rad2 = new Rad(5);
      rad3 = new Rad(5);
      rad4 = new Rad(5);
      }

      function einsteigen(&fahrer) {
      $this->fahrer = fahrer;
      }

      function fahre() {
      echo $this->fahrer->getName() . " fährt und fährt ...";
      }
      }

      class Mercedes extends Auto {
      var stern;

      function Mercedes() {
      // aufruf des Parentkonstruktors mit parent::Auto(); ?!
      stern= new Stern();
      }
      }


      programm:

      $mercedes = new Mercedes();

      $schumi = new Fahrer("Michael Schuhmacher" ) ;

      $mercedes->einsteigen($schumi); // von Auto
      $mercedes->fahre(); // von Auto

      Ausgabe.
      Michael Schuhmacher fährt und fährt ....



      hhihihihihihih

      bin grad ned sicher wegen den referenzen beim funktionsaufruf, hab bisher noch ned referenzen übergeben....aber wenn einsteigen($schumi) ned geht dann mit &$schumi müsste das ja.

      also so würd ich es außerhalb von php machen.

      in UML Klassendiagramm :D :

      (Auto USES A Fahrer)
      [Auto] -------------------- [Fahrer]
      [Rad rad1, rad2, ... ] (Auto HAS A Rad)
      ^
      | (Mercedes IS A Auto)
      |
      Mercedes
      [Stern stern]


      EDIT: usegroup.de/software/phptutorial/klassen_und_objekte.html

      hier im 2ten beispiel wird sowas gemacht mit instanzen austausch. scheint vom syntax her richtig zu sein, wie ich es gemacht habe.

      edit: huch das is ja php5 :D und der absatz darunter haha....hm müsste ich mal ausprobieren ob das in php4 genauso geht. müsste doch eigentlich ?(
      edit: oder doch php4. les es dir mal ganz durch. ganz interessant. vor allem das letzte beispiel auch noch.

      das sieht mir aus als wäre der unterschied zwischen php4 und php5 ähnlich wie c++ und java/c#
      in c++ muss man für referenzen dauernd was davor schreiben....in java/c# ist einfach alles eine referenz.

      :)
      für die es interessiert oder noch interessieren wird:
      der oben genannte ansatz für ungelesene threads funktioniert nicht ganz.

      hier meine jetzige funktionierende implementierung:

      function fillThreadread() {
      global $session;

      $lastlogout = $session->userinfo["LastLogout"];
      if (isset($_SESSION["LastFillID"])) $LastFillID = $_SESSION["LastFillID"];
      else $LastFillID = 0;

      $query = "SELECT Autor, ID, PID FROM forum WHERE Zeit > '$lastlogout' AND ID > $LastFillID AND deleted = 0";
      $result = mysql_query($query, $this->connection);
      if(!$result || (mysql_numrows($result) < 1)){
      return NULL;
      }

      $maxid = 0;
      $currentUID = $session->userinfo["ID"];
      while ($row = mysql_fetch_array($result)) {
      $id = $row["ID"];
      $pid = $row["PID"];
      if ($id > $maxid) $maxid = $id;
      if ($row["Autor"] != $currentUID) $_SESSION["threadread"][$pid] = UNREAD;
      }
      $_SESSION["LastFillID"] = $maxid;
      }


      die maximalsuche von maxid ist nicht wirklich nötig, aber egal.
      im vergleich zur oberen variante wird das array jetzt nur noch mit ungelesenen IDs geupdated. das sind genau die, die seit dem letzten aufruf neu hinzugekommen sind.
      das wurde nötig, da vorher während der session gelesene threads nie wieder ungelesen wurden. was aber passieren kann, wenn jemand während der session was neues schreibt.
      daher wird sich nun die letzte ID gemerkt und beim nächsten aufruf von da an weitergeguckt.
      zu dem werden nun alle beiträge genommen und nicht nur threads. das unread/read tag wird aber trotzdem nur für threadIDs gespeichert.

      so...wollte das nur der vollständigkeit halber nochmal dalassen.

      ciao.