Zend Tutorial – 03 – Weitere Actions

1. In diesem Teil des Tutorials wagen wir uns an weitere Actions und somit auch an eine Erweiterung unserer Anwendung. Ziel ist es, unseren IndexController um die Funktionen des Anlegens, Bearbeitens und Löschens zu erweitern. Wir werden auch mit den Zend_Forms in Berührung kommen, die uns die Arbeit mit Formularen vereinfachen sollen.

2. Wir legen uns unter dem Ordner application/modules/bibo einen Unterordner forms an. In diesen Ordner werden ab sofort alle Formulare abgelegt. Entsprechend der Zend Namenskonvention sind die Klassennamen der Formulare für das Modul Bibo mit Bibo_Form_FormularnameForm zu benennen. Für das Formular BuchAnlegenForm ergibt sich also Bibo_Form_BuchAnlegenForm. Unsere Datei BuchAnlegenForm.php im Ordner application/modules/bibo/forms wird mit folgendem Inhalt befüllt:

class Bibo_Form_BuchAnlegenForm extends Zend_Form
{
    public function __construct($options = null)
    {
       parent::__construct($options);
       
       $name = new Zend_Form_Element_Text('name');
       $name->setLabel('Name des Buches')
             ->setRequired(true)
             ->addFilter('StripTags')
             ->addFilter('StringTrim')
             ->addValidator('NotEmpty')
             ->addErrorMessage('Bitte einen Namen des Buches eintragen')
             ->setAttrib('size',90);
      
       $author = new Zend_Form_Element_Text('author');
       $author->setLabel('Author des Buches')
             ->setRequired(true)
             ->addFilter('StripTags')
             ->addFilter('StringTrim')
             ->addValidator('NotEmpty')
             ->addErrorMessage('Bitte einen Author des Buches eintragen')
             ->setAttrib('size',90);

       $beschreibung = new Zend_Form_Element_Textarea('beschreibung');
       $beschreibung->setLabel('Kurzbeschreibung des Buches')
             ->setRequired(true)
             ->addFilter('StripTags')
             ->addFilter('StringTrim')
             ->addValidator('NotEmpty')
             ->addErrorMessage('Bitte eine Kurzbeschreibung des Buches eintragen')
             ->setAttribs(array('rows' => 10, 'cols' => 70));
       
       $anzahl = new Zend_Form_Element_Text('anzahl');
       $anzahl->setLabel('Anzahl der vorhandenen Exemplare')
             ->setRequired(true)
             ->addValidator(new Zend_Validate_Digits())
             ->addValidator(new Zend_Validate_Between(array('min' => 1, 'max' => 20)))
             ->addErrorMessage('Bitte eine Zahl zwischen 1 und 20 angeben');
             
       $submit = new Zend_Form_Element_Submit('submit');
       $submit->setLabel('Buch anlegen');
       
       $this->addElements(array($name, $author, $beschreibung, $anzahl, $submit));
    }
}

Wird eine Instanz der Klasse erstellt, so wird der Konstruktor aufgerufen und generiert uns ein neues Formular. Wir erzeugen über new Zend_Form_Element_### verschiedene Formularelemente. Weitere Möglichkeiten sind der Zend Dokumentation zu entnehmen. Danach werden verschiedene Eigenschaften der Formularelemente gesetzt. Beispielsweise, ob das Element ausgefüllt sein muss(setRequired) oder es werden andere Validatoren hinzugefügt (addValidator). Am Ende der Formulargenerierung dürfen wir nicht vergessen die Objekte dem Formular zu zu weisen. Dies geschieht über $this->addElements(array(…)).

