ZURÜCK

AngularJS mit Twig

Kombination des Javascript Frameworks AngularJS mit der PHP Template-Engine Twig.

Datum: 2015-11, Tags: Angular JS, Twig, PHP, Howto


AngularJS und Twig unterscheiden sich grundsätzlich darin, dass AngularJS ein Client-Framework ist, also im Browser des Seitenbesuchers läuft, während Twig als Template-Engine serverseitig eingebunden wird. Die Module in AngularJS bilden sowohl das Model, als auch View und Controller, währen Twig lediglich den View-Aspekt abdeckt. Trotzdem kommt es vor, dass beide Komponenten in einem Projekt geleichzeitig eingesetzt werden oder werden müssen. Beispielsweise wird eine Webseite grundlegend mit Twig-Templates erstellt, darin wird aber AngularJS verwendet - wie gerade in dieser Seite.

Leider benutzen sowohl AngularJS, als auch Twig per default die gleiche Syntax zur Auszeichnung ihrer Funktionen und Filter: doppelte geschweifte Klammern, wie z.B. {{ 'Hallo Welt' }}. Dieser Ausdruck führt sowohl bei AngularJS, als auch bei Twig dazu, dass der eingeklammerte Text ausgegeben wird. Die meisten Ausdrücke hingegen sind jedoch spezifisch für entweder das eine oder andere Framework und führen zu Seitenfehlern, wenn sie vermischt werden. Ein klare und eindeutige Trennung der Auszeichnungen ist erforderlich. Wie das erreicht wird, wird im Folgenden beschrieben.


Ein einfaches AngularJS Projekt


Für eine einfache Webseite mit AngularJS benötigen wir lediglich eine einfache HTML-Seite demo.html, die die AngularJS-Bibliothek aus dem Content-Delivery-Network von Google lädt. Zusätzlich legen wir noch eine extra Datei für unsere Angular-Module an, app.js.

demo.html
<!DOCTYPE html>
<html ng-app="demo">
  <head>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script type="text/javascript" src="app.js"></script>
  </head>
  <body>
    <h2 ng-style="{color: '#66c'}">{{ 'Hello AngularJS' | uppercase }}</h2>
  </body>
</html>
app.js
var app = angular.module('demo', []);


Über den tag <html ng-app="demo"> wird unser Angular-Modul "demo" für die komplette Webseite initialisert. Dadurch können wir die Angular-Syntax ng-style="{color: '#66c'}" und {{ 'Hello AngularJS' | uppercase }} benutzen. Wenn wir die Seite über einen Browser aufrufen, erscheint die von Angular gerenderte Ausgabe:


HELLO ANGULARJS


Integration in einem Twig-Template


Für ein Twig-Projekt müssen wir einen Controller auf PHP-Basis erstellen, der gleichzeitig das Detenmodell beinhalten soll. mit Hilfe von Twig können wir dann die Ansicht erzeugen.

Um Twig herunterzuladen, benutzen wir den Paketmanager Composer aus einem Terminal heraus:

composer require twig/twig
Using version ^1.23 for twig/twig
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files

ls -al
insgesamt 36
drwxr-xr-x  3 user users 4096 24. Nov 12:23 .
drwxrwxrwx 55 user users 4096 24. Nov 09:36 ..
-rw-r--r--  1 user users  176 24. Nov 10:46 app.js
-rw-r--r--  1 user users   56 24. Nov 12:21 composer.json
-rw-r--r--  1 user users 2732 24. Nov 10:09 composer.lock
-rw-r--r--  1 user users  293 24. Nov 09:57 demo.html
drwxr-xr-x  4 user users 4096 24. Nov 12:21 vendor

Dann erstellen wir unseren Controller index.php und das Twig-Template demo.html.twig

index.php
<?php

require_once './vendor/autoload.php';

$loader = new Twig_Loader_Filesystem(__DIR__);
$twig = new Twig_Environment($loader);

$viewdata['greetings'] = array(
  'Robin Williams' => array('Nano Nano!', 'Gooood Morning!'),
  'Lionel Richie' => 'Hello?!',
  'Leonard Nimoy' => 'LLAP!',
  'Bruce Willis' => 'Yippie-Ka-Yeah!'
);
echo $twig->render('demo.html.twig', $viewdata);

demo.html.twig
<!DOCTYPE html>
<html ng-app="demo">
  <head>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script type="text/javascript" src="app.js"></script>
  </head>
  <body>
    <h1 ng-style="{color: '#66c'}">{{ 'Famous Greetings' | uppercase }}</h1>
    {% for name, greeting in greetings %}
      <h3>{{ name }}</h3>{{ greeting|join('\n')|nl2br }}</p>
    {% endfor %}
  </body>
</html>

Wenn wir nun wie hier die AngularJS-Syntax mit den geschweiften Klammern benutzen wollen, kolliediert das mit der Twig-Syntax und die Seite erzeugt einen Fehler. Wir müssen AngularJS umkonfigurieren, so dass dort nicht die beiden geschweiften Klammern als Markierung benutzt wird, sondern z.B. zwei normale, runde Klammern. Dazu passen wir die Javascript-Datei app.js wie folgt an:

app.js
var app = angular.module('demo', []);

app.config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('((');
    $interpolateProvider.endSymbol('))');
  });

Nun können wir die runden Klammern für AngularJS Auszeichnungen nutzen.

demo.html.twig
<!DOCTYPE html>
<html ng-app="demo">
  <head>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script type="text/javascript" src="app.js"></script>
  </head>
  <body>
    <h1 ng-style="{color: '#66c'}">(( 'Famous Greetings' | uppercase ))</h1> <!-- angular -->
    {% for name, greeting in greetings %} <!-- twig -->
      <h3>{{ name }}</h3>{{ greeting|join('\n')|nl2br }}</p> <!-- twig -->
    {% endfor %}
  </body>
</html>

Und sowohl die Twig- als auch die Angular-Auszeichnungen werden fehlerfrei ausgegeben:


(( 'Famous Greetings' | uppercase ))

Robin Williams

Nano Nano!
Gooood Morning!

Lionel Richie

Hello?!

Leonard Nimoy

LLAP!

Bruce Willis

Yippie-Ka-Yeah!


Resümee

In Twig kann noch die Interpretation der Anweisungen über {% verbatim %} ... {% endverbatim %} abgeschaltet werden. In dem entsprechenden Block enthaltene Anweisungen mit geschweiften Klammern würden dann von AngularJS benutzt werden können. Das würde aber zu einem sehr überladenen und undurchsichtigen Code führen. Die Konfiguration des AngularJS interpolateProviders ist auf jeden Fall die bessere Alternative.