Variabili del template di scoping nelle relazioni "has-a" (composizionali)

0

Sto sviluppando un nuovo linguaggio di template per PHP, e una delle caratteristiche è un approccio orientato agli oggetti per i modelli figlio nidificati. Ad esempio, posso dichiarare un oggetto di tipo HtmlBuilder come questo:

$template = "
  <div>
    <h1>{{field1}}</h1>
    <p>{{field2}}</p>
  </div>";

$content = [ 
   "field1" => "value1",
   "field2" => "value2"
];

$hb = new HtmlBuilder($content, $template);
echo $hb->render();

In questo caso, HtmlBuilder fa un semplice find-and-replace nei campi. Ma potrei anche nidificare un HtmlBuilder (o uno dei suoi sottotipi più specializzati) all'interno di un altro:

// Child template
$template1 = "
  <p>{{field2}}</p>
  <p>{{field4}}</p>
  ";

$content1 = [ 
   "field4" => "something else"
];

$hb1 = new HtmlBuilder($content1, $template1);

// Parent template
$template2 = "
  <div>
    <h1>{{field1}}</h1>
    {{field3}}
  </div>";

$content2 = [ 
   "field1" => "value1",
   "field2" => "value2",
   "field3" => $hb1
];

$hb2 = new HtmlBuilder($content2, $template2);
echo $hb2->render();

In questo caso, quando viene eseguito il rendering di $hb2 , $hb1 verrà automaticamente visualizzato nel segnaposto field3 .

La mia domanda è, ha senso progettare questo sistema in modo tale che il valore di field2 venga automaticamente trasferito dal modello principale al modello figlio (pur consentendo la sua sovrascrittura nel figlio)? Oppure, dovrei richiedere che venga passato esplicitamente in $content1 ?

    
posta alexw 08.01.2015 - 22:02
fonte

1 risposta

1

Le dipendenze implicite sono cattive, specialmente se il tuo motore di template non si lamenterà delle variabili mancanti. Credo che sarebbe vantaggioso per ogni frammento di modello sapere quali variabili ha bisogno e rifiutare di essere renderizzato o istanziato con argomenti sbagliati.

Ecco un esempio in cui la mancanza di scoping introdurrà difficoltà:

$academic_staff_template = "
  <div>
    <h4>{{ title }} {{ name }}</h4>
    {{ bio }}
  </div>
";
$lecturer = new HtmlBuilder([], $academic_staff_template);

$lecture_template = "
  <html>
    <head>
      <title>{{ title }}</title>
    </head>
    <body>
      <h1>Lecture {{ title }}</h1>
      {{ description }}
      {{ lecturer }}
    </body>
  </html>
";
$vars = [
  "title" => "Archaeology 101",
  "description" => "...",
  "lecturer" => $lecturer,
  "name" => 'Henry Walton "Indiana" Jones, Jr.',
  "title" => "Dr.",
  "bio" => "...",
];
$lecture = new HtmlBuilder($vars, $lexture_template);

Entrambi i modelli usano una variabile title , ma usano lo stesso nome per indicare qualcosa di completamente diverso. Il tuo progetto attuale produrrebbe questo output renderizzato:

<html>
  <head>
    <title>Dr.</title>
  </head>
  <body>
    <h1>Lecture Dr.</h1>
    ...
    <div>
      <h4>Henry Walton "Indiana" Jones, Jr.</h4>
      ...
    </div>
  </body>
</html>

A volte, è estremamente utile includere un altro modello senza inserire un nuovo scope variabile. Ad esempio, {% include "snippet/footer" %} potrebbe essere una direttiva utile per caricare uno snippet. Ma se cerchi di creare modelli incapsulati e liberamente accoppiati , questo si sta verificando direttamente in scontri con lo spazio dei nomi e tutti i tipi di problemi.

Ecco un'idea: quando analizzi un modello, prendi nota di tutte le variabili richieste. Tale modello analizzato può essere visualizzato in due modi:

  • Tramite l'API: $result = $engine->parse($source)->render(["var1" => "value1"]) . Il metodo render genera un'eccezione se non vengono fornite tutte le variabili necessarie.
  • All'interno del linguaggio del modello: se block è associato a un oggetto modello analizzato, la sintassi come {{ block var1: "value" var2: someVariable }} potrebbe rendere il modello. Nessuna variabile tranne quelle passate esplicitamente sarebbe disponibile all'interno del blocco. Se gli argomenti specificati non corrispondono agli argomenti richiesti da block , verrebbe generato un errore.

Poiché alcuni dati appartengono naturalmente insieme, sarebbe fantastico offrire l'accesso agli array all'interno del tuo linguaggio template. Quindi potremmo passare un singolo dizionario con informazioni sul docente al modello dello staff accademico. Ecco come progetterei quell'interfaccia:

$lecturer_template = $engine->parse("
  <div>
    <h4>{{ person.title }} {{ person.name }}</h4>
    {{ person.bio }}
  </div>
");
$page_template = $engine->parse("
  <html>
    <head>
      <title>{{ course.title }}</title>
    </head>
    <body>
      <h1>Lecture {{ course.title }}</h1>
      {{ course.description }}
      {{ lecturer person: course.lecturer }}
    </body>
  </html>
");

$course = [
  "title" => "Archaeology 101",
  "description" => "...",
  "lecturer" => [
    "name" => "Henry Walton \"Indiana\" Jones, Jr.",
    "title" => "Dr.",
    "bio" => "...",
  ],
];

$result = $page_template->render(["course" => $course, "lecturer" => $lecturer_template]);
    
risposta data 09.01.2015 - 17:35
fonte

Leggi altre domande sui tag