Nun wird unser IndexController.php im Ordner application/modules/bibo/controllers um eine buchanlegenAction() erweitert. Fügt dazu folgende Funktion unter die indexAction() als zweite Funktion hinzu:

  /**
     * Buchanlegen Action
     * Erzeugung eines Buches incl. seiner Exemplare
     */
    
	public function buchanlegenAction()
    {
        $form = new Bibo_Form_BuchAnlegenForm();
        $this->view->form = $form;
        
        //Prüfen ob Request abgeschickt wurde
        if ($this->_request->isPost())
        {
            $formData = $this->_request->getPost();
            //Prüfen der Validität der Formulardaten
            if ($form->isValid($formData))
            {
        		$buecher = new Bibo_Model_BuecherMapper();
        		$buch = new Bibo_Model_Buecher();
        		$exemplare = new Bibo_Model_ExemplareMapper();
        		
        		//Setzen der Bucheigenschaften
        		$buch->setName($form->getValue('name'));
        		$buch->setAuthor($form->getValue('author'));
        		$buch->setBeschreibung($form->getValue('beschreibung'));
        		//Schreiben der Buchdaten in die Datenbank
        		$buchId = $buecher->save($buch);
        		//Erzeugung angegebenen Exemplaranzahl für dieses Buch
        		$anzahl = $form->getValue('anzahl');
        		for($count = 0; $count < $anzahl; $count++)
                {
                    $exemp = new Bibo_Model_Exemplare();
                    $exemp->setexem_buch_id($buchId);
        		
                    $exemp->setAusgeliehen('FALSE');
        		    $exemp->setKunde($form->getValue(''));
        		    $exemplare->save($exemp);
                    
                }
                
                //Redirect zur Buchübersicht
                $url = '/';
        		$this->_redirect($url);
            }
            else
            {
                //Formular füllen, falls abgeschicktes Formular nicht valide
                $form->populate($formData);
            }
        }
    }

Passend zu dem Controller buchanlegenAction() müssen wir jetzt die View erstellen. Im Ordner application/modules/bibo/views/scripts/index/ erzeugen wir die Datei buchanlegen.phtml und befüllen Sie mit folgendem Inhalt:

<?php echo $this->form;

3. Rufen wir jetzt die URL http://192.168.199.132:8108/index/buchanlegen auf, so bekommen wir ein Formular generiert. Ist das Formular valide, wird es abgeschickt und erzeugt uns ein neues Buch samt der angegebenen Exemplare.

