Während den letzten Wochen habe ich mich hier bei Braintower mit dem PHP Framework Symfony und dessen minimalistischem Ableger Silex auseinandergesetzt.
Für ein Kundenprojekt war es notwendig eine Applikation zu entwickeln, die sowohl ein Web-Frontend als auch eine Konsolenapplikation mit gleichen Funktionen bietet.

Silex wurde das Framework der Wahl, weil in unserem Unternehmen die Skript Sprache PHP oft zum Einsatz kommt und wir mit dem Umgang in Symfony bereits Erfahrungen gesammelt haben.
Das Leichtgewicht Framework Silex ermöglicht es im Handumdrehen eine funktionsfähige Applikation zu erstellen ohne viel Code schreiben zu müssen.
Mittels Composer und einer kleinen Anpassung am Webserver (hier Apache) war die Anwendung über das Web erreichbar.

{
   "require":{
      "kint-php/kint": "0.9",
      "silex/silex": "1.3.*@dev",
      "twig/twig": "1.17.*@dev",
      "neutron/silex-imagine-provider": "0.1.*",
      "imagine/imagine": "0.7.*",
      "symfony/console": "^2.7",
      "doctrine/dbal": "~2.2",
      "doctrine/migrations": "^1.1"     
   }
}

Das Apache Modul mod_rewrite muss aktiviert sein und die RewriteRule leitet auf die index.php zurück.

<IfModule mod_rewrite.c>
    Options -MultiViews

    RewriteEngine On
    #RewriteBase /path/to/app
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [QSA,L]
</IfModule>

Die index.php ist relativ simpel gestaltet, sie definiert Controller die je nach Route andere Aufgaben erfüllen.

Den Routen können Variablen übergeben werden. Sie können sowohl auf GET als auch auf POST reagieren und unterschiedliche Arbeiten durchführen. Ich möchte hier allerdings nicht zu sehr ins Detail gehen wie die Routen funktionieren. Ich möchte einen Allgemeinen Eindruck vermitteln, wie mittels wenigen Schritten eine Web-Applikation entstehen kann.

require_once __DIR__.'/../vendor/autoload.php';
$app = new Silex\Application();
$app->get('/hello/{name}', function($name) use($app) {
    return 'Hello '.$app->escape($name);
});
$app->run();

Um Templates (HTML-Bausteine) verwenden zu können habe ich Twig eingesetzt.

$app->get('/', function () use ($app) {
    return $app['twig']->render('layout.html.twig');
})->bind('home');

Es ermöglicht Logik in die HTML Dateien einfließen zu lassen und öfter eingesetzte DOM Elemente in sogenannten Makros zu speichern. Zudem kann man die einzelnen html.twig Templates untereinander verschachteln. Der Block „content“ kann von einem anderen Twig Template überschrieben werden.

<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
{% block content %}
    <!-- place to include content -->
{% endblock %}    
</body>
</html>

Wenn man sich die Aufbereitung von Daten, die an das Web-Frontend gesendet werden, sparen möchte kann man mittels Twig die Logik zum Ausgeben von Arrays oder das Abfragen von Werten abbilden. Mir persönlich hat es sehr gut gefallen dort Logiken für Schleifen zu deponieren. Aber das muss jeder für sich selbst entscheiden.

<h1>Members</h1>
<ul>
    {% for user in users %}
        <li>{{ user.username|e }}</li>
    {% endfor %}
</ul>

Interessant war für mich die Möglichkeit Klassen zu erzeugen, die sowohl für das Web-Frontend, als auch die Konsole-Applikation genutzt werden können. Zum Beispiel finden alle Datenbank Verbindungen serverseitig statt. Das aus dem Query resultierende Ergebnis wird lediglich an das Web-Frontend übergeben.

Die Datenbankverbindung wird mittels Doctrine realisiert, welche in der Applikation selbst registriert werden muss. Nachdem der DoctrineServiceProvider() initialisiert ist, kann durch Aufruf des Applikation-Parameter ‚db‘ ein Query übergeben werden. Als Datenbanktreiber habe ich PDO eingesetzt.

$this->app->register(new DoctrineServiceProvider(), array(
    'db.options' => array(
        'driver' => 'pdo_mysql',
        'host' => DB_HOST,
        'dbname' => DB_DATABASE,
        'user' => DB_USER,
        'password' => DB_PASSWORD,
    ),
));
$sql = "SELECT something FROM somewhere";
$stmt = $this->app['db']->prepare($sql);
try {
    $stmt->execute();
    $dbOutput = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
    return array();
}

Die Konsole-Applikation console.php wurde mit der Symfony Komponente Console implementiert.

use Symfony\Component\Console\Application;
$cli = new Application();

Die Konsole-Applikation erwartet für jeden Command eine eigene Klasse. Diese kann man in einer separaten Datei anlegen oder direkt in der console.php erstellen.

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class SomeConsoleCommand extends Command
{
    protected function configure()
    {
        // ...
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // ...
    }
}

Über die Funktion configure() legt man den Aufruf des Kommandos fest, welche Werte übergeben werden müssen und zusätzlich einem Hilfetext per execute() wird das Kommando ausgeführt.

Fazit:

Nachdem das Projekt abgeschlossen war, habe ich mich dazu entschieden auch ein kleines privates Projekt in Silex zu realisieren. Ich bin immer noch angetan von der Leichtigkeit dieses Frameworks. Mit wenigen Mitteln hat man hier eine Applikation geschaffen, die auch mit großen Symfony Projekten mithalten kann.

Nicolas Kortgen

Nicolas Kortgen

Application Developer

Nick ist in Frankreich aufgewachsen, bevor es ihn nach Deutschland verschlagen hat. Er kann nicht nur die Bälle beim Jonglieren in der Luft halten, sondern auch die unterschiedlichsten Projekte am Laufen. Löst den Rubik Würfel in unter einer Minute. Startete bei Braintower als Praktikant, wechselte dann zum Azubi und steckt auch noch heute alle mit seiner guten Laune an.

Gefällt dir der Artikel? Bitte teile ihn!
Share on Facebook
Facebook
0Share on LinkedIn
Linkedin
Email this to someone
email
Tweet about this on Twitter
Twitter