L'action lire (read).
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 : 
<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 : 
L'affichage ne produira qu'un codice_1 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 codice_2 et sa vue.
L'action ajouter (create).
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 codice_3 :
L'action lister tous les objets (index).
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');
codice_4 retourne un objet codice_5 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 codice_5 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).
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 codice_2.
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 ...