Programmieren > Sprachen > PHP > Zend 2

Datenbank-Anbindung mit dem Zend-Framework

Auf dieser Seite soll nun erklärt werden, wie man mit dem Zend-Framework Verbindung zu einer Datenbank aufnimmt. Mit dem Thema Datenbank kann man ganze Universitäts-Studiengänge füllen. Deshalb sei hier auch noch mal betont, dass dies nur einer von vielen möglichen Wegen ist. Ausgangspunkt für diese Erklärungen ist die Minimal-Applikation wie sie auf der Seite Zend Framework 2: Installation und erste Einblicke vorgestellt wurde.

Die Datenbank-Verbindung

Zuerst muss die Möglichkeit einer Datenbank-Verbindung hergestellt werden. Zu diesem Zweck wird hier angenommen, dass Sie lokal eine MySQL-Datenbank namens zf2tutorial mit einer befüllten Tabelle namens user haben. Die Tabelle und ihre Befüllung können sie mit folgendem Skript erstellen.

DROP TABLE IF EXISTS `user` ;

CREATE  TABLE `user` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `username` VARCHAR(255) NOT NULL,
  `password` VARCHAR(255) NOT NULL,
  `firstname` VARCHAR(255) NOT NULL ,
  `lastname` VARCHAR(255) NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;

INSERT INTO `user` VALUES (1,'max','geheim','Max','Mustermann'),(2,'ilse','geheim','Ilse','Schmidt');

Ist diese Datenbank vorhanden, muss der Zend2-Applikation erklärt werden, wie sie zu dieser Datenbank Kontakt aufnehmen kann. Dies geschieht in der Datei config/autoload/global.php. Diese sieht dann folgendermaßen aus.

<?php
return array(
      'db' => array(
            'driver'         => 'Pdo',
            'dsn'            => 'mysql:dbname=zf2tutorial;host=localhost',
            'username' => 'Ihr_Benutzername',
            'password' => 'Ihr_Passwort',
      ),
      'service_manager' => array(
            'factories' => array(
                  'Zend\Db\Adapter\Adapter'
                  => 'Zend\Db\Adapter\AdapterServiceFactory',
            ),
      ),
);

In dieser Konfiguration wird dem ServiceManager erklärt, dass er zum Bau eines Datenbank-Adapters die AdapterServiceFactory benutzen muss. Diese Factory greift dann auf die Datenbank-Parameter zurück, die in der Konfiguration db hinterlegt sind.

Der Tabellenzugriff

Auf die Tabelle wird mit einer eigenen Klasse zugegriffen. Es sollte für jede Tabelle eine Klasse angelegt werden. Für unser Beispiel sieht diese Klasse folgendermaßen aus.

<?php 

namespace Application\Model;

use Zend\Db\TableGateway\AbstractTableGateway;

class UserTable extends AbstractTableGateway
{
    private $adapater;
    protected $table;

    public function __construct($adapter) {
        $this->adapter = $adapter;
        $this->table = 'user';
    }
   
    public function getContent() {
       $stmt = $this->adapter->query('SELECT * FROM user',array());
      
       return $stmt->toArray();
    }
}

Dieser Inhalt wird in der Datei module/Application/src/Application/Model/UserTable.php abgelegt. Eine Klasse zu bauen sollte bei Zend immer der ServiceManager übernehmen. Deshalb wird für das Modul Application eine ServiceManager-Konfiguration für die User-Tabelle hinzugefügt. Die Datei module/Application/config/module.config.php bekommt folgende Erweiterung

<?php

use Application\Controller\IndexController;
use Application\Model\UserTable;

return array(
    'router' => array(   ...  ),
    'controllers' => array(  ...  ),
    'service_manager' => array(
      'factories' => array(
            'Application\Model\UserTable' => function($sm) {
               $adapter = $sm->get('Zend\Db\Adapter\Adapter');
               $userTable = new UserTable($adapter);
               return $userTable;         
            }
      ),
   ),
    'view_manager' => array( ... ),
);

Hier wird dem ServiceManager eine Factory zum Bau einer User-Tabelle in Form einer anonymen Funktion übergeben. Dieser anonymen Funktion wird der ServiceManager als Parameter übergeben. In der ersten Zeile wird ein Datenbank-Adapter erzeugt. Hierzu wird der ServiceManager angewiesen, die in der Datei global.php hinterlegte Definition für den Bau eines Adapters zu benutzen. In der 2. Zeile wird der Adapter beim Bau einer User-Tabelle benutzt und in der dritten Zeile wird dieses Tabellen-Objekt zurückgegeben.

Die Datenbankverbindung nutzen

Um diese Datenbankverbindung zu nutzen, kann sie z.B. in einen Controller eingebaut werden. Hierzu habe ich die Controller-Factory in der Datei module/Application/config/module.config.php verändert zu.

...
    'controllers' => array(
       'factories' => array(
            'Application\Controller\Index' => function ($serviceLocator) {
               $ctr = new IndexController();
               $ctr->setUserTable($serviceLocator->getServiceLocator()->get('Application\Model\UserTable'));
               return $ctr;
            }
       )
    ),
...

Einer Controller-Factory wird ein Servicelocator übergeben, der die Konfiguration des ServiceManager für die User-Tabelle abrufen kann, und diese einer neuen Setter-Funktion des Controllers übergibt. Nun kann im Index-Controller auf die User-Tabelle zugegriffen werden. (Datei: module/Application/src/Application/Controller/IndexController.php)

<?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
   private $userTable;
   
   public function setUserTable($userTable) {
      $this->userTable = $userTable;
   }
   
   public function indexAction() {
      return array(
            'title' => 'Zend2 Skeleton Application',
            'message' => 'This is a very minimalistic Zend2 Application',
            'userTable' => $this->userTable->getContent(),
      );
   }
}

In diesem Beispiel sieht man, wie die Setter-Funktion eine interne Variable befüllt und die Ausgabe der Funktion getContent eine Variable befüllt, auf die im Seiten-Template zugegriffen werden kann. Im Seiten-Template wird aus dieser Variable dann eine Tabelle gebaut. (Datei: module/Application/view/application/index/index.php)

<h1><?php echo $this->title ?></h1>

<p><?php echo $this->message ?></p>

<h2>Benutzer-Tabelle</h2>

<table>
  <tr>
    <th>ID</th>
    <th>Vorname</th>
    <th>Nachname</th>
  </tr>
  <?php foreach ($this->userTable as $line) { ?>
  <tr>
    <td><?php echo $line['id'] ?></td>
    <td><?php echo $line['firstname'] ?></td>
    <td><?php echo $line['lastname'] ?></td>
  </tr>
  <?php } ?>
</table>