4. In der IndexController.php im Ordner application/modules/bibo/controllers fügen wir die drei Methoden buchbearbeitenAction(), buchbearbeitenfailAction() und buchloeschenAction() hinzu

    /**
     * Buchbearbeiten Action
     * Bearbeiten eines Buches incl. der Exemplaranzahl, falls mögl.
     */
    public function buchbearbeitenAction()
    {
        //Holen der Buch-Id
        $id = (int)$this->_request->getParam('id');
		//Anlegen des Formulars
        $form = new Bibo_Form_BuchBearbeitenForm();
        $this->view->form = $form;
        
        //Prüfen ob Formular zum Bearbeiten abgeschickt wurde
        if ($this->_request->isPost())
        {
            $formData = $this->_request->getPost();
            //Prüfen ob Formular valide ist
            if ($form->isValid($formData))
            {
                $buecher = new Bibo_Model_BuecherMapper();
            	$buch = new Bibo_Model_Buecher();
            	$exemplare = new Bibo_Model_ExemplareMapper();
            	
            	//Setzen der Eigenschaften des Buches
            	$buch->setId($id);
            	$buch->setName($form->getValue('name'));
            	$buch->setAuthor($form->getValue('author'));
            	$buch->setBeschreibung($form->getValue('beschreibung'));
            	//Schreiben der Änderungen in die DB
            	$buchId = $buecher->save($buch);
                
            	//neue Anzahl der Exemplare aus Formular ermitteln
            	$neueanzahl = $form->getValue('anzahl');
            	$exemplarmapper = new Bibo_Model_ExemplareMapper();
            	//bisherige Exemplaranzahl aus DB ermitteln
                $alteanzahl = $exemplarmapper->getExemplarAnzahlByBuchId($id);
                
                //Wenn neue Anzahl größer als alte Anzahl --> neue Exemplare hinzufügen
            	if($neueanzahl>$alteanzahl)
            	{
            	    $differenz = $neueanzahl - $alteanzahl;
                	for($count = 0; $count < $differenz; $count++)
                    {
                        $exemp = new Bibo_Model_Exemplare();
                        $exemp->setexem_buch_id($id);
                        $exemp->setAusgeliehen('FALSE');
            		    $exemp->setKunde($form->getValue(''));
            		    $exemplarmapper->save($exemp);
                        
                    }
            	}
            	
            	//Wenn neue Anzahl kleine als alte Anzahl
            	elseif($neueanzahl<$alteanzahl)
            	{
            	    $freieanzahl =  $exemplarmapper->getFreieExemplarAnzahlByBuchId($id);
            	    //Prüfen ob freie Anzahl an Exemplaren größer gleich Differenz zwischen alter 
            	    //und neuer Exemplaranzahl
            	    if($freieanzahl>=($alteanzahl-$neueanzahl))
            	    {
            	        $exemp = new Bibo_Model_Exemplare();
            	        //betreffende Exemplaranzahl löschen, 
            	        //vorher Prüfung ob Ausleihstatus auf FALSE steht
            	        $where = array( 'exem_buch_id = ?'=>$id,
				    					'ausgeliehen = ?'=>'FALSE');
				    
				        $exemp =  $exemplarmapper->getDbTable()->fetchAll($where,'',($alteanzahl-$neueanzahl));
				        
				        foreach($exemp as $ex)
				        {
				            $wherealternativ = array( 'id = ?'=>$ex->id);
				            $exemplarmapper->getDbTable()->delete($wherealternativ);
				        }
				        
				        
            	    }
            	    //Falls die zu löschende Anzahl an Exemplaren aktuell im Umlauf ist --> Fehlerausgabe
            	    else
            	    {
            	        $url = 'index/buchbearbeitenfail/';
            	        $this->_redirect($url);
            	    }
            	}
            	//Redirect zur Bücherübersicht                
                $url = '/';
            	$this->_redirect($url);
            }
            //Falls Formulardaten nicht valide --> Formular mit eingegebenen Daten füllen
            else
            {
                $form->populate($formData);
            }
        }
        //Wenn Seite zum Bearbeiten erstmalig aufgerufen wird, mit entsprechenden 
        //Eigenschaften des Buches befüllen
        else 
        {
                $id = (int)$this->_request->getParam('id', 0);
                if ($id> 0)
                {
                    $buecherMapper = new Bibo_Model_BuecherMapper();
                    $exemplareMapper = new Bibo_Model_ExemplareMapper();
                    $buch = new Bibo_Model_Buecher();
                    $buch = $buecherMapper->getBuchByBuchId($id);
                    $anzahlexemplare = $exemplareMapper->getExemplarAnzahlByBuchId($id);
                    
                    $array = array();
                    $array['name'] = $buch[0]->getName();
                    $array['author'] = $buch[0]->getAuthor();
                    $array['beschreibung'] = $buch[0]->getBeschreibung();
                    $array['anzahl'] = $anzahlexemplare;
                    
                    $form->populate($array);   
                }        
        }    
    }
    
    /**
     * Buchbearbeiten Fail Action
     * Bearbeiten des Buches schlägt fehl
     */
    public function buchbearbeitenfailAction()
    {
	
    }
	
	/**
     * Buchlöschen Action
     * Löschen eines Buches
     */
    public function buchloeschenAction()
    {
        $id = (int)$this->_request->getParam('id', 0);
                if ($id> 0)
                {
                    $exemplarmapper = new Bibo_Model_ExemplareMapper();
                    $buchmapper = new Bibo_Model_BuecherMapper();
                    $freieExemplare = $exemplarmapper->getFreieExemplarAnzahlByBuchId($id);
                    $verfExemplare = $exemplarmapper->getExemplarAnzahlByBuchId($id);
                    if($verfExemplare == $freieExemplare)
                    {
                        $wheredelete = array( 'exem_buch_id = ?'=>$id);
				        $exemplarmapper->getDbTable()->delete($wheredelete);
				        $wheredeletebuch = array( 'id = ?'=>$id);
				        $buchmapper->getDbTable()->delete($wheredeletebuch);
				        
				        $url = '/';
            	
                        $this->_redirect($url);
                    }
                    else
            	    {
            	        $url = 'index/buchbearbeitenfail/';
            	        $this->_redirect($url);
            	    }
                }
    }

