Con los componentes Zend\Db\Resultset y Zend\Db\Sql nos permitirán hacer consultas a nuestra base de datos.
Mientras que con Resultset podremos crear la SQL directamente con Sql dispondremos de una capa de abstracción que mediante el uso de sus métodos crearemos la consulta.
Otra forma de acceder a los datos contenidos en nuestra base de datos es medianet Zend\Db\TableGateway, usaremos este método cuando queramos trabajar con "factory's". Creando una clase que derive de TableGateway nos permitirá invocar sus métodos nativos para interaccionar con los datos de la base de datos.
Antes de plantearnos nada hemos de definir la cadena de conexión con nuestro sistema gestor, para ello es en el fichero local.php de la carpeta autoload de nuestra aplicación donde deberán estar ubicada esta definición. Este fichero no existe, pero existe otro de nombre local.php.dist que podemos renombrar y usar.
En nuestro caso y como ejemplo hemos creado una base de datos llamada myapp, con un usuario myAppUsername con privilegios de acceso y una contraseña myAppPassword.
El esquema de nuestra base de datos es:
/* Tabla menus */ CREATE TABLE `menus` ( `id_menu` int(10) unsigned NOT NULL, `menu` varchar(255) NOT NULL DEFAULT 'navigation', `name` varchar(255) NOT NULL, `label` varchar(255) NOT NULL, `module` varchar(255) NOT NULL, `controller` varchar(255) NOT NULL, `action` varchar(255) NOT NULL, `order` smallint(6) NOT NULL ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; /* Insertar menus */ INSERT INTO `menus` (`id_menu`, `menu`, `name`, `label`, `module`, `controller`, `action`, `order`) VALUES (1, 'topnav', 'Home', 'Home', 'Application', 'Index', 'index', 0), (2, 'admin', 'Menus', 'Menus', 'Menus', 'Menus', 'index', 0);
Contenido del fichero /config/autoload/local.php:
<?php return array( 'db' => array( 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=myapp;host=localhost', 'username' => 'myAppUsername', 'password' => 'myAppPassword', 'driver_options' => array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8\'' ), ), 'service_manager' => array( 'factories' => array( 'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory' ), ), );
El componente TableGateway es el que encuentro es el más extendido para la interacción con los datos de nuestra base datos.
Lo más correcto es crear una clase que nos proporcione métodos para la interacción con los datos. Al igual que las clases formularios estarán ubicadas en su carpeta src/ModuleName/Form las clases encargadas del acceso a la base de datos las ubicaremos en la carpeta src/ModuleName/Model. Así pues crearemos la carpeta Model en /module/Menus/src/Menus/, y dentro crearemos nuestra clase en el fichero MenusTable.php.
Contenido del fichero /module/Menus/src/Menus/Model/MenusTable.php:
<?php namespace Menus\Model; use Zend\Db\TableGateway\TableGateway; use Zend\Db\Adapter\Adapter; use Zend\Db\Sql\Select; use Zend\Db\ResultSet\ResultSet; class MenusTable extends TableGateway { protected $table = 'menus'; public function __construct(Adapter $adapter = null, $databaseSchema = null, ResultSet $selectResultPrototype = null) { return parent::__construct($this->table, $adapter, $databaseSchema, $selectResultPrototype); } public function saveMenu($menu, $name, $label, $module, $controller, $action, $order){ $data['menu'] = $menu; $data['name'] = $name; $data['label'] = $label; $data['module'] = $module; $data['controller'] = $controller; $data['action'] = $action; $data['order'] = $order; $this->insert($data); return $this->lastInsertValue; } }
Una vez definido la clase modelo ya estamos capacitados a interaccionar con la base de datos desde nuestro controlador. Así editaremos nuestro fichero MenusController.php y añadiremos la funcionalidad de creación de un nuevo registro.
Contenido del fichero /module/Menus/src/Menus/Controller/MenusController.php:
<?php namespace Menus\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; use Menus\Form\MenuForm; use Menus\Form\MenuFilter; use Menus\Model\MenusTable; class MenusController extends AbstractActionController { /** * Crea un nuevo registro * * @return \Zend\View\Model\ViewModel */ public function createAction() { $form = new MenuForm(); $form->setInputFilter(new MenuFilter()); $viewVars = array ( 'title' => 'Add Menu', 'form' => $form ); if (! $this->request->isPost ()) { return new ViewModel ( $viewVars ); } $post = $this->request->getPost (); $form->setData ( $post ); if (! $form->isValid ()) { $viewVars ['error'] = true; return new ViewModel ( $viewVars ); } // Create menu try { $formData = $form->getData(); $adapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter'); $MenusTable = new MenusTable($adapter); $menu = (isset ( $formData ['menu'] )) ? $formData ['menu'] : null; $name = (isset ( $formData ['name'] )) ? $formData ['name'] : null; $label = (isset ( $formData ['label'] )) ? $formData ['label'] : null; $module = (isset ( $formData ['module'] )) ? $formData ['module'] : null; $controller = (isset ( $formData ['controller'] )) ? $formData ['controller'] : null; $action = (isset ( $formData ['action'] )) ? $formData ['action'] : null; $order = (isset ( $formData ['order'] )) ? $formData ['order'] : null; $MenusTable->saveMenu ( $menu, $name, $label, $module, $controller, $action, $order ); return $this->redirect()->toRoute(NULL, array( 'controller' => 'menus', 'action' => 'index' )); } catch (\Exception $e) { $viewVars['error'] = true; $viewVars['message'] = $e->getMessage(); } return new ViewModel ( $viewVars ); } }
En este métod podemos acceder de dos formas, mediante la llamada directa desde URL, en ese caso $this->request->isPost () será true, con lo que directamente saldremos del método y mostraremos el formulario de entrada de datos, o, el acceso es mediante el action del formulario, en ese caso $this->request->isPost () devolverá un valor false y seguirá ejecutando las instrucciones del método.
En el caso de que nos encontremos que es el formulario envía los datos mediante el método post, debemos validarlos mediante $form->isValid (), que nos devolverá un valor false en caso de que no cumpla con las reglas establecidas.
El siguiente paso será recuperar los datos enviados en el request y pasarlos a nuestra clase modelo para que realice una inserción de un nuevo registro.
Para recuperar valores del post en nuestro controlador siempre podemos usar:
$data = $this->request->getPost(); $variable = $data['variable'];
Para finalizar este ejemplo deberemos crear el método indexAction dentro de nuestro controlador, así como la vista al mismo asociado.
Antes editaremos nuestra clase modelo y añadiremos la función fetchAll.
Añadiremos un nuevo método al fichero /module/Menus/src/Menus/Model/MenusTable.php:
public function fetchAll($where = array(), $order = array('order asc')){ $rowset = $this->select(function (Select $select) use ($where, $order){ if( count($where) > 0 ){ $select->where ( $where ); } if( count($order) > 0 ){ $select->order ( $order ); } } ); return $rowset; }
En nuestro controlador añadiremos el método indexAction.
Añadiremos un nuevo método al fichero /module/Menus/src/Menus/Controller/MenusController.php:
public function indexAction() { $adapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter'); $menusTable = new MenusTable($adapter); $menus = $menusTable->fetchAll(array(), array( 'menu', 'order' )); $viewVars = array( 'title' => 'Menus list', 'menus' => $menus ); return new ViewModel($viewVars); }Ahora tan solo nos falta definir la nueva vista asociada a la acción de crear un nuevo registro en el controlador. Para ello crearemos un fichero llamado index.phtml en /module/Menus/view/menus/.
Contenido del fichero /module/Menus/view/menus/index.phtml:
<section class="Menus"> <?php if( isset($this->menus) ){ ?> <table class="table table-striped table-bordered table-condensed"> <tr> <th><?php echo $this->translate('Menu'); ?></th> <th><?php echo $this->translate('Menu Name'); ?></th> <th><?php echo $this->translate('Label'); ?></th> <th><?php echo $this->translate('Module'); ?></th> <th><?php echo $this->translate('controller'); ?></th> <th><?php echo $this->translate('action'); ?></th> <th><?php echo $this->translate('order'); ?></th> <th width="300px"> </th> </tr> <?php foreach ($this->menus as $menu){ ?> <tr> <td><?php echo $menu['menu']; ?></td> <td><?php echo $menu['name']; ?></td> <td><?php echo $menu['label']; ?></td> <td><?php echo $menu['module']; ?></td> <td><?php echo $menu['controller']; ?></td> <td><?php echo $menu['action']; ?></td> <td><?php echo $menu['order']; ?></td> <td><a href="<?php echo $this->url('menus/default', array('controller' => 'menus', 'action' => 'edit', 'id' => $menu['id_menu']), null); ?>"><?php echo $this->translate('Edit'); ?></a> | <a href="<?php echo $this->url('menus/default', array('controller' => 'menus', 'action' => 'delete', 'id' => $menu['id_menu']), null); ?>"><?php echo $this->translate('Delete');?></a> </td> </tr> <?php } ?> </table> <?php } ?> <p><a class="btn btn-primary" href="<?php echo $this->url('menus/default', array('controller' => 'menus', 'action' => 'create'), null); ?>"><?php echo $this->translate('Add new menu');?></a></p> </section>
Sólo nos resta comprobar el resultado de la creación de nuevas entradas de menú, para ello navegaremos a la dirección http://localhost/myApp/menus/menus e iremos insertando nuevos registros:
Dejaremos para más adelante la edición y el borrado de entradas.
No hay comentarios:
Publicar un comentario