S'initier au Zend Framework/Mini blog/Actions

Zend Framework
Programmation PHP / Zend Framework
Programmation PHP / Zend Framework
Sommaire
Modifier ce modèle


L'action lire (read) modifier

Cette action prend l'identifiant de l'objet comme paramètre. Ce paramètre est envoyé dans l'URL par la méthode Http Get. Cet identifiant sert ensuite à consulter l'objet par la méthode find(..) :

$objet= $this->objet->find( $id )->current();

L'objet est ensuite transformé en tableau pour être envoyé à la vue :

$this->view->objet= $objet->toArray();

Cela donne dans le contrôleur la nouvelle action :

	public function readAction()
	{
		$id= (int) $this->_getParam('id');
		$this->view->nouvelle= $this->_nouvelles->find( $id )->current();
	}


La vue sera une simple liste à puce, à insérer dans  :

application/default/views/scripts/index/read.phtml
<p>Nouvelle numero : <?php echo $this->nouvelle['id']; ?></p>
<ul><?php foreach ( $this->nouvelle as $cle => $valeur ) :	?> 
	<li><?php echo $cle . ' : ' . $valeur; ?></li>	 
<?php endforeach; ?>
</ul>


Cet action est accessible maintenant par l'URL :

http://www.monblog.zf/index/read/id/777

L'affichage ne produira qu'un NULL car nous n'avons pas encore enregistré de données. On peut tester en insérant des données directement en base comme ici :

INSERT INTO `nouvelle` (`id`, `heuredate`, `titre`, `corps`, `categorie_id`) VALUES
(777, '2008-05-29 18:25:56', 'La date fonctionne', 'La date est imposée\r\n', 1);

On peut aussi ajouter l'action create et sa vue.

L'action ajouter (create) modifier

Cette action ajoute un nouvel enregistrement en deux étapes : le formulaire vide est affiché, l'utilisateur saisie les données puis soumet le formulaire. Chaque élément possède un Validateur. Par exemple si l'utilisateur doit saisir un champ requis et qu'il soumet le formulaire sans avoir bien rempli ce champ, le formulaire est réaffiché pré-rempli avec les données précédemment saisies et un message d'erreur est affiché à côté du champ fautif.

	$titre= new Zend_Form_Element_Text ( 'titre' );
	$titre->setLabel ( 'titre' )->addValidator ( 'NotEmpty' )->setRequired ( true );

Le Framework propose ainsi un service pour examiner la conformité des données : caractères numériques, alpha-numériques, dates, adresse e-mail, type de fichier et avec la possibilité de personnaliser son propre validateur.

La première étape est la création du formulaire, en considérant qu'il s'agit d'un objet fortement lié au modèle on va créer le fichier dans le dossier des modèles. Une autre approche est de considérer ce formulaire comme un objet utilisateur et de créer le fichier dans library/My/Forms/. Dans application/default/models/NouvelleForm.php :

class NouvelleForm extends Zend_Form {
	
	public function init() {
		$this->setName ( 'Nouvelle' )->setMethod ( 'post' );
		$this->setAttrib ( 'enctype', 'multipart/form-data' );
		
		$id = new Zend_Form_Element_Hidden ( 'id' );
		$this->addElement ( $id );
		
		$heuredate = new Zend_Form_Element_Hidden ( 'heuredate' );
		$aujourdhui = new Zend_Date();
		$date_format = 'YYYY-MM-dd HH:mm:ss';
		$heuredate->setValue( $aujourdhui->toString($date_format) );
		$this->addElement( $heuredate );
		
		$titre = new Zend_Form_Element_Text ( 'titre' );
		$titre->setLabel ( 'titre' )->addValidator ( 'NotEmpty' );
		$titre->addFilter ( 'StripTags' )->addFilter ( 'StringTrim' );
		$this->addElement ( $titre );
		
		$corps = new Zend_Form_Element_Textarea ( 'corps' );
		$corps->setLabel ( 'corps' )->addValidator ( 'NotEmpty' );
		$corps->addFilter ( 'StripTags' )->addFilter ( 'StringTrim' );
		$this->addElement ( $corps );

		$tab= array( 	'1' => 'culture',
					'2' => 'insolite',
					'3' => 'sport' );
		$categorie_id = new Zend_Form_Element_Select('categorie_id');
         	$categorie_id->setMultiOptions( $tab );
		$this->addElement( $categorie_id );
			
		// le bouton envoi
		$submit = new Zend_Form_Element_Submit ( 'submit' );
		$submit->setAttrib ( 'id', 'submitbutton' );
		
		$this->addElement ( $submit );
	}
}

