Ankündigung

Einklappen
Keine Ankündigung bisher.

HTML-Tags und CakePHP

Einklappen

Neue Werbung 2019

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

  • HTML-Tags und CakePHP

    Hallo zusammen,

    ich beschäftige mich gerade für den versprochenen Framework-Vergleich-Artikel mit CakePHP. Neben einigen anderen mehr oder weniger negativen Auffälligkeiten sitze ich gerade an dem Problem, eigene Tags erstellen zu wollen. In meinem Framework ist es möglich eigene TagLibs - und als solche verstehe ich die Helper in CakePHP - zu erstellen. Konkreter Anwendungsfall ist die automatisch formatierte Ausgabe eines

    Code:
    <php:highlight>
      $T = &Singleton::getInstance('benchmarkTimer');
      $T->start('MyEvent');
    
      //
      // Zu messender PHP-Code
      //
    
      $T->stop('MyEvent');
    </php:highlight>
    Code-Blocks als formatierter PHP-Code. Die Logik dazu habe ich bereits implementiert und diese stellt auch keinen Bereich meiner Frage dar.

    Frage:
    Die eigentliche Frage ist nun, wie ich CakePHP beibringe, den HTML-Code in meinem Template zu parsen und formatiert auszugeben?

    Was ich bereits unternommen habe:
    - Suchen und Herunterladen der Datei tags.ini.php
    - Hinzufügen eines weiteren Tags der Form
    Code:
    ; php:highlight
    php_highlight = "<php:highlight>%s</php:highlight>"
    - Erzeugen einer Helper-Klasse (PHP_HIGHLIGHTHelper extends Helper)
    - Hinzufügen des Helpers in meinem Controller (seite_controller)

    Innerhalb des Templates kann ich die Methode test() natürlich verwenden, jedoch parst der AppController von CakePHP diese Tags nicht automatisch.

  • #2
    Hallo,

    dazu habe ich diesen Artikel gefunden. Ich habe es aber noch nicht ausprobiert...

    Kommentar


    • #3
      Hallo phpdummi,

      danke, damit hab ich das hinbekommen. Ist zwar etwas umständlich, da die Jungs das GUI-DOM-Design nicht erklären, aber scheinbar parst CakePHP die Tags immer dann, wenn man einen Helper involviert.
      Der Eintrag in der tags.ini.php war nicht relevant, denn ein weiterer Tag (doku:navigation) konnte ich ohne einen solchen Eintrag auch mit einem Helper parsen.

      Lösung:
      - Einbinden der Widget-Klasse aus deinem Link
      - Implementieren einer erweiterten Widget-Klasse
      PHP-Code:
      <?php
         
      require_once(dirname(__FILE__) . DS 'widget_helper.php');

         class 
      PHPHighlightWidgetHelper extends WidgetHelper
         
      {

            
      /**
            *  Tag definieren
            */
            
      var $tag = array(
                             
      'php:highlight',
                             
      'doku:navigation'
                            
      );


            function 
      tag_php_highlight($attr,$inner_html){

               
      // Quelltext highlighten
               // - Zeilenumbrüche am Anfang entfernen
               // - Leerzeichen und Zeilenumbrüche am Ende entfernen
               // - Leerzeichen und Zeilenumbrüche um den kompletten Text entfernen
               
      $HighlightedContent highlight_string(trim('<?php'.ltrim(rtrim($inner_html),"\x0A..\x0D").' ?>'),true);

               
      // PHP-Anfangstag ersetzen
               
      $HighlightedContent str_replace('<font color="#007700">&lt;?</font>','',$HighlightedContent);
               
      $HighlightedContent str_replace('<font color="#0000BB">&lt;?php','<font color="#0000BB">',$HighlightedContent);
               
      $HighlightedContent str_replace('<font color="#0000BB">php','<font color="#0000BB">',$HighlightedContent);
               
      $HighlightedContent str_replace('<font color="#0000BB"></font>','',$HighlightedContent);

               
      // PHP-Endtag ersetzen
               
      $HighlightedContent str_replace('<font color="#0000BB">?&gt;</font>','',$HighlightedContent);

               
      // Code im DIV zurückgeben
               
      return '<div class="phpcode">'.$HighlightedContent.'</div>';

             
      // end function
            
      }
         
          
      // end class
         
      }
      ?>
      - Einbindung des Helpers in den Controller
      PHP-Code:
      <?php
      ..
      var 
      $helpers = array('HTML','PHPHighlightWidget');
      ..
      ?>

      Kommentar


      • #4
        Schön das es funktioniert. Das dafür eine Helper Instanz erforderlich ist kam mir auch etwas suspekt vor. Da der Blog Eintrag schon etwas älter war, habe ich noch ein wenig im Manual von CakePHP gesucht - ohne Erfolg.

        Btw: Funktioniert var $helpers = array('HTML','PHPHighlightWidget'); tatsächlich?
        Besser gesagt darf das überhaupt noch funktionieren?

        Kommentar


        • #5
          Grüatzi,

          habe ich noch ein wenig im Manual von CakePHP gesucht - ohne Erfolg.
          So ging mir das auch. Ich habe nach all dem Try&Error&RTFM immer noch nicht ganz verstanden, wie das Framework intern (GUI-mäßig) arbeitet.

          Btw: Funktioniert var $helpers = array('HTML','PHPHighlightWidget'); tatsächlich?
          Besser gesagt darf das überhaupt noch funktionieren? :Cool:
          Ja, das funktioniert wirklich. Mein Verständnis ist einfach, dass man einen Helper in einem View bekannt machen muss, damit er seine Arbeit tut. Genauer spezifiziert, warum man das tun muss ist im Manual nicht. Ich habe eine Beschreibung erwartet, die mir sagt, welche Methoden wann und zu welchem Zweck ausgeführt werden. Nur dann kann man Erweiterungen einfach implementieren.

          However, ich werde mir das noch weiter ansehen und versuchen das ActiveRecord-Thema nochmal anzuschauen.

          Kommentar


          • #6
            Zitat von dr.e.
            Grüatzi
            Schon im Urlaub? Deserteur!
            Zitat von dr.e.
            Btw: Funktioniert var $helpers = array('HTML','PHPHighlightWidget'); tatsächlich?
            Besser gesagt darf das überhaupt noch funktionieren?
            Ja, das funktioniert wirklich. Mein Verständnis ist einfach, dass man einen Helper in einem View bekannt machen muss, damit er seine Arbeit tut. Genauer spezifiziert, warum man das tun muss ist im Manual nicht. Ich habe eine Beschreibung erwartet, die mir sagt, welche Methoden wann und zu welchem Zweck ausgeführt werden. Nur dann kann man Erweiterungen einfach implementieren.
            Ich würde sagen so sollte es auch sein, zu viel Magie bringt Unübersichtlichkeit...

            PS:
            "Besser gesagt darf das überhaupt noch funktionieren? "
            Bezog sich mitunter auch auf var (PHP4). War wohl doch nicht so witzig wie ich dachte

            Kommentar


            • #7
              Hallo phpdummi,

              Schon im Urlaub? Deserteur!
              Nein, nur ein gewöhnlicher Sonntag, den ich damit zubringe mir CakePHP genauer anzusehen. Urlaub gibts erst in 2 Wochen. Dieser wird wohl aber auch nicht erholsamer, schließlich wartet noch die PHP 5 Umstellung und der Vergleichsartikel...


              Ich würde sagen so sollte es auch sein, zu viel Magie bringt Unübersichtlichkeit...
              Das scheint mir auch deren Philosophie zu sein. Wenn jedoch das Manual auch ohne so viel Magie wäre, fände ich das nicht schlecht.


              PS:
              Ja ich weiß, das gute PHP 4. Aber soviel ihr auch drüber schimpft, man kann trotz alle dem verdammt komplexe Geschichten damit bauen.


              Nächstes Thema: (Ausnahmsweise stelle ich hier mal die Fragen )
              Soweit ich dem Manual entnehmen kann ist es nicht möglich mehrere Views innerhalb eines Layouts anzulegen. Sollte das doch so sein, korrigiere mich bitte, aber das Manual spricht immer von einem Layout ([..] your layout [..]). Die Problemstellung die ich dabei habe ist, dass ich für mein Menü auf der linken Seite, meinen Header und mein Menü oben jeweils einen eigenen View erzeugen möchte. Einen denkbaren Umweg stellt das Platzieren mehrere Elemente im "Hauptview", der in einem "Haupt-Layout" steckt dar, was jedoch den Nachteil mit sich bringt, dass ich scheinbar nicht beliebig Views schachteln kann. Oder gibt es doch eine Möglichkeit eine 1:n-Beziehung zwischen Layout und View zu erzeugen?

              Kommentar


              • #8
                Hallo Dr.E.,

                Mehrere Layouts sind schon möglich, allerdings in etwas anderer Form als du es vielleicht gewohnt bist. (Soll nicht heißen das CakePHP hier einen besseren Ansatz hat, ganz im Gegenteil)

                Dem View Kapitel zu entnehmen:
                You can create as many layouts as you wish for your Cake site, just place them in the app/views/layouts directory, and switch between them inside of your controller actions using the controller's $layout variable, or setLayout() function.
                Im Falle eines Menüs wird, im Gegensatz zum Header und Footer, von Elementen gesprochen.
                Ads, help boxes, navigational controls, extra menus, and callouts are often implemented in Cake as elements. An Element is basically a mini-view that can be included in other Views.
                Dazu wird im View per $this->renderElement('element'); das gewünschte Element aufgerufen. Sollen Parameter übergeben werden, geschiet dies über ein Array:
                PHP-Code:
                <?php
                echo $this->renderElement('helpbox', array("helptext" => "Oh, this text is very helpful."));
                 
                ?>

                Kommentar


                • #9
                  Hallo phpdummi,

                  das Thema Elements hatte ich gesehen und auch als solches verstanden. Nur leuchtete mir irgendwie nicht ein, dass ich mit CakePHP dann offensichtlich nur 3 echte Struktur-Ebenen habe: Layout, View, Element.

                  Das bedeutet dann im Umkehrschluss, dass ich in einem Layout nur eine View-Area habe, in die ich Views "klemmen" kann. Innerhalb eines Views kann ich dann mit den Elements weitere Elemente inkludieren.

                  Der Witz an der Angelegeheit ist nur, dass ich die Elemente nicht im View, sondern im Layout brauche, was offensichtlich nicht möglich ist, da ich zwar mehrere Layouts haben kann, aber nicht mehrere View-Areas in einem Layout. Denn wenn ich die "meherer Elemente innerhalb eines Views"-Geschichte mache, begebe ich mich in echte Abhängigkeit, da ich in einem View nicht beliebig tief strukturieren kann. Es steht mit mit dem implementierten Routing nämlich nur eine Ebene für den Controller (hier /Seite) und eine für die Action (hier /Seite/Startseite) zur Verfügung. Diese nutze ich bereits für den Content-Bereich, da ich ja dort unterschiedliche Contents einbinden will. Da ich nicht gesehen habe, wie man mehrere Views per URL steuert, glaube ich nicht, dass das so funktioniert, wie ich mir das vorstelle, bzw. es sein müsste.

                  Hilf mir, wenn ich auf dem Schlauch stehe, aber ich vermute, dass das nix wird...

                  Kommentar


                  • #10
                    Hallo dr.e.,

                    ich denke auch das das nix wird. Doch zunächst einmal die Frage ob ich dich überhaupt richtig verstanden habe.
                    Es existiert ein Basis-Layout indem du Header und Footer untergebracht hast.
                    In diesem Layout soll aber direkt das Menü eingebunden werden, welches wiederum nicht statisch ist (also eine gewisse Logik bzw. Daten benötigt).
                    Egal welche Action bzw. View aufgerufen wird, dieses Basis Layout soll immer eingebunden werden.
                    Soweit korrekt?

                    Kommentar


                    • #11
                      Ich bin mir jetzt auch nicht sicher ob ich richtig verstanden habe was ihr wollt...

                      Es gibt neben $this->renderElement() auch noch $this->requestAction().
                      Damit ist es möglich innerhalb eines Views andere Actions/Controller aufzurufen.

                      Man könnte also Im "Grund-Layout" (oh man mir ist die Nomenklatur von View/Layout/View-Area irgendwie nciht ganz klar ) über einen Aufruf von $this->requestAction('menus/display'); das Menu rendern lassen und einbinden.

                      Kommentar


                      • #12
                        Hallo phpdummi,

                        genau das meine ich. Unter http://adventure-php-framework.org/Seite/Klassen gibt es ein UML, das mein Vorhaben beschreibt.

                        - Ein Basis-Layout mit mehreren Views
                        - In den Views wird jeweils
                        - Menü
                        - Inhalt
                        - Header
                        eingeblendet und zwar unabhängig von einander.

                        Das unter dem UML gezeigte Template ist ein Beispiel für ein Haupt-Template/-Layout, das mit "<core:importdesign [..] />" Views einbindet. das ist zwar ein Beispiel aus der Doku-Seite, die mit meinem Framework implementiert ist, jedoch muss ich irgendeine Vergleichsbasis haben - eben eine bereits bestehende Seite.


                        @Agrajag:
                        Es gibt neben $this->renderElement() auch noch $this->requestAction().
                        Damit ist es möglich innerhalb eines Views andere Actions/Controller aufzurufen.
                        Ist mir bekannt, ich möchte aber nicht im selben View einen anderen (zusätzlichen) Controller aufrufen, sondern einen weiteren View in das Basis-Layout einbinden. Im Manual und in den Beispielen steht leider nur, dass man im Layout ein

                        Code:
                        <?php echo $layout_for_content; ?>
                        einbinden kann, nicht aber ein

                        Code:
                        <?php echo $layout_for_VIEW1_content; ?>
                        
                        <?php echo $layout_for_VIEW2_content; ?>
                        <!-- some more html stuff
                        <?php echo $layout_for_VIEW3_content; ?>
                        schreiben kann, wobei ich mich VIEW[1-3] unterschiedliche Views innerhalb des Basis-Layouts adressiere.


                        Man könnte also Im "Grund-Layout" (oh man mir ist die Nomenklatur von View/Layout/View-Area irgendwie nciht ganz klar ) über einen Aufruf von $this->requestAction('menus/display'); das Menu rendern lassen und einbinden.
                        Die "Nomenklatur" ist die: eine View-Area ist ein Bereich, in dem später ein View angezeigt wird. Mit CakePHP hast du die Möglichkeit für den Content-Bereich (mehr gibt's offensichtlich nicht) über die URL gesteuert unterschiedliche Contents einbinden/anzeigen zu lassen. das passiert über die Controller, bzw. deren Action-Methoden.
                        Wie würdest du das genau implementieren? Ich hab keine Möglichkeit, oder besser gesagt keinen Controller gefunden, der für das Basis-Layout zuständig ist. Würde es einen solchen geben, könnte ich dort mit den bereits diskutierten Mitteln ein dynamisches Menü erzeugen.

                        Kommentar


                        • #13
                          Hallo dr.e,

                          nun bist du an einem kritischen Punkt angelangt! Bis jetzt habe ich die Erfahrung gemacht, dass eben diese "Denke" nicht vorgesehen ist.
                          Eben darum habe ich dich auch zu einem Vergleichsartikel angespornt - der spätestens an diese Stelle die Vorteile deines Frameworks aufzeigt.

                          Mir ist bis jetzt bei keinem Framework, das auf Einfachheit Wert legt, ein allgemein gültiges Paradigma für diese mehrfache Verschachtelung untergekommen.
                          Ich hatte mich für ein kleineres Projekt für CodeIgniter entschieden, da der Einarbeitungsaufwand gleich Null war.
                          Auch dort bin ich an eine Stelle gekommen, an der ich für einzelne Sprachen unterschiedliche Templates mit unterschiedlich tiefer Verschachtelung einbinden wollte.
                          Meine Lösung dieses "Problems" bestand letztlich darin, die vorhandene Parser Klasse zu erweitern.
                          Ob meine Lösung nun besonders elegant war bezweifle ich gerade mal.
                          Da mir auch der Umstand auf die Nerven ging, pro View immer wieder das Basis-Layout einzubinden, habe ich direkt noch den Controller erweitert usw. ... Lästig!

                          Um zur Problemlösung zurückzukommen:
                          Theoretisch müsstest du in jedem View die setLayout Methode aufrufen und jedem Logischen Element über ein Array die nötigen Daten zukommen lassen - umständlich!
                          Eine andere Möglichkeit wäre eben den Parser zu erweitern (der HTML Helper müsste das sein?), was aber auch nicht wirklich dem Sinn eines Frameworks entgegen kommt.

                          @Agrajag:
                          Bist du den nun Cake Benutzer? Wenn ja, müsstest du ja schon auf dieses Problem gestoßen sein. Wie löst du das?
                          Ich denke es gibt zumindest für eine Erweiterung bestehender Klassen bereits fertige "Lösungen" im Netz ...

                          Kommentar


                          • #14
                            Hallo phpdummi,

                            Eben darum habe ich dich auch zu einem Vergleichsartikel angespornt - der spätestens an diese Stelle die Vorteile deines Frameworks aufzeigt.
                            Ich mach ja schon... Finde es auch gut, dass du so in die Diskussion mit einbringst, merci!

                            Ich warte noch auf Agrajag's Lösung und versuche dann deinen Ansatz über den HTML-Helper/Parser.

                            Kommentar


                            • #15
                              Hallo dr.e,

                              ich würde mich auch über eine Lösung von einem Cake Benutzer freuen - sieht nur recht dünne aus
                              Finde es auch gut, dass du so in die Diskussion mit einbringst, merci!
                              Solange ich keinen Artikel schreiben muss helfe ich gerne
                              Ich habe eben nochmal eine bisschen gesucht und folgendes gefunden:
                              Smarty mit CakePHP
                              Layout mit Joomla! Templates
                              (Gefunden in der Bakery)
                              und versuche dann deinen Ansatz über den HTML-Helper/Parser.
                              Ich hoffe du versuchst nicht den Parser zu erweitern, das wäre in der Tat zu viel des Guten!
                              Ich würde den etwas unschönen Ansatz über die set() Methode versuchen (bzw. habe es sogar mal für 10min versucht und die Geduld verloren )
                              Dazu habe ich folgendes gefunden: pages_controller.php
                              PHP-Code:
                              <?php
                              //...
                              class PagesController extends AppController{
                                    
                                    
                              // [...]
                                   
                                       
                              function display() {
                                             
                                             
                              // [...]

                                             
                              $this->set('page'$page);
                                             
                              $this->set('subpage'$subpage);
                                             
                              $this->set('title'$title);
                                             
                              $this->render(join('/'$path));

                                             
                              // [...]
                                         
                              }
                              ?>
                              Hey dacht ich mir, da geht doch noch was! Während ich noch Yesterday höre (Link für alle denen die Schallplatten Nadeln ausgegangen sind -> gleiche "Qualität" )
                              finde ich doch tatsächlich einen Beispiel Controller: controller.php
                              und die dazu passende HTML Datei: default.thtml

                              Na wenn das nichts ist!

                              Kommentar

                              Lädt...
                              X