Problem mit Templatesystem + Blöcke

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Problem mit Templatesystem + Blöcke

    Hallo liebe PHP Freunde.

    Mein Problem ist kein Problem das noch keiner hatte.
    Daher habe ich seit über einer Woche das Internet durchsucht nach Lösungen.
    Es gab auch diverse Lösungsvorschläge für mein Problem, leider waren diese meist nur sehr speziell und nicht für mich anwendbar oder für mich total unverständlich.
    Die Konsequenz daraus ist, dass ich nun euch hier fragen muss, obwohl sich der ein oder andere sicher gerade denkt: Das hatten wir doch alles schon.

    Naja nur das vorweg.

    Nun mein Problem.

    Ich möchte meine Seite mit Templates ausstatten, dazu habe ich mir eine Testumgebung geschaffen, die aus drei Dateien besteht.

    1. news.php
    2. template.class.php
    3. news.tpl

    Wir Ihr erkennt, sind das die drei Grundvoraussetzungen für ein Templatesystem.

    Als erstes der Code von allen drei Dateien:

    1. news.php
    PHP-Code:
    include('config.inc.php');
    include(
    'template.class.php');

    $SQL =  "SELECT news_author, news_text ".
                
    "FROM news ";
                
    $DATA mysql_query($SQL);

    while ( 
    $row mysql_fetch_array($DATA) )
    {
        
    $author $row['news_author'];
        
    $text   $row['news_text'];
    }

    $values =   array   (
                            
    'AUTHOR' => $author,
                            
    'TEXT' => $text
                        
    );
                        
    $template = new template();
    $template->read_template_file('news.tpl');
    $template->replace_content($values);
    $template->parse_content(); 
    2. template.class.php
    PHP-Code:
    class template
    {
        var 
    $tmp_file;
        var 
    $content;
        
        function 
    read_template_file($source)
        {
            
    $this->tmp_file $source;

            if( !
    file_exists $this->tmp_file ) )
            {
                echo 
    "Konnte Template-File <b>"$this->tmp_file ."</b> nicht lesen!";
            }
            else
            {
                
    $this->content file_get_contents($this->tmp_file);
                
                return 
    $this->content;
            }
        }
        
        function 
    replace_content($array)
        {
            foreach ( 
    $array as $keyname => $value )
            {
                
    $this->content str_replace "{"$keyname ."}"$value$this->content );
            }
        }
        
        function 
    parse_content()
        {
            echo 
    $this->content;
        }

    3. news.tpl
    PHP-Code:
    <html>
    <
    body>

    <!--- 
    BEGIN newsrow --->
    Autor: {AUTHOR} <br>
    Text: {TEXT}<br>
    <!--- 
    END newsrow --->

    </
    body>
    </
    html
    Wie man an den Dateien hoffentlich erkennt, soll es sich um eine Newsseite handeln.
    Der Code ist bewusster Weise sehr klein gehalten, da es mir ja hier nur um die wesentlichen Dinge geht.

    In der Datei news.php wird die Datenbank ausgelesen.
    Das funktioniert 1a.
    Die template.class.php ist das Herzstück, hier wird die Templatedatei (news.tpl) mit dem Code der news.php vereint.
    Für nur quasi einen Wert klappt das 1a.
    Also so wie das Beispiel da steht, wird mir eben immer der letzte Wert der DB ausgespuckt.

    Nun habe ich eben im Internet gesehen, dass andere Coder es so machen, dass sie folgenden Teil
    PHP-Code:
    <!--- BEGIN newsrow --->
    Autor: {AUTHOR} <br>
    Text: {TEXT}<br>
    <!--- 
    END newsrow ---> 
    einmal einlesen und so oft mit Werten füllen, wie Datensätze in der Datenbank stehen.

    Nur leider habe ich keine Ahnung, wie ich soetwas machen soll.
    Habe mir auch schon die Varianten von phpbb2 angeschaut, dort wird eine Funktion namens assign_block_vars verwendet.
    Ich denke diese Funktion macht in etwa das, was ich brauche.
    Leider sehe ich da nicht im geringsten durch.

    Kann mir also jemand Schritt für Schritt erklären, wie ich es schaffe,
    dass der Teil zwischen

    <!--- BEGIN newsrow --->

    und

    <!--- END newsrow --->

    so oft mit den richtigen Variablen gefüllt wird, wie es Datensätze in der Datenbank gibt.
    Dafür wäre ich euch sehr verbunden :>

    Mit freundlichen Grüßen Sodan und danke im Voraus

  • #2
    habs mir nicht ganz durchgelesen, aber nachdem du von "für einen wert klappts 1a" gesprochen hast, habe ich die vermutung, dass du vergisst dass du in der while-schleife die gesamten daten zwar durchlaufen lässt, aber die variable $author jedesmal neu gesetzt wird und nur der letzte Wert erhalten bleibt....!

    Die Blöcke musst du dann heraustrennen und immer hintereinander hängen und jedesmal den Platzhalter ersetzten..... z.B. mit der preg Funktion preg_match

    Für ne Step-by-Step Anleitung fehlt mir leider grad die Zeit, sry
    Für alle die Fehler suchen, gibts gratis tolle Debuggingmöglichkeiten:
    var_dump(), print_r(), debug_backtrace und echo.
    Außerdem gibt es für unsere Neueinsteiger ein hervorragendes PHP Tutorial zu PHP 4 und PHP 5 (OOP)
    Es heißt $array['index'] und nicht $array[index]! Und nein, das ist nicht egal!
    Dieses Thema lesen, um Ärger im Forum und verzögerte Hilfen zu vermeiden.

    Kommentar


    • #3
      mach das doch mit regulären ausdrücke:
      PHP-Code:
      <?php
      $text 
      "<!--- BEGIN newsrow --->News<!--- END newsrow ---><!--- BEGIN newsrow --->Noch mehr News<!--- END newsrow --->";
      preg_match_all("/<!--- BEGIN newsrow --->(.+?)<!--- END newsrow --->/"$text$newsbloeckePREG_PATTERN_ORDER);
      echo 
      $newsbloecke[0][0] . "<br>";
      echo 
      $newsbloecke[0][1];
      //gibt aus:
      //News
      //Noch mehr News
      ?>
      in dem array $newsbloecke[0] sind jetzt die einzelnen news zu finden die kannst du dann in einer schleife ersetzen und nacheinenander ausgeben - hilft dir das? der rest mit while sollte ja klar sein
      Zuletzt geändert von tontechniker; 18.09.2005, 21:09.
      Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

      Kommentar


      • #4
        Vielen Dank für eure Antworten,

        ich versuche auf jedenfall mal die Variante von tontechniker.

        Und es ist keine Schande nicht viel Zeit zu haben Shurakai
        Bin dir nicht Böse.

        mfg Sodan

        Kommentar


        • #5
          So.

          Ein wenig funktioniert es schon, aber noch nicht 100%.
          Irgendwo muss ich da noch nen Logikfehler haben.

          Hier erstmal der neue Quellcode von allen drei Dateien:

          1. news.php

          PHP-Code:
          // Dateien includieren

          include('config.inc.php');
          include(
          'template.class.php');

          // Daten aus der Datenbank auslesen

          $SQL =  "SELECT news_author, news_text ".
                      
          "FROM news ";
                      
          $DATA mysql_query($SQL);

          // Template

          $template = new template();
          $template->read_template_file('news.tpl');

          // Inhalt für den nicht-dynamischen Inhalt

          $var = array    (
                              
          'Ueberschrift' => 'News'
                          
          );

          $template->replace_content($var);

          // Auzzählen wie oft der Block der news wiederholt werden muss

          $blockcount mysql_num_rows($DATA);

          while ( 
          $row mysql_fetch_array($DATA) )
          {
              
          $author $row['news_author'];
              
          $text   $row['news_text'];
              
              
          $values =   array   (
                                  
          'AUTHOR' => $author,
                                  
          'TEXT' => $text
                                  
          );
              
              
          $template->replace_block_content($blockcount,$values);
              
          }

          //$template->parse_content(); 
          2. template.class.php

          PHP-Code:
          class template
          {
              var 
          $tmp_file;
              var 
          $content;
              
              function 
          read_template_file($source)
              {
                  
          $this->tmp_file $source;

                  if( !
          file_exists $this->tmp_file ) )
                  {
                      echo 
          "Konnte Template-File <b>"$this->tmp_file ."</b> nicht lesen!";
                  }
                  else
                  {
                      
          $this->content file_get_contents($this->tmp_file);

                      return 
          $this->content;
                  }
              }
              
              function 
          replace_content($array)
              {
                  foreach ( 
          $array as $keyname => $value )
                  {
                      
          $this->content str_replace "{"$keyname ."}"$value$this->content );
                  }
                  
                  return 
          $this->content;
              }
              
              function 
          replace_block_content($blockcount,$vararray)
              {
                  
          preg_match_all("/<!--- BEGIN --->(.+?)<!--- END --->/"$this->content$blocksPREG_PATTERN_ORDER);

                  
          $this->block_content $this->content;

                  for ( 
          $i 0$i $blockcount 1$i++ )
                  {
                      foreach ( 
          $vararray as $keyname => $value )
                      {
                          
          $this->block_content str_replace "{"$keyname ."}"$value$this->block_content);
                      }
                  }

                  echo 
          $this->block_content ."<br>";
              }

              function 
          parse_content()
              {
                  echo 
          $this->content;
              }

          3. news.tpl

          PHP-Code:
          <html>
          <
          head>
          <
          title>{title}</title>
          </
          head>

          <
          body>

          Hier nichts was sich wiederholt: {Ueberschrift}<br><br>

          <!--- 
          BEGIN newsrow --->
          Autor: {AUTHOR} <br>
          Text: {TEXT}<br>
          <!--- 
          END newsrow --->

          </
          body>

          </
          html
          Mit diesen Dateien, klappt es schon so halb.

          Ich lese zwei Datensätze aus, die werden auch korrekt dargestellt.
          Nur wird der Teil, der nur einmal angezeigt werden soll, mehrmals angezeigt.

          Ich denke, dass der Fehler innerhalb der Klasse liegt, dass da Inhalte von $this->content falsch weitergegeben werden.

          Nur leider fehlt mir momentan ein Plan wie ich das ändern kann.

          Hier noch mal das, was mir dann ausgespuckt wird:


          Hier nichts was sich wiederholt: News

          Autor: Jens
          Text: Dies ist ein Test

          Hier nichts was sich wiederholt: News

          Autor: Sodan
          Text: bla


          Der Teil mit "Hier nichts was sich ..." soll aber nur einmal angezeigt werden und zwar als erstes.

          Ich hoffe ihr seht durch und könnt mir kleinen Template-Anfänger weiterhelfen

          MfG Sodan

          Kommentar


          • #6
            PHP-Code:
            preg_match_all("/<!--- BEGIN --->(.+?)<!--- END --->/"$this->content$blocksPREG_PATTERN_ORDER);
            $this->block_content $this->content
            verarbeitest du $blocks überhaupt weiter?? oder seh ich das falsch
            Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

            Kommentar


            • #7
              Wenn Ihr das gerade sehen würdet, wie ich da sitze und mich selber haue ^^

              das ist natürlich ein berechtigter einwand lieber tontechniker.

              danke erstmal.

              ich werde mal weiter sehen.

              mfg Sodan

              Kommentar


              • #8
                es sieht jetzt so aus, dass er alles macht was er machen soll.

                er ersetzt den sich nicht wiederholenden inhalt und die blocks korrekt.
                es gibt nur noch ein problem.

                er macht es nicht in der korrekten reihenfolge.

                vllt. erkennt einer von euch am code, warum nicht.

                1. news.php
                PHP-Code:
                // Dateien includieren

                include('config.inc.php');
                include(
                'template.class.php');

                // Daten aus der Datenbank auslesen

                $SQL =  "SELECT news_author, news_text ".
                            
                "FROM news ";
                            
                $DATA mysql_query($SQL);

                // Template

                $template = new template();
                $template->read_template_file('news.tpl');

                // Inhalt für den nicht-dynamischen Inhalt

                $var = array    (
                                    
                'Ueberschrift' => 'News'
                                
                );

                $template->replace_content($var);

                // Auzzählen wie oft der Block der news wiederholt werden muss

                $blockcount mysql_num_rows($DATA);

                while ( 
                $row mysql_fetch_array($DATA) )
                {
                    
                $author $row['news_author'];
                    
                $text   $row['news_text'];
                    
                    
                $values =   array   (
                                        
                'AUTHOR' => $author,
                                        
                'TEXT' => $text
                                        
                );
                    
                    
                $template->replace_block_content($blockcount,$values);
                    
                }

                $template->parse_content(); 
                2. template.class.php
                PHP-Code:
                class template
                {
                    var 
                $tmp_file;
                    var 
                $content;
                    var 
                $temp_content;
                    var 
                $data;
                    
                    function 
                read_template_file($source)
                    {
                        
                $this->tmp_file $source;

                        if( !
                file_exists $this->tmp_file ) )
                        {
                            echo 
                "Konnte Template-File <b>"$this->tmp_file ."</b> nicht lesen!";
                        }
                        else
                        {
                            
                $this->file_content file_get_contents($this->tmp_file);
                            
                            
                preg_match_all("/<begin-block>.*^(.+)(^.*?^)(.+)(^<end-block>.*?)/smU"$this->file_content$blocksPREG_PATTERN_ORDER);

                            
                $this->block_content $blocks[0][0];
                            
                            
                $temp_content preg_replace("@<begin-block[^>]*?>.*?<end-block>@si","",$this->file_content);

                            
                $this->data = array($temp_content$this->block_content);

                            return 
                $this->data;
                        }
                    }
                    
                    function 
                replace_content($array)
                    {
                        
                $this->content $this->data[0];

                        foreach ( 
                $array as $keyname => $value )
                        {
                            
                $this->content str_replace "{"$keyname ."}"$value$this->content );
                        }
                        
                        return 
                $this->content;
                    }
                    
                    function 
                replace_block_content($blockcount,$vararray)
                    {
                        
                $this->block_content $this->data[1];

                        for ( 
                $i 0$i $blockcount 1$i++ )
                        {
                            foreach ( 
                $vararray as $keyname => $value )
                            {
                                
                $this->block_content str_replace "{"$keyname ."}"$value$this->block_content);
                            }
                        }
                        
                        echo 
                $this->block_content;
                    }

                    function 
                parse_content()
                    {
                        echo 
                $this->content;
                    }

                3. news.tpl
                PHP-Code:
                <html>
                <
                head>
                <
                title>{title}</title>
                </
                head>

                <
                body>

                Hier nichts was sich wiederholt: {Ueberschrift}<br><br>

                <
                begin-block>
                Autor: {AUTHOR}<br>
                Text: {TEXT}<br>
                <
                end-block>

                </
                body>

                </
                html
                hoffentlich werdet ihr schlau draus.
                es sieht so aus, dass er erst die ausgaben macht aus der funtion replace_block_content und dann hängt noch die ausgaben von parse dran.

                die ausgaben sollen aber in der richtigen reihenfolge geschehen, also erst

                Hier nichts was sich wiederholt: {Ueberschrift}<br><br>

                dann

                Autor: {AUTHOR}<br>
                Text: {TEXT}<br>

                natürlich mit den werten statt den platzhaltern.

                mfg Sodan

                Kommentar


                • #9
                  er macht es nicht in der korrekten reihenfolge.
                  was heißt das? versteh ich dich richtig das er erst die news und dann die überschrift ausgibt??
                  das wäre ja logishc weil du in der fukntion blockcontent den ihnhalt ausgibst und dann parse ausgibts
                  PHP-Code:
                  echo $this->block_content
                  Zuletzt geändert von tontechniker; 21.09.2005, 18:41.
                  Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

                  Kommentar


                  • #10
                    und wie würdest du es machen, damit es nicht dazu kommt

                    Kommentar


                    • #11
                      wenn ich das richtig sehe dann musst du nur in der news.php was ändern:
                      PHP-Code:
                      // Dateien includieren
                      ....
                      $template = new template();
                      $template->read_template_file('news.tpl');

                      $template->parse_content(); //muss hier steht WICHTIG
                      ...
                      $var = array    (
                                          
                      'Ueberschrift' => 'News'
                                      
                      );

                      $template->replace_content($var);

                      // Auzzählen wie oft der Block der news wiederholt werden muss

                      $blockcount mysql_num_rows($DATA);

                      while ( 
                      $row mysql_fetch_array($DATA) )
                      {
                          
                      $author $row['news_author'];
                          
                      $text   $row['news_text'];
                          
                          
                      $values =   array   (
                                              
                      'AUTHOR' => $author,
                                              
                      'TEXT' => $text
                                              
                      );
                          
                          
                      $template->replace_block_content($blockcount,$values);
                          
                      }
                      ... 
                      müsste eigentlich schon helfen --> da du ja bei replace_block_content den inhalt direkt ausgibst
                      Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

                      Kommentar


                      • #12
                        Danke!
                        Werde das dann testen.

                        MfG Sodan

                        Kommentar


                        • #13
                          OK.
                          Habe es getestet. Entweder ich habs falsch gemacht oder es klappt auch so nicht, auf jedenfall gings nicht.

                          Aber ich habe mir eine neue Funktion einfallen lassen.

                          und zwar folgende:

                          PHP-Code:
                          function compile($vararray)
                              {
                                  
                          $handle file ($this->tmp_file);

                                  foreach (
                          $handle as $line)
                                  {
                                      if ( 
                          preg_match_all("<begin-block.newsrow>",$line,$out) )
                                      {
                                          for ( 
                          $x 0$x count($this->block_array); $x++ )
                                          {
                                              echo 
                          $this->block_array[$x];
                                          }
                                      }
                                      else
                                      {
                                          foreach ( 
                          $vararray as $keyname => $value )
                                          {
                                              
                          $this->line str_replace "{"$keyname ."}"$value$line );
                                          }
                                          echo 
                          $this->line;
                                      }
                                  }
                              } 
                          Sie macht folgendes, sie liest das file aus und geht dann Zeile für Zeile vor.
                          Findet sie in einer Zeile etwas wie block.begin ...
                          dann wird hier ein block eingefügt, der vorher geparsed wurde.
                          das funtioniert auch schon.
                          findet er nicht so eine "Marke" ersetzt er einfach so, was er findet mit den normalen array-daten.

                          das problem ist quasi bloß, dass er mir dann auch alles zwischen
                          <begin> und </end> nochmal anzeigt, obwohl das ja schon mal in geparseter form anegezeigt wurde.

                          hat jemand eine idee, wie ich ihm dann sagen könnte, dass er weiter gehen soll in den lines, bis hinter die end-marke?

                          solangsam bekomme ich eine krise mit den blöcken

                          mfg Sodan

                          Kommentar


                          • #14
                            ich verstehe dein problem nicht ganz - vorher war doch nur das problem das er es in der falschen reihenfolge angezeigt hat - lösung wäre $template->parse_content(); einfach nach $template->replace_content($var); hinzuschreiben (war in meiner antwort nicht ganz klar) - versuch das ncoh mal

                            deine fukntion geht jetzt jede zeile durch und wenn sie <begin-block.newsrow> findet dann macht sie das:
                            PHP-Code:
                                            for ( $x 0$x count($this->block_array); $x++)
                                            {
                                                echo 
                            $this->block_array[$x];
                                            } 
                            wenn nciht ersetzt sie aus dem keyname array
                            was ich nicht ganz verstehe - du beziehst dich in den funktionen (for(....){ echo this->block_array und foreach(...)) doch auf das gesamte template ist das beabsichtigt?
                            EDIT:
                            ok - langsam versteh ich das - du beziehst dich auf die zeile
                            Zuletzt geändert von tontechniker; 23.09.2005, 22:09.
                            Die Regeln | rtfm | register_globals | strings | SQL-Injections | [COLOR=silver][[/COLOR][COLOR=royalblue]–[/COLOR][COLOR=silver]][/COLOR]

                            Kommentar


                            • #15
                              ja also falls du merken solltest, dass ich hier einfach nur sinnlosen mist fabriziere, dann bin ich auch gerne bereit meinen code komplett neu zu überarbeiten.

                              ich hab jetzt schon hunderte andere ansätze gefunden und bastle meine ganze freizeit, aber das mit den blöcken ist einfach hinter meinem horizont.

                              vllt. kann ich dich ja animieren selbst sowas zu schreiben
                              wenn du es hinbekommst, kannst du mir es ja sicherlich gut erklären ^^

                              ich werde weitermachen und hoffe, dass ich ans ziel komme.

                              mfg Sodan

                              Kommentar

                              Lädt...
                              X