La deuxième étape est la logique de gestion du formulaire dans l'action create :

	public function createAction()
	{
		$form= new NouvelleForm();
		$this->view->form= $form;
		$this->view->placeholder('title')->set('Ajouter une nouvelle');
		
	    if ( $this->_request->isPost () )
	    {
	    	$formData= $this->_request->getPost();
	    	if ( $form->isValid( $formData ) )
	    	{				
				$form->populate ( $formData );
				$newRow= $this->_nouvelles->createRow( $formData );
				try {
						$newRow->save();					
					} catch (Exception $e) {
						Zend_Debug::dump($e, 'e');
					}
		        $this->_redirect ( '/index/index' );
		  	} else {
	    		$form->populate ( $formData );
	    	} //isValid()
		} //isPost()
	}

La vue associée dans application/default/views/scripts/index/create.phtml :

<?php echo $this->form; ?>

Maintenant on peut vérifier l'affichage de la nouvelle. Il faut noter auparavant l'id dans la base de donnée et ensuite appeler l'action read :

index/read/id/341

L'action lister tous les objets (index) modifier

Cette action liste tous les enregistrements d'un objets sous forme d'un tableau. Il y en a un par ligne. La logique dans l'action est beaucoup plus simple que celle dans 'create' par contre l'affichage des objets sera moins trivial.

    public function indexAction() 
    {
        $this->view->nouvelles= $this->_nouvelles->fetchAll();
        $this->view->placeholder('title')->set('Liste de toutes les nouvelles');
    }

fetchAll() retourne un objet Rowset et c'est affecté à la variable de vue $nouvelles.

Ainsi dans la vue Html, $nouvelles sera par exemple :

