2016-06-26 10 views
0

Ich habe mir schon eine Weile den Kopf verdreht, weil es zwar in PHP einfach "zu machen" ist, aber das Ergebnis nicht erweiterbar ist, weil PHP keine vernünftige eingebaute Template-Syntax hat. Also habe ich Twig installiert, vorausgesetzt, es hätte eine eingebaute Explosionsfunktion, um zwischen den Blöcken zu iterieren. Aber es scheint keine Möglichkeit zu geben, den Inhalt in eine willkürliche Anzahl von Unterabschnitten zu unterteilen.Wie man Twig/PHP/HTML-Vorlagenblöcke als willkürliche Anordnung von explodierten Unterabschnitten rendert?

Ich überlegte, {% embed %}, zu verwenden, aber das Dokument soll entsprechend den Abschnitten entworfen werden, die in der übergeordneten Vorlage angezeigt werden. Und in welcher Reihenfolge (das ist variabel; das ist für ein Formular mit einer Menge Geschäftslogik drin.)

Ich habe das Formular in PHP erstellt und es als "sehr schöne" statische Seite mit zu arbeiten leicht eine beliebige Anzahl von Teilbereichen, die alle funktionieren und unabhängig von denen interaktiv angezeigt werden (basierend auf z. B. Benutzerprivilegien), aber das Templatisieren ist die Herausforderung.

Die statische (twigless) Version basiert auf dem Exportieren des analysierten Inhalts in ein Array, das dann mit den entsprechend formatierten Divs für jeden sichtbaren Abschnitt umschlossen werden kann. Dies funktioniert, aber erfordert mich eingeschlossen html und Objekt Pufferung zu verwenden, das schrecklich aussieht und wäre nicht leicht zu pflegen:

$content = include("form_content_html.php"); // return an object-buffered array 
// I was including the escaped values here using if isset($data) and echo short tags. 

foreach ($content as $section) { /* do something; */ } 

$template = include("form_template_subsection.php"); 

$formview->addSubsectionTemplate($template); 

echo $formview->addSubsection($content,$i++,$type); 
// fill section of $type with $content[$i] if isset 

echo $formview->addSubsection($content,$i++,$sometype); 
// $types have different css class for certain effects 

// etc. not the best approach.

(Ich brauche alle Benutzer/db Inhalt zu entkommen, bevor es auf die Form Wert verbindlich, aber Da die Formularfelder sehr benutzerdefiniert sind, habe ich sie in ihre eigene Inhaltsschicht getrennt, so dass dies die einzige Ebene ist, deren Inhalt zur Zeit maskiert werden muss.)

Also vergiss das, jetzt benutze ich Twig. (Anmerkung: nicht Symfony2, da das Projekt auf einem gemeinsamen Webhost ist.)

Ich glaube nicht, es gibt einen Weg von {%extend%}ing die Mutter Vorlage, so dass einige der Kinder Schablonenblöcke sind „Drop in“ dem Namen Elternvorlagenbehälter, der Rest wird ignoriert; was ich suche, denn auf diese Weise kann ich die gesamte Logik in die oberste Ebene setzen (welche Teile des Formulars sichtbar machen usw.) und zuerst die Werte übergeben.

Beachten Sie, dass der Stil der Formularabschnitte von der Struktur der übergeordneten Vorlage und nicht vom untergeordneten Inhalt diktiert wird. Z.B. Abschnitt 1 kann Inhalt 1 und css css auf Inhalt 2 in Abschnitt 2 anzeigen; oder Abschnitt 1 und 2 mit derselben CSS können unterschiedliche Inhalte anzeigen.

Wenn ich das Formular in 15 Nur-Content-Subtemplates aufteilen würde und diese dann bedingt in die Parent-Datei aufnehmen würde, würde es funktionieren. Aber das scheint den Zweck der Verwendung einer Template-Engine zu besiegen? Obwohl Twig es auf diese Weise viel einfacher macht, mit enthaltenen Dateien zu arbeiten, die HTML-Snippets enthalten, lassen Sie mich wissen, ob das eine bevorzugte Lösung ist.

Soll ich den Inhalt Knoten in nummerierte {% block1 %}, {% block2 %} usw. Unterabschnitte und dann renderBlock in meiner PHP-Ansicht-Klasse teilen?

Wenn Twig eine {% section %}...{% section %} Syntax hatte, die es Ihnen erlaubt, die Vorlage in Stücke zu zerlegen und dann jedes Stück als ein Array von Blockelementen zu analysieren ... nun, das habe ich halb erwartet und wünschte, ich könnte es selbst hinzufügen.

+0