Im Ordner application/modules/bibo/forms legen wir die Datei BuchBearbeitenForm.php an und füllen sie mit folgendem Inhalt:

class Bibo_Form_BuchBearbeitenForm extends Zend_Form
{
    public function __construct($options = null)
    {
       parent::__construct($options);
       
       $name = new Zend_Form_Element_Text('name');
       $name->setLabel('Name des Buches')
             ->setRequired(true)
             ->addFilter('StripTags')
             ->addFilter('StringTrim')
             ->addValidator('NotEmpty')
             ->addErrorMessage('Bitte einen Namen des Buches eintragen')
             ->setAttrib('size',90);
      
       $author = new Zend_Form_Element_Text('author');
       $author->setLabel('Author des Buches')
             ->setRequired(true)
             ->addFilter('StripTags')
             ->addFilter('StringTrim')
             ->addValidator('NotEmpty')
             ->addErrorMessage('Bitte einen Author des Buches eintragen')
             ->setAttrib('size',90);

       $beschreibung = new Zend_Form_Element_Textarea('beschreibung');
       $beschreibung->setLabel('Kurzbeschreibung des Buches')
             ->setRequired(true)
             ->addFilter('StripTags')
             ->addFilter('StringTrim')
             ->addValidator('NotEmpty')
             ->addErrorMessage('Bitte eine Kurzbeschreibung des Buches eintragen')
             ->setAttribs(array('rows' => 10, 'cols' => 70));
       
       $anzahl = new Zend_Form_Element_Text('anzahl');
       $anzahl->setLabel('Anzahl der vorhandenen Exemplare')
             ->setRequired(true)
             ->addValidator(new Zend_Validate_Digits())
             ->addValidator(new Zend_Validate_Between(array('min' => '1', 'max' => '20')))
             ->addErrorMessage('Bitte eine Zahl zwischen 1 und 20 angeben');      
             
       $submit = new Zend_Form_Element_Submit('submit');
       $submit->setLabel('Buch bearbeiten');
       
       $this->addElements(array($name, $author, $beschreibung, $anzahl, $submit));
    }
}

Im View Ordner application/modules/bibo/views/scripts/index/ erzeugen wir die Dateien buchbearbeiten.phtml mit Inhalt

<?php echo $this->form

und buchbearbeitenfail.phtml mit dem Inhalt

<?php echo 'Löschen nicht möglich, da zuviele Exemplare ausgeliehen sind!'

.

In einem letzten Schritt aktualisieren wir unsere index.phtml im Ordner application/modules/bibo/views/scripts/index/

<h1>Hello Bibo-Modul</h1>
<div id="divtabelle">
	<table cellspacing=0 cellpadding=5 id="buchtabelle">
    	<thead>
        	<tr>
            	<th>Buchname</th>
                <th>Author</th>
                <th>Beschreibung</th>
                <th>Verfügbare Exemplare</th>
                <th>Aktionen</th>
            </tr>
        </thead>
        <tbody>
            <?php
            foreach ($this->entries as $entry)
            {?>
                <tr>
                    <td><?php echo $entry->name;?></td>
                    <td><?php echo $entry->author?></td>
                    <td><?php echo $entry->beschreibung?></td>
                    <td><?php 
                        $exemplare = new Bibo_Model_ExemplareMapper();
                        $freieExemplare = $exemplare->getFreieExemplarAnzahlByBuchId($entry->id);
                        $verfExemplare = $exemplare->getExemplarAnzahlByBuchId($entry->id);
                        echo $freieExemplare.' von '.$verfExemplare.' verfügbar';
                    ?>
                    
                    </td>
                    <td>
                        <a href="<?php echo $this->url(
                                                array(
                                                        'controller' => 'index',
                                                        'action'     => 'buchbearbeiten'
                                                      )).'/id/'.$this->escape($entry->id)?>" style="color: orange">Bearbeiten</a>
                            
                       
                        <a href="<?php echo $this->url(
                                                array(
                                                        'controller' => 'index',
                                                        'action'     => 'buchloeschen'
                                                      )).'/id/'.$this->escape($entry->id)?>" style="color: red;">Löschen</a></td>
                </tr>
                                
     <?php }?>
        </tbody>
     </table>
	 <div class="buchanlegen"><a href="<?php echo $this->url(            
                                                array(
                                                        'controller' => 'index',
                                                        'action'     => 'buchanlegen'
                                                      ),null,TRUE)?>">Neues Buch anlegen</a>
     </div>
