View – die “Präsentationsschicht”

Der dritte und letzte Teil zum Thema “Wie stellen wir den ganzen Datenwust denn nun eigentlich dar?” ist der “View” – auf Deutsch auch “Präsentationsschicht” genannt. Man könnte auch “User Interface” sagen, aber da vermischen sich ganz schnell Elemente der reinen Darstellung mit Elementen der Geschäftslogik. Insofern nehmen wir es mal ganz wortwörtlich und definieren: Unser “View” – das ist das Gerüst der Webseite, in die unsere Daten quasi “hineinprojeziert” werden. Und das will ich heute einmal zerpflücken.

Wie gehabt greife ich mir stellvertretend einen View aus dem aktuellen Stand der Winzen-Webapp (winzen.danielstange.de), und zwar den ersten View, der genutzt wird, um eine Liste aller Personen darzustellen. (Sourcecode des Views / Sourcecode des Projekts):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title><?php echo $title; ?></title>

    <!-- Bootstrap -->
    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <!-- Optional theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>
<style>
    .starter-template {
        padding-top: 50px;
    }
</style>
<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Die Datenbank zum Winzen-Gruppen-Projekt</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
            <ul class="nav navbar-nav">
                <li class="active"><a href="/">Home</a></li>
                <li><a href="http://winzen.hypotheses.org/">Winzen-Gruppe-Blog von Christian Günther</a></li>
                <li><a href="http://blog.danielstange.de/">Blog von Daniel Stange</a></li>
                <li><a href="http://http://blog.danielstange.de/impressum/">Impressum</a></li>
            </ul>
        </div><!--/.nav-collapse -->
    </div>
</nav>

<div class="container">

    <div class="starter-template">
<h1><?php echo $title; ?></h1>
<table class="table table-striped">


<?php foreach ($person as $person_item): ?>
    <tr>
        <td>
            <?php echo trim($person_item['FirstName']." <strong>".$person_item['LastName']."</strong>");
            if($person_item['LastName'] === 'unbekannt') {
                echo " <i>(".$person_item['NameHint'].")</i>";
            }
            ?>
        </td>
        <td>
            <a href="<?php echo site_url('person/'.$person_item['PersonId']); ?>">Details</a>
        </td>
    </tr>
<?php endforeach; ?>
</table>
    </div>

</div><!-- /.container -->
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
</body>
</html>

Was man hier sieht, ist eigentlich relativ nackt ein HTML-Template (eine Seitenvorlage), und zwar mehr oder weniger direkt aus dem relativ bekannten und beliebten Framework Bootstrap gebaut. Es ist schon lange nicht mehr so, das mal einfach mal ein bisschen HTML schreibt und es ein bisschen hübsch macht. Es ist vor allem die erschütternde Vielfalt von “Viewports” (Kreuzprodukt aus Geräten und Browsern…), die verhindert, dass konzises Erscheinungsbild und “bei Null anfangen” rational und ökonomisch wären.

Bootstrap nutzt HTML5 als Sprachstandard für die Seitenbeschreibungssprache. Gestaltet wird die Optik mit CSS3-Stylesheets. Ein bisschen JavaScript ist hier auch eingebunden, aber das tut erstmal nichts zur Sache.

Mitten im HTML finden sich ein paar verteilte PHP-Tags – ich habe sie fett markiert, damit man sie überhaupt bemerkt. Da man die im Endprodukt nicht mehr sieht, muss schon einmal irgendwas gemacht werden: Das PHP wird ausgeführt und das Ergebnis der Ausführung an die Stelle geschrieben, wo der PHP-Code stand. Daher kommt der (längst nicht mehr gebräuchliche) ausführliche Name “PHP Hypertext Preprocessor”. Zuerst (pre) wird der PHP-Code ausgewertet (processed), danach wird das HTML (hypertext) gerendert und angezeigt.