Was ich suche ist das Äquivalent von "iterate über getElementsByClassName" im Knoten/Xpath-Modell, und dann für Ergebnisse 1, 3 und 4, setzen Sie die Anzeigeklasse, wenn ($ x) nicht festgelegt 2 und 5, und wickeln Sie das übergeordnete Element von jedem "in der entsprechend gestalteten Vorlage ein und legen Sie diese anschließend in die übergeordnete Vorlage ab. – Ber

Antwort

0

Ich habe die Lösung gefunden, Ich denke :

(Von der Twig Dokumentation)

Der Set-Tag kann auch zu 'Capture' Brocken von Text verwendet werden:

{% set foo %} 
    <div id="pagination"> 
    ... 
    </div> 
{% endset %} 

Ergo, set kann über anonyme aufeinanderfolgende Blöcke verwendet werden, iterieren:

{% set i=0, out=[] %}{# declare top scope #} 

{% block initialize_content %}{# use once #} 
    {% set i=0, out=[] %}{# prevent dupes #} 
    {% set foo %} 

     <div id="pagination">...</div> 

    {% endset %}{% set out=out|merge({ i: foo}) %}{% set i=i+1 %}{% set foo %} 

     {{ escape_variables_here }} ... more html 

    {% endset %}{% set out=out|merge({ i: foo}) %}{% set i=i+1 %}{% set foo %} 

     {{ variables_all_scoped_to_same_context }} ... more html 

     {# so dividers can be moved "up and down" if necessary ... #}  

    {% endset %}{% set out=out|merge({ i: foo}) %}{% set i=i+1 %}{% set foo %} 

     {# ... like this. ^^a tag/macro could probably define this #} 

    {% endset %}{% set out=out|merge({ i: foo}) %} 
    {# or loop over i = 0..n or i = loop.index0 #} 

{% endblock initialize_content %} {# end setter #} 
{% block content %} 

    {% if key is defined and out.key is defined %}{{ out.key |raw }}{% endif %} 

    {# output top-scoped var (outputs nothing if setter not called) #} 
    {# the setter doesn't have to be in its own block, but that allows 
    the variables in the content to be redefined in setter's scope. #} 

{% endblock %} 

(vgl Setting element of array from Twig)

+0

*** Blockinhalt *** sollte wahrscheinlich ein Makro sein: *** {% Makroinhalt (out, key)%} *** und include ** out ** durch Einschließen der Datei und *** initialize_content ** * als Block, um den Wert von ** out ** festzulegen. – Ber

0

Ist das eine mögliche Lösung? Von der Twig Dokumentation:

Horizontal Wiederverwendung ist ein Weg, um das gleiche Ziel wie mehrere Vererbung, aber ohne die damit verbundene Komplexität zu erreichen:

{% extends "base.html" %} 

{% use "blocks.html" %} 

{% block title %}{% endblock %} 
{% block content %}{% endblock %}

Die Verwendung Anweisung Zweig erzählt definiert die Blöcke zu importieren in blocks.html in der aktuellen Vorlage (es ist wie Makros, aber für Blöcke):

{# blocks.html #} 

{% block sidebar %}{% endblock %}

Hinweis: Die Variable use importiert nur eine Vorlage, wenn sie nicht eine andere Vorlage erweitert, wenn sie keine Makros definiert, und wenn der Text leer ist. Aber es kann andere Vorlagen verwenden.

Nun, das ist ein bisschen gründlich weniger als unklar.

(Bezieht sich "es" auf die importierte Vorlage, die andere Vorlagen verwenden kann, oder bedeutet "es", dass eine Vorlage mehr als eine Vorlage oder beides verwenden kann und wenn der Text leer ist, bedeutet das ? Körper des Tags importiert Blockes Wenn ja, dann ist es vielleicht keine Lösung)

Wäre es möglich, so etwas zu tun.

{# form_template.html #} 
{% extends "form_content.html" %} 

{% block section1 %} 
    <div class="{{ style1 }}"><div class="{{ style2 }}">etc. 

     {{ parent() }} 

    </div></div>{% endblock %} 

Oder das? ...

{# form.html #} 

{% use "form_content.html" %} 

{% for sections as i %} 
    {% block wrapper_elements %}{% block section{{i.name}} %}{% endblock %} 
    {% endblock %} 
{% endfor %} 

{# form_content.html #} 

{% use "form_fields.html" %} 

{% block section1 %}{% if field1 %} 
     Actual content here: {% block field1 %}{% endblock %} And here 
    {% else %}&nbsp;{% endif %} 
{% endblock %} 

{% block section2 %}More actual content here{% block section2 %} 

Aber wenn ja, wie über die Abschnitte zu durchlaufen, bevor jedes in form.html nennen?