</div>

Wie euch aufgefallen ist, haben wir für die buchloeschenAction() keine seperate View erstellt. Das ist dem Umstand geschuldet, das am Ende des Controllers ein Redirect auf eine andere View stattfindet.

5. Damit haben wir die Möglichkeit geschaffen, Bücher anzulegen, zu bearbeiten und zu löschen. Im nächsten Schritt werden wir die Anwendung so erweitern, dass ein Ausleihen von Exemplaren ermöglicht wird.

6. Zunächst erweitern wir unseren IndexController.php um drei Actions: ausleihenAction(), leihenAction() und zurueckAction()

	/**
     * Ausleihen Action
     * Laden der Ausleihübersicht mit Exemplaren
     */
    public function ausleihenAction()
    {
		$id = (int)$this->_request->getParam('id');
		$exemplare = new Bibo_Model_ExemplareMapper();
		$this->view->entries = $exemplare->getExemplareByBuecherId($id);
    }
    
    /**
     * Zurueck Action
     * Rückgabe von einzelnen Exemplaren eines Buches
     */
    public function zurueckAction()
    {
		$id = (int)$this->_request->getParam('id');
		$exemId = (int)$this->_request->getParam('exemId');
		$exemplare = new Bibo_Model_ExemplareMapper();
		$exemp = new Bibo_Model_Exemplare();
		
		//Setzen der Id des Buches
		$exemp->setid($id);
		//Setzen der Id des Exemplares
		$exemp->setexem_buch_id($exemId);
		//Ausleihstatus auf FALSE setzen
		$exemp->setAusgeliehen('FALSE');
		//Name des Ausleihenden entfernen
		$exemp->setKunde('');
		//Schreiben der Änderungen in die Datenbank
		$exemplare->save($exemp);
		//Redirect auf die Exemplaransicht des Buches
		$url = 'index/ausleihen/id/' . $exemId;
        $this->_redirect($url);
		
    }
    
    /**
     * Leihen Action
     * Ausleihen von einzelnen Exemplaren eines Buches
     */
    public function leihenAction()
    {
        $id = (int)$this->_request->getParam('id');
		$exemId = (int)$this->_request->getParam('exemId');
        $exemplare = new Bibo_Model_ExemplareMapper();
        $exemp = new Bibo_Model_Exemplare();
        $form = new Bibo_Form_LeihForm();
        $this->view->form = $form;
        
        //Prüfen ob Formular zum Leihen abgeschickt wurde
        if ($this->_request->isPost())
        {
            $formData = $this->_request->getPost();
            //Prüfen ob Formular valide ist
            if ($form->isValid($formData))
            {
                //Setzen der Id des Buches
                $exemp->setid($id);
                //Setzen der Id des Exemplars
                $exemp->setexem_buch_id($exemId);
                //Ausleihstatus auf TRUE setzen
                $exemp->setAusgeliehen('TRUE');
                //Setzen des Kundes
                $exemp->setKunde($form->getValue('kunde'));
				//Schreiben der Änderungen in die Datenbank
                $exemplare->save($exemp);
                $url = 'index/ausleihen/id/' . $exemId;
                //Redirect auf die Exemplaransicht des Buches
                $this->_redirect($url);
            }
        }
    }

