CRUD en MVC avec le ZendFramework
Voila le plus chiant souvent c'est de faire des système de CRUD (Creation Read Update Delete) pour des tables a chaque nouveaux projets, et je me suis amusé une petite demie heure avec le ZendFramework pour voir si c'était possible simplement ...
Admettons que j'ai des tables user, photo, post, comment par exemple ... Je vais créer dans ma structure de répertoire (voir ici) des classes UserModel, PhotoModel, PostModel et CommentModel qui ressemblent a ça :
class UserModel extends Zend_Db_Table { protected $_name = "user"; protected $_primary = "id"; }
Je les fait pas toutes, elle sont toutes identiques ...
On va faire un controlleur qui gère tout ça ! Dans un premier temps, on va s'occuper d'afficher les données ainsi qu'un formulaire ... après on y fera les actions qui vont bien puis après il faudra y faire des paginations et tout, mais ça pour l'instant, j'en ai pas besoin alors il va falloit que vous réfléchissiez quand même un peu :)
Le controlleur AdminController :
class AdminController extends Zend_Controller_Action { public function __call($action, $arguments) { $model = ucwords(str_replace('Action', 'Model', $action)); $view = Zend_Registry::get('view'); $view->model = new $model(); echo $view->render('Admin/model.php'); } }
Bien sur ça nécéssiterait d'un peu plus de vérifications ... mais bon dans l'immédiat ça construit un model et ça le passe à la vue. Si on tape http://monProjet/Admin/user on aura l'admin des users ! On intercèpte en fait le dernier call avant l'erreur avec la methode __call ce qui rend les choses plus génériques! on n'est pas obligé de faire une action par modèle !
Maintenant il faut faire la vue qui va bien. Pour cela on va se servir de la table d'information que le récupère par le modèle :
<?= $this->render('header.php') ?> <?php $data = $this->model->fetchAll()->toArray(); $info = $this->model->info(); ?> <h2>Formular</h2> <form method="post"> <?php foreach ($info['cols'] as $k) { if (!in_array($k, $info['primary'])) { ?> <label for="<?= $k ?>"><?= $k ?></label> <input type="text" name="<?= $k ?>" value="" /> <br /> <?php } } ?> <br /> <input type="submit" value="Insert/Update"> </form> <hr /> <h2>Data</h2> <table> <thead> <tr> <?php foreach ($info['cols'] as $k) { ?> <th><?= $k ?></th> <?php } ?> </tr> </thead> <tbody> <?php foreach ($data as $item) { ?> <tr> <?php foreach ($item as $v) { ?> <td><?= $v ?></td> <?php } ?> </tr> <?php } ?> </tbody> </table> <?= $this->render('footer.php') ?>
Bon c'est un poil plus long, mais si on regarde bien c'est pas si compliqué !
Reste plus qu'a y ajouter des actions derrière tout ça !
J'avais commencé a tout détailler, pour vraiment bien expliquer, le problème c'est que c'est long et que je complique à ajouter de bouts de codes partout, comme je sais que je n'aime pas lire des articles pompeux, je vais mettre le code fini et clair =)
Pour le controlleur la fonction __call:
public function __call($action, $arguments) { $model = ucwords(str_replace('Action', 'Model', $action)); /* initialize view */ $view = Zend_Registry::get('view'); $view->action = str_replace('Action', '', $action); $view->model = new $model(); /* get some information */ $info = $view->model->info(); $primary = $info["primary"][0]; /* delete part */ if ($delete = $this->_getParam('delete')) { $view->model->delete($primary .'='. $delete); $this->_redirect('Admin/' . $view->action); } /* insert/update part */ if ($mode = $this->_getParam('formularType')) { $data = array_intersect_key($this->_getAllParams(), array_flip($info["cols"])); if ($mode == 'new') { $view->model->insert($data); } else { unset($data[$primary]); $view->model->update($data, $primary . "=" . $this->_getParam($primary)); } $this->_redirect('Admin/' . $view->action); } /* get data for edit */ if ($id = $this->_getParam($primary)) { if ($data = $view->model->find($id)) { $view->mode = 'edit'; $data = $data->toArray(); $view->itemEdit = $data[0]; } } /* show view */ echo $view->render('Admin/model.php'); }
Voila ya tout. Et pour la vue :
<?= $this->render('header.php') ?> <?php /* gather some information */ $data = $this->model->fetchAll()->toArray(); $info = $this->model->info(); $primary = $info["primary"][0]; $link = $this->baseUrl() .'/Admin/'. $this->action; ?> <h2>Formular</h2> <form method="post" action="<?= $link ?>"> <?php foreach ($info['cols'] as $k) { if (!in_array($k, $info['primary'])) { ?> <label for="<?= $k ?>"><?= $k ?></label> <input type="text" name="<?= $k ?>" value="<?= (isset($this->itemEdit)) ? $this->itemEdit[$k] : "" ?>" /> <br /> <?php } } ?> <br /> <?php /* specific part when editing */ $mode = 'new'; if (isset($this->mode) && ($this->mode == 'edit')) { $mode = 'edit'; ?> <input type="hidden" name="<?= $primary ?>" value="<?= $this->itemEdit[$primary] ?>" /> <?php } ?> <input type="hidden" name="formularType" value="<?= $mode ?>" /> <input type="submit" value="Insert/Update"> </form> <hr /> <h2>Data</h2> <table> <thead> <tr> <th>Options</th> <?php foreach ($info['cols'] as $k) { ?> <th><?= $k ?></th> <?php } ?> </tr> </thead> <tbody> <?php foreach ($data as $item) { ?> <tr> <td> <a href="<?= $link ?>?<?= $primary ?>=<?= $item[$primary] ?>">Update</a> <a href="<?= $link ?>?delete=<?= $item[$primary] ?>">Delete</a> </td> <?php foreach ($item as $v) { ?> <td><?= $v ?></td> <?php } ?> </tr> <?php } ?> </tbody> </table> <?= $this->render('footer.php') ?>
Pareil donc on a assez simplement un CRUD en MVC grâce au ZendFramework !