object(Zend_Db_Table_Rowset)#38 (10) {
  ["_data:protected"] => array(24) {
    [0] => array(5) {
      ["id"] => string(2) "13"
      ["heuredate"] => string(19) "2008-05-29 18:25:56"
      ["titre"] => string(18) "La date fonctionne"
      ["corps"] => string(25) "La date est imposée"
      ["id_categorie"] => string(2) "17"
    }
    [1] => array(5) {
      ["id"] => string(2) "14"
      ["heuredate"] => string(19) "2008-05-30 10:35:14"
      ["titre"] => string(32) "La première nouvelle fonctionne"
      ["corps"] => string(112) "Dans la doc."
      ["id_categorie"] => string(3) "156"
    }...

Il y a ici un objet Rowset contenant deux objets, que l'on affichera sous forme de lignes de tableau. Chaque colonne correspondant a un attribut. La vue associée sera donc un tableau dynamique car l'on ne connait pas à l'avance le nombre de colonnes.

<table>
<caption><?php echo $this->caption?></caption>
<thead>
		<tr><?php foreach ( $this->colonnes as $colonne ) : ?> 
			<th><?php echo $colonne?></th>	 
			<?php endforeach; ?>
		</tr>
</thead>
<tfoot>
		<tr><?php foreach ( $this->colonnes as $colonne ) :	?> 
			<th><?php echo $colonne?></th>	 
			<?php endforeach; ?>
		</tr>
</tfoot>
<tbody>
		<?php foreach ( $this->nouvelles as $nouvelle ) : ?>
		<tr><?php foreach ( $nouvelle->toArray () as $col ) : ?>
			<td><?php echo $col; ?></td>
			<?php endforeach; ?>
		</tr>
		<?php endforeach; ?>
</tbody>
</table>

En résumé, on construit l'en-tête (thead), le pied (tfoot) puis finalement les données du tableau (tbody). Pour une lecture aisée, la liste des objets peut être découpée en pages, un formulaire permet de choisir le nombre d'objets par page. En utilisant le composant Zend_Paginator qui s'appuie sur les sessions PHP pour mémoriser les choix du client.

L'action mettre-à-jour (update) modifier

Cette action prend un identificateur en paramètre, vérifie que les données du formulaire sont valides puis va mettre-à-jour un seul enregistrement. Le même formulaire que 'create' est utilisé sauf qu'il est pré-rempli avec les attributs de l'enregistrement à modifier. La logique de cette action est très proche de create. Cette fois-ci on récupère l'id en paramètre GET, et on pré-remplit un formulaire. Par contre s'il y a des données POST, c'est que l'utilisateur a soumis le formulaire, dans ce cas nous mettons à jour l'enregistrement. La première étape est d'écrire les branchements sans mise-à-jour du modèle :

	public function updateAction()
	{
		$id= (int) $this->_getParam('id');
		$form= new NouvelleForm();
		$this->view->form= $form;
		
	    if ( $this->_request->isPost () )
	    {
	    	$formData= $this->_request->getPost();
	    	if ( $form->isValid( $formData ) )
	    	{				
	    		Zend_Debug::dump($formData, 'Validé !');
	    		// à compléter ...
	    	}
	    	
	    } else {
    		$theRow= $this->_nouvelles->fetchRow ( 'id=' . $id );
			$form->populate ( $theRow->toArray () );	
	    }
	}

La seconde et dernière étape est de compléter avec la mise-à-jour du modèle :

		...
		unset($formData['submit']);
		$where= 'id = '. $id;
		$this->_nouvelles->update( $formData, $where );
		$this->_forward( 'index' );

Les données postées sont nettoyées des données non pertinentes au modèle (valeur du bouton 'submit'). On exécute ensuite la requête de mise-à-jour. Il faut garder à l'esprit que les données provenant des paramètres d'URL comme 'id' doivent être contrôlées pour éviter tous problèmes de sécurité. La vue est la même que pour 'create', ainsi dans application/default/views/scripts/index/update.phtml :

<?php echo $this->form; ?>

Il faut par contre modifier la vue 'index' pour y ajouter une colonne 'modifier' dans les nœuds thead et tfoot :

<th>Modifier</th>

Dans le nœud tbody ce sera un lien vers l'objet avec son id en paramètre :

<td><a href="index/update/id/<?php echo $nouvelle->id; ?>">modif.</a></td>

Pour que le lien vers l'URI aboutisse il est souvent conseillé d'utiliser la balise 'Base' dans l'en-tête Html :

	<head>
		...
	    <base href="http://www.monblog.zf/">

Pour terminer ce tour d'horizon des actions de base, il reste l'action d'effacement : 'delete'.

L'action effacer (delete) modifier

Cette action prend l'identifiant comme paramètre et se déroule en deux temps : au premier appel l'objet à effacer est affiché suivit d'un formulaire avec boutons pour confirmer ou non l'effacement. Si l'utilisateur clique sur 'Non', il est redirigé vers l'action 'index' qui liste tous les enregistrement de l'objet courant. Dans le cas de la confirmation, l'objet est effacé.

   	if ( $this->_request->isPost () ) {
			if ( $this->_hasParam('Oui') ) {	// on efface
				$where= 'avion_id = ' . $id;			// id unique 
				$this->objet->delete ( $where );
				$this->view->message='Effacé(e)';

La première étape est de créer le formulaire de confirmation ainsi l'action delete peut s'écrire ainsi :

public function deleteAction()
{
	$id= (int) $this->_getParam('id');

	$confirmForm= new Zend_Form();		
        $hid= new Zend_Form_Element_Hidden('id');
        $hid->setValue( $id );
        $hid->setLabel('Voulez-vous supprimer la nouvelle num. ' . $id . ' ?');    
        $oui= new Zend_Form_Element_Submit('Oui');
        $oui->removeDecorator('DtDdWrapper');
        $non= new Zend_Form_Element_Submit('Non');
        $non->removeDecorator('DtDdWrapper');
      $confirmForm->addElements( array($hid, $oui, $non) );
      $this->view->confirmForm = $confirmForm;
        
      // à compléter ...
}

Ici le formulaire est programmé mais il aurait pu être tout autant créé directement en Html dans la vue. La vue s'en trouve d'ailleurs ici réduite au minimum :

<?php echo $this->confirmForm; ?>

On doit maintenant ajouter la logique d'effacement :

if ( $this->_request->isPost () )
{
	if ( $this->_hasParam('Oui') )
	{	// on efface
		$where= 'id = ' . $id;			// id unique 
		$this->_nouvelles->delete ( $where );
	}
$this->_forward( 'index' );    		
} else {
	if ( $id > 0 ) {
$this->view->nouvelle= $this->_nouvelles->fetchRow ( 'id=' . $id )->toArray();
	}
} //isPost()

Pour compléter, la vue on récapitule les attributs de la nouvelle. On copie/colle le code source de la vue 'read' à la suite du formulaire ce qui au final est :

<?php echo $this->confirmForm; ?>
<p>Nouvelle numero : <?php echo $this->nouvelle['id']; ?></p>
<ul><?php foreach ( $this->nouvelle as $cle => $valeur ) :	?> 
	<li><?php echo $cle . ' : ' . $valeur; ?></li>	 
<?php endforeach; ?>
</ul>

Il faut comme cela l'a été pour 'update' modifier la vue 'index' pour y ajouter une colonne 'supprimer' dans les nœuds thead et tfoot :

<th>Supprimer</th>

Dans le nœud tbody ce sera un lien vers l'objet avec son id en paramètre :

<td><a href="index/delete/id/<?php echo $nouvelle->id; ?>">suppr.</a></td>

D'autres actions sont envisageables comme les actions d'effacement (deletelist) ou de modification de masse (updatelist) mais cela dépasse le cadre de ce tutoriel.