Wenn ihr mal die Hervorhebungen durchgeht: Das ist eigentlich alles ganz elementares PHP:

  • echo-Befehle: geben die nachfolgende Zeichenkette oder Variable aus
  • eine for-each-Schleife in alternativer Syntax (foreach / endforeach), geht durch eine Liste durch und macht mit jedem Element etwas, nämlich:
  • mehr echo-Befehle
  • eine Verkettung von Befehlen, nämlich echo und trim:
    • echo: zeigt an: trim entfernt Leerzeichen am Anfang und Ende: Der Punkt . verkettet Text und die Anführungszeichen ” ” fassen Text ein.
    • Das ist sogenanntes chaining – man klemmt einfach alles aneinander, so dass die Ausgabe des einen in die nächste Funktion reinlaufen. Es ist ein bisschen wie eine Kanalisation: Man spült einmal, und es läuft alles durch bis in die Kläranlage. Solche Chains liest man von hinten nach vorne, also:
      • Verkettung:
        $person_item['FirstName']." <strong>".$person_item['LastName']."</strong>"

        Das Vorname-Feld des Datensatzes und die Zeichenkette ” <strong>” und das Nachname-Feld des Datensatzes und die Zeichenkette “</strong>”. Macht: Vorname <strong>Nachname</strong>. Und strong ist Markup für Fettdruck.

      • Trunkieren:
        Es ist guter Stil, keinen Bullshit anzusammeln. Kommt aber vor, also räumen wir auf: Wenn kein Vorname im Datensatz steht, wird ein Leerzeichen vor <strong> geschrieben. Das machen wir jetzt wieder weg, indem wir den PHP-Befehl trim(Zeichenkette) benutzen.
      • Und das echo gibt das Ergebnis des Ganzen aus.
    • es schließt sich an: eine if-Klausel. Das ist eine Fallprüfung, die prüft, ob eine Bedingung wahr ist.
      if (Bedingung) {Auszuführender Code, falls Bedingung wahr}
    • Optional: else if (2. Bedingung) {2. Code-Block}
    • Optional: else { 3. Code-Block}

      Innerhalb einer if-Klausel wird nur ein Block von Code ausgeführt, nämlich der erste, für den eine Fallprüfung zutrifft. Nach der Ausführung des Blocks springt das Programm aus der Klausel, egal, ob nachfolgende else if-  oder else-Bedingungen ebenfalls wahr würden.

    • In vorliegenden Fall wird in kursiv ein kurzer Namenshinweis angehängt, der eine Person, deren Name unbekannt ist, ein wenig einordnet. Es wird geprüft, ob der Nachname exakt “unbekannt” ist und nur ein einziger Code-Block bereitgehalten. Ist der Nachname nicht exakt “unbekannt”, wird kein weiterer Code ausgeführt.

Damit ist im Grunde schon alles gesagt: Unser View ist wie eine Schablone. Hier und da sind “Löcher”, die mit PHP-Code gefüllt werden und in die – quasi durch das PHP hindurch – Text in die Seite geschrieben werden kann. Es passiert quasi keine Logik – alle Aufrufe von PHP-Funktionen und Kontrollstrukturen erfolgen rein im Sinne der Ausgabe von sauberen Werten. Und das ist genau so, wie es sein soll: Der View macht nichts außer eine Ansicht zusammenstellen. Jetzt kommen sicherlich die Pöbler und sagen: “Moment, Du lädst im View jQuery, Du willst doch bestimmt im…”. Ja, schweigen bitte: Sieht hier jemand ein JavaScript-Controller, der im View geschrieben ist? Der Kern ist: Es geht nicht darum, was wo eingebunden und zur Ausführung gebracht wird. Es geht darum, ein Programm so zu zerteilen, dass man alles so lange zerlegt, bis nur noch kleine, wiederverwendbare Schnipsel bleiben und “glue code”, der aus den Schnipseln etwas baut. Und jedes Stück Schnipsel gehört in einen Bereich und hat eine Aufgabe: Er strukturiert Daten und Datenzugriff (Model), er verwaltet und koordiniert die Logik (Controller) oder zeigt etwas an und nimmt Eingaben entgeben (View).

Für Fortgeschrittene: Einigen dürfte auffallen, dass wir die Werte im Controller in $data[‘title’] schreiben und im View mit $title darauf zugreifen.

$data['person'] = $this->person_model->get_person();
$data['title'] = 'Winzen Datenbank';
$this->load->view('person/index', $data);
<?php echo $title; ?>

Das ist leider nicht ganz leicht zu erklären: $data ist eine Liste mit namentlich benannten Elementen – ein assoziatives Array . Frage ich $data nach einem Wert für “title”, erhalte ich “Winzen Datenbank” als Rückgabe.

Wenn man das ganz streng nimmt, wird im Controller gar nicht der View selbst geladen, sondern ein Objekt $this angesprochen. $this ist entgegen der Schreibweise keine gewöhnlich Variable, sondern verweist auf eine Instanz eines Objekts (die laufende Instanz des Controllers). Und der Controller erbt im Endeffekt fast alles, was er kann, von seinen “Eltern”, und das passiert in der Zeile

class Person extends CI_Controller

Die Klasse CI_Controller vererbt dem Controller ein Objekt load, das wiederum hat eine Methode view und in View kann man einen Dateipfad geben und eine Sammlung aus Werten. Die Methode db->view(View-Definition, Werte) zerlegt (deserialisiert) die Liste von Werten in einzelne Variablen, die so heißen wie die Schlüssel in der Liste. Und damit wird dann die View-Definition interpretiert und eben nicht isoliert geladen. Deswegen geht das hier gut, obwohl $data[‘title’] und $title nicht synonym sind.

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.