Im Verzeichnis application/modules/bibo/views/scripts/index/ legen wir ein neues View-Script ausleihen.phtml an und schreiben folgenden Inhalt in die Datei:

Exemplaranzeige: <br />
<?php 
    $exemAnzahl = 0;
?>
<table>
        <tr>
            <th>Buch-ID</th>
            <th>Ausleihstatus</th>
            <th>Kunde</th>
            <th>Buch ausleihen</th>
        </tr>
    <?php foreach ($this->entries as $entry): ?>
        <tr>
            <td><?php echo $this->escape($entry->exem_buch_id) ?></td>
            <td><?php if($entry->ausgeliehen == 'TRUE')
                      {
                        echo('ausgeliehen');
                      }
                      else
                      {
                        echo('nicht ausgeliehen');
                      } ?></td>
            <td><?php echo $this->escape($entry->kunde) ?></td>
            
            <td><?php if($entry->ausgeliehen == 'TRUE')
                      {?>
                        <a href="<?php echo $this->url(
                                    array(
                                            'controller' => 'index',
                                            'action'     => 'zurueck'
                                          ),null,TRUE).'/id/'.$this->escape($entry->id).'/exemId/'.$this->escape($entry->exem_buch_id) ?>" style="color: orange">Zurückgeben</a>
                <?php
                      }
                      else
                      {
                        $exemAnzahl++;  ?>
                        <a href="<?php echo $this->url(
                                    array(
                                            'controller' => 'index',
                                            'action'     => 'leihen'
                                          ),null,TRUE).'/id/'.$this->escape($entry->id).'/exemId/'.$this->escape($entry->exem_buch_id) ?>" style="color: green">Ausleihen</a>
                <?php    
                      }        
            ?></td>
        </tr>
    <?php endforeach ?>    
</table>
<p>noch verfügbare Exemplare: <?php echo $exemAnzahl;?></p>

Im selben Verzeichnis legen wir die Datei leihen.phtml an und fügen folgenden Inhalt in diese ein:

<?php echo $this->form;

Jetzt benötigen wir lediglich noch ein Formular zum Eintragen des Ausleihenden. Dazu dient die Datei LeihForm.php im Verzeichnis application/modules/bibo/forms:

class Bibo_Form_LeihForm extends Zend_Form
{
    public function __construct($options = null)
    {
       parent::__construct($options);
       $kunde = new Zend_Form_Element_Text('kunde');
       $kunde->setLabel('Ausleihender')
             ->setRequired(true)
             ->addFilter('StripTags')
             ->addFilter('StringTrim')
             ->addValidator('NotEmpty')
             ->addErrorMessage('Bitte einen Ausleihenden eintragen');
      
       $submit = new Zend_Form_Element_Submit('submit');
       $submit->setLabel('Buch ausleihen');
       
       $this->addElements(array($kunde, $submit));
    }
}

Um das Ausleihen aufrufen zu können, müssen wir in der index.phtml im Verzeichnis application/modules/bibo/views/scripts/index/ vor dem Link zum Buch bearbeiten folgenden Code einfügen:

 
                        if($freieExemplare>0)
                        {?>
                            <a href="<?php echo $this->url(
                                                       array(
                                                               'controller' => 'index',
                                                               'action'     => 'ausleihen'
                                                           )).'/id/'.$this->escape($entry->id);?>" style="color: green">Ausleihen</a>
                  <?php }
                        else
                        {?>
                            <a href="<?php echo $this->url(
                                                       array(
                                                               'controller' => 'index',
                                                               'action'     => 'ausleihen'
                                                            )).'/id/'.$this->escape($entry->id)?>" style="color: grey">Buch vergriffen</a>
                <?php   } ?>

7. Damit haben wir eine simple Verwaltung von Büchern und deren Exemplaren erstellt.

Im nächsten Tutorial wird unsere Anwendung um ein Login erweitert.

Link: Weiter zu Teil 4 des Tutorials

Kommentar verfassen