Création d'un module sous Magento 2 - Partie 5 - Le Grid

Le Grid dans Magento est un système (presque) tout fait permettant d'afficher la liste des données contenues dans la base de données. Il permet aussi de mettre en place des formulaires d'ajout ou de modification de données, ainsi qu'un système de suppression. Pour notre exemple, nous allons créer un Grid pour lister nos commerciaux.

Introduction

Cet article va être long ! Il y a beaucoup de fichiers à créer et à comprendre. Pour la création du Grid il va falloir créer 4 fichiers. En voici la liste, par ordre de création : 

  • Controller/Adminhtml/Index/Index.php Modification du contrôleur qu'on a créé dans la partie précédente.
  • view/adminhtml/layout/thorleif_index_index.xml : le layout pour définir le bloc à utiliser
  • Block/Adminhtml/Commerciaux.php : le Grid container (appelé depuis le layout)
  • Block/Adminhtml/Commerciaux/Grid.php : le Grid ! 

Voilà, on a tous les fichiers concernant le Grid. Maintenant, voici les fichiers nécessaires pour créer les formulaires d'ajout, de modification et de suppression :

  • Controller/Adminhtml/Index/Edit.php : l'action qui va gérer l'affichage du formulaire d'ajout et de modification
  • view/adminhtml/layout/thorleif_index_edit.xml : le layout pour définir le block à utiliser pour les formulaires d'ajout et d'édition
  • Block/Adminhtml/Commerciaux/Edit.php : le block contenant le container du formulaire
  • Block/Adminhtml/Commerciaux/Edit/Tabs.php : les onglets sur le côté du formulaire 
  • Block/Adminhtml/Commerciaux/Edit/Form.php : la préparation du formulaire 
  • Block/Adminhtml/Commerciaux/Edit/Tab/Info.php : la configuration du formulaire
  • Controller/Adminhtml/index/NewAction.php : l'action pour ajouter un commercial (on redirige vers l'edit car c'est le même formulaire)
  • Controller/Adminhtml/Index/Save.php : l'action pour sauvegarder nos données 
  • Controller/Adminhtml/Index/Delete.php : l'action pour supprimer nos données une par une 
  • Controller/Adminhtml/Index/MassDelete.php : l'action pour supprimer plusieurs données en une seule fois.

Maintenant que nos fichiers sont créés, nous pouvons coder ! Nous allons attaquer chacun des fichiers en suivant l'ordre défini ci-dessus. 

Le Grid et son container

La première chose que l'on va faire est la création du Grid pour lister nos commerciaux. Pour cela, on va d'abord modifier notre contrôleur Index. On va utiliser ici la classe PageFactory qui va nous permettre de créer notre page. On importe donc son namespace, et on le définit dans le constructeur de la classe. Ensuite, dans la méthode execute(), on créé notre page, et, avant de la retourner, on la configure en précisant quel menu est actif, quel sera le titre de la page, et enfin, comment sera défini le fil d'ariane. 

/app/code/Ns/Thorleif/Controller/Adminhtml/Index/Index.php
  1. <?php
  2. namespace Ns\Thorleif\Controller\Adminhtml\Index;
  3.  
  4. use Magento\Framework\View\Result\PageFactory;
  5. use Magento\Backend\App\Action\Context;
  6.  
  7. class Index extends \Magento\Backend\App\Action
  8. {
  9.     protected $resultPageFactory;
  10.  
  11.     public function __construct(Context $context, PageFactory $resultPageFactory)
  12.     {
  13.         $this->resultPageFactory = $resultPageFactory;
  14.         parent::__construct($context);
  15.     }
  16.  
  17.     public function execute()
  18.     {
  19.         $resultPage = $this->resultPageFactory->create();
  20.         $resultPage->setActiveMenu('Ns_Thorleif::index'); // Notez bien l'identifiant de votre menu !
  21.         $resultPage->addBreadcrumb(__('Gestion des commerciaux'), __('Gestion des commerciaux'));
  22.         $resultPage->getConfig()->getTitle()->prepend(__('Gestion des commerciaux'));
  23.         return $resultPage;
  24.     }
  25. }

Notre contrôleur terminé, nous allons nous attaquer au layout. Ici, on va juste préciser que c'est le block Ns\Thorleif\Block\Adminhtml\Commerciaux qui va être exécuté. Ce block sera le container du Grid, mais on y vient juste après.

/app/code/Ns/Thorleif/view/adminhtml/layout/thorleif_index_index.xml
  1. <?xml version="1.0"?>
  2. <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.       xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
  4.     <body>
  5.         <referenceContainer name="content">
  6.             <block class="Ns\Thorleif\Block\Adminhtml\Commerciaux" name="thorleif_index_index"/>
  7.         </referenceContainer>
  8.     </body>
  9. </page>

Dans ce layout, on a précisé quel sera le block à exécuter. Il va donc falloir le créer ! Ce block se nommera Commerciaux (choisissez un nom qui corresponde mieux à votre projet), et sera le container du Grid. Ici, on va préciser le nom du répertoire qui contiendra la liste des blocks permettant de construire le Grid. Attention : on parle d'un nom de répertoire contenant des blocks, mais l'attribut contenant cette information se nomme "$_controller", ce qui peut porter à confusion. On définit aussi le nom du module (attribut $_blockGroup), le titre dans le header (attribut $_headerText), et enfin, le label du bouton d'ajout d'un nouveau commercial. Il existe d'autres options, mais je vous laisse faire des recherches par vous-même. 

/app/code/Ns/Thorleif/Block/Adminhtml/Commerciaux.php
  1. <?php
  2. namespace Ns\Thorleif\Block\Adminhtml;
  3.  
  4. class Commerciaux extends \Magento\Backend\Block\Widget\Grid\Container
  5. {
  6.     protected function _construct()
  7.     {
  8.         $this->_controller = 'adminhtml_commerciaux';
  9.         $this->_blockGroup = 'Ns_Thorleif';
  10.         $this->_headerText = __('Gestion des commerciaux');
  11.         $this->_addButtonLabel = __('Add Item');
  12.         parent::_construct();
  13.     }
  14. }

Le container créé, nous pouvons nous attaquer au Grid. Nous allons donc créer un fichier Grid.php dans le répertoire Block/Adminhtml/Commericaux/ (que nous allons devoir créer), qui contiendra la configuration du Grid.

Pour faire simple, on va lister les méthodes à implémenter, et préciser leur rôle pour la construction du Grid : 

  • _construct() : On précise ici l'id du Grid, l'ordre par défaut d'affichage des données, et si le filtre est sauvegardé en session
  • _prepareCollection() : On récupère la collection des commerciaux afin de les afficher
  • _prepareColumns() : On liste les données des commericaux à afficher ainsi que la liste des exports possibles
  • _prepareMassaction() : On configure les actions de masse, afin de pouvoir supprimer plusieurs commerciaux d'un coup
  • getGridUrl() : Retourne l'URL du Grid 
  • getRowUrl() : Retourne l'URL de la page d'ajout/d'édition

Voici le code complet du fichier Grid.php pour notre exemple sur les commerciaux : 

/app/code/Ns/Thorleif/Block/Adminhtml/Commerciaux/Grid.php
  1. <?php
  2. namespace Ns\Thorleif\Block\Adminhtml\Commerciaux;
  3.  
  4. class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
  5. {
  6.     protected $_commerciauxFactory; // On ajoute le suffixe Factory à notre modèle.
  7.  
  8.     protected $_coreRegistry;
  9.  
  10.  
  11.     public function __construct(
  12.         \Magento\Backend\Block\Template\Context $context,
  13.         \Magento\Backend\Helper\Data $backendHelper,
  14.         \Ns\Thorleif\Model\CommerciauxFactory $commerciauxFactory, // On ajoute le suffixe Factory à notre modèle
  15.         \Magento\Framework\Registry $coreRegistry,
  16.         array $data = [] )
  17.     {
  18.         $this->_commerciauxFactory = $commerciauxFactory;
  19.         $this->_coreRegistry = $coreRegistry;
  20.         parent::__construct($context, $backendHelper, $data);
  21.     }
  22.  
  23.  
  24.     protected function _construct()
  25.     {
  26.         parent::_construct();
  27.         $this->setId('commerciauxGrid');
  28.         $this->setDefaultSort('id');
  29.         $this->setDefaultDir('ASC');
  30.         $this->setSaveParametersInSession(true);
  31.     }
  32.  
  33.  
  34.     protected function _prepareCollection()
  35.     {
  36.         $collection = $this->_commerciauxFactory->create()->getCollection();
  37.         $this->setCollection($collection);
  38.         return parent::_prepareCollection();
  39.     }
  40.  
  41.  
  42.     protected function _prepareColumns()
  43.     {
  44.         $this->addColumn(
  45.             'id', [
  46.                 'header' => __('ID'),
  47.                 'type' => 'number',
  48.                 'index' => 'id',
  49.                 'header_css_class' => 'col-id',
  50.                 'column_css_class' => 'col-id',
  51.                 'width' => 10
  52.             ]
  53.         );
  54.         $this->addColumn(
  55.             'name', [
  56.                 'header' => __('Name'),
  57.                 'index' => 'name',
  58.                 'width' => 40
  59.             ]
  60.         );
  61.         $this->addColumn(
  62.             'city', [
  63.                 'header' => __('City'),
  64.                 'index' => 'city',
  65.                 'width' => 40
  66.             ]
  67.         );
  68.         $this->addExportType('*/*/exportCsv', __('CSV'));
  69.         $this->addExportType('*/*/exportXml', __('XML'));
  70.         $this->addExportType('*/*/exportExcel', __('Excel'));
  71.  
  72.         return parent::_prepareColumns();
  73.     }
  74.  
  75.  
  76.     protected function _prepareMassaction()
  77.     {
  78.         $this->setMassactionIdField('id');
  79.         $this->getMassactionBlock()->setFormFieldName('commerciaux');
  80.  
  81.         $this->getMassactionBlock()->addItem(
  82.             'delete', [
  83.                 'label' => __('Delete'),
  84.                 'url' => $this->getUrl('thorleif/*/massDelete'),
  85.                 'confirm' => __('Are you sure?'),
  86.             ]
  87.         );
  88.         return $this;
  89.     }
  90.  
  91.  
  92.     public function getGridUrl()
  93.     {
  94.         return $this->getUrl('*/*/index', ['_current' => true]);
  95.     }
  96.  
  97.  
  98.     public function getRowUrl($row)
  99.     {
  100.         return $this->getUrl( '*/*/edit', ['id' => $row->getId()] );
  101.     }
  102.  
  103. }

Si tout est correct, vous devriez avoir le résultat suivant : 

creation-d-un-module-sous-magento-2-partie-5-le-grid

On a bien une liste de commerciaux, et le Grid de Magento a ajouté automatiquement un système de filtres, d'exports, de pagination, et une mise en page responsive, toutes ces choses rébarbatives que nous n'auront pas à créer ! 

Le formulaire d'édition

Attaquons-nous maintenant au formulaire d'édition. Dans un premier temps, nous allons créer le contrôleur qui va afficher le formulaire. Appelons ce contrôleur Edit.php, et plaçons-le dans le répertoire Controller/Adminhtml/Index/ de notre module :  

/app/code/Ns/Thorleif/Controller/Adminhtml/Index/Edit.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Controller\Adminhtml\Index;
  4.  
  5. class Edit extends \Magento\Backend\App\Action
  6. {
  7.  
  8.     protected $_coreRegistry = null;
  9.     protected $resultPageFactory;
  10.  
  11.  
  12.     public function __construct(
  13.         \Magento\Backend\App\Action\Context $context,
  14.         \Magento\Framework\View\Result\PageFactory $resultPageFactory,
  15.         \Magento\Framework\Registry $registry
  16.     )
  17.     {
  18.         $this->resultPageFactory = $resultPageFactory;
  19.         $this->_coreRegistry = $registry;
  20.         parent::__construct($context);
  21.     }
  22.  
  23.  
  24.     public function execute()
  25.     {
  26.         // Récupération de l'id et du modèle
  27.         $id = $this->getRequest()->getParam('id');
  28.         $model = $this->_objectManager->create('Ns\Thorleif\Model\Commerciaux');
  29. ;
  30.         // Vérification de l'existance de l'id dans la BDD
  31.         if ($id)
  32.         {
  33.             $model->load($id);
  34.             if (!$model->getId())
  35.             {
  36.                 $this->messageManager->addError(__('Le commercial n\'existe pas'));
  37.                 $resultRedirect = $this->resultRedirectFactory->create();
  38.                 return $resultRedirect->setPath('*/*/');
  39.             }
  40.         }
  41.  
  42.         // Récupération des données
  43.         $data = $this->_objectManager->get('Magento\Backend\Model\Session')->getFormData(true);
  44.         if (!empty($data))
  45.         {
  46.             $model->setData($data);
  47.         }
  48.  
  49.         // Sauvegarde du model pour l'utiliser dans les blocs par la suite
  50.         $this->_coreRegistry->register('ns_thorleif', $model);
  51.  
  52.         // Construction du formulaire
  53.         $resultPage = $this->resultPageFactory->create();
  54.         $resultPage->setActiveMenu('Ns_Thorleif::index')
  55.             ->addBreadcrumb(__('Commerciaux'), __('Commerciaux'))
  56.             ->addBreadcrumb(__('Gestion des commerciaux'), __('Gestion des commerciaux'));
  57.         $resultPage->getConfig()->getTitle()->prepend($model->getId() ? __('Modification de ') . $model->getName() : __('Nouveau commercial'));
  58.  
  59.         return $resultPage;
  60.     }
  61. }

Dans l'exemple ci-dessus, j'ai ajouté des commentaires pour que vous compreniez bien ce qu'on est en train de faire. Ce n'est pas bien compliqué à comprendre : on récupère le commercial ayant l'id renseigné dans la requête HTTP, s'il le commercial n'existe pas, on est redirigé vers la liste des commerciaux. Une fois qu'on a récupéré notre commercial, on l'enregistre dans un registre, et on configure notre page (titre, fil d'ariane, ... ), puis on retourne la page générée. 

Après le contrôleur, il va falloir créer le layout qui permettra l'affichage du formulaire. Dans ce layout, on va ajouter les blocks thorleif_index_edit (dans le contenu) et thorleif_index_edit_tabs (à la  gauche de la page). Vérifiez bien les noms des fichiers et des blocks ! 

/app/code/Ns/Thorleif/view/adminhtml/layout/thorleif_index_edit.xml
  1. <?xml version="1.0"?>
  2. <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.       layout="admin-2columns-left"
  4.       xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
  5.     <head>
  6.         <css src="jquery/fileUploader/css/jquery.fileupload-ui.css"/>
  7.     </head>
  8.     <update handle="editor"/>
  9.     <body>
  10.         <referenceContainer name="content">
  11.             <block class="Ns\Thorleif\Block\Adminhtml\Commerciaux\Edit" name="thorleif_index_edit"/>
  12.         </referenceContainer>
  13.         <referenceContainer name="left">
  14.             <block class="Ns\Thorleif\Block\Adminhtml\Commerciaux\Edit\Tabs" name="thorleif_index_edit_tabs"/>
  15.         </referenceContainer>
  16.     </body>
  17. </page>

Le block thorleif_index_edit correspond au container du formulaire (comme il existe un container pour le Grid). Créons donc ce block : fichier Edit.php dans le répertoire Block/Adminhtml/Commerciaux/ . Dans ce fichier, on configure le formulaire, et on précise les infos suivantes : 

  • L'ajout des boutons "Save", "Save and Continue", et  "Delete"
  • Le titre de la page dans le header
/app/code/Ns/Thorleif/Block/Adminhtml/Commerciaux/Edit.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Block\Adminhtml\Commerciaux;
  4.  
  5. use Magento\Backend\Block\Widget\Context;
  6. use Magento\Framework\Registry;
  7.  
  8. class Edit extends \Magento\Backend\Block\Widget\Form\Container
  9. {
  10.  
  11.     protected $_coreRegistry = null;
  12.  
  13.  
  14.     public function __construct(Context $context, Registry $registry, array $data = [])
  15.     {
  16.         $this->_coreRegistry = $registry;
  17.         parent::__construct($context, $data);
  18.     }
  19.  
  20.  
  21.     protected function _construct()
  22.     {
  23.         $this->_objectId = 'id';
  24.         $this->_controller = 'adminhtml_commerciaux';
  25.         $this->_blockGroup = 'Ns_Thorleif';
  26.  
  27.         parent::_construct();
  28.  
  29.         $this->buttonList->update('save', 'label', __('Save'));
  30.         $this->buttonList->add(
  31.             'saveandcontinue',
  32.             [
  33.                 'label' => __('Save and Continue Edit'),
  34.                 'class' => 'save',
  35.                 'data_attribute' => [
  36.                     'mage-init' => [
  37.                         'button' => [
  38.                             'event' => 'saveAndContinueEdit',
  39.                             'target' => '#edit_form'
  40.                         ]
  41.                     ]
  42.                 ]
  43.             ],
  44.             -100
  45.         );
  46.         $this->buttonList->update('delete', 'label', __('Delete'));
  47.     }
  48.  
  49.  
  50.     public function getHeaderText()
  51.     {
  52.         $registry = $this->_coreRegistry->registry('ns_thorleif');
  53.         if ($registry->getId()) {
  54.             $name = $this->escapeHtml($registry->getName());
  55.             return __("Modificaion du commercial '%1'", $name);
  56.         }
  57.         else
  58.         {
  59.             return __('Ajout d\'un commercial');
  60.         }
  61.     }
  62. }

Après la création du container du formulaire, on crée la partie de gauche contenant les onglets des différentes parties du formulaire. Pour notre exemple, on n'aura qu'un seul onglet. Créons donc un fichier Tabs.php dans le répertoire Block/Adminhtml/Commerciaux/Edit/ de notre module. Dans ce fichier on va préciser le titre de notre onglet, et la partie du formulaire auquel il est attaché, à savoir le block Info.php que nous allons créer par la suite. 

/app/code/Ns/Thorleif/Block/Adminhtml/Commerciaux/Edit/Tabs.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Block\Adminhtml\Commerciaux\Edit;
  4.  
  5. class Tabs extends \Magento\Backend\Block\Widget\Tabs
  6. {
  7.  
  8.     protected function _construct()
  9.     {
  10.         parent::_construct();
  11.         $this->setId('thorleif_edit_tabs');
  12.         $this->setDestElementId('edit_form');
  13.         $this->setTitle(__('Informations'));
  14.     }
  15.  
  16.  
  17.     protected function _beforeToHtml()
  18.     {
  19.         $this->addTab(
  20.             'commerciaux_info',
  21.             [
  22.                 'label' => __('General'),
  23.                 'title' => __('General'),
  24.                 'content' => $this->getLayout()->createBlock(
  25.                     'Ns\Thorleif\Block\Adminhtml\Commerciaux\Edit\Tab\Info'
  26.                 )->toHtml(),
  27.                 'active' => true
  28.             ]
  29.         );
  30.  
  31.         return parent::_beforeToHtml();
  32.     }
  33. }

Le prochain fichier à créer est le fichier Form.php à placer dans le répertoire Block/Adminhtml/Commerciaux/Edit/ de notre module. Ici, on va préparer le formulaire, en lui précisant un ID, l'action (le contrôleur qui va gérer les données envoyées), et la méthode (POST ici). On remarquera que l'action est une donnée qui est envoyée depuis le contrôleur. 

/app/code/Ns/Thorleif/Block/Adminhtml/Commerciaux/Edit/Form.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Block\Adminhtml\Commerciaux\Edit;
  4.  
  5. class Form extends \Magento\Backend\Block\Widget\Form\Generic
  6. {
  7.     /**
  8.      * @return $this
  9.      */
  10.     protected function _prepareForm()
  11.     {
  12.         $form = $this->_formFactory->create(
  13.             [
  14.                 'data' => [
  15.                     'id'    => 'edit_form',
  16.                     'action' => $this->getData('action'),
  17.                     'method' => 'post'
  18.                 ]
  19.             ]
  20.         );
  21.         $form->setUseContainer(true);
  22.         $this->setForm($form);
  23.  
  24.         return parent::_prepareForm();
  25.     }
  26. }

Dernier fichier à créer avant de pouvoir afficher notre page d'édition, le fichier Info.php du répertoire Block/Adminhtml/Commerciaux/Edit/Tab/ de notre module. Dans ce fichier nous allons configurer notre formulaire : 

  • On va récupérer les données à afficher dans le formulaire dans le cas d'une mise à jour des données
  • On ajoute un fieldset et la liste des champs à afficher 
  • On configure le titre de l'onglet concernant cette partie du formulaire
  • On précise si on affiche l'onglet on pas (dans notre cas, on va l'afficher)
/app/code/Ns/Thorleif/Block/Adminhtml/Commerciaux/Edit/Tab/Info.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Block\Adminhtml\Commerciaux\Edit\Tab;
  4.  
  5. use Magento\Backend\Block\Widget\Form\Generic;
  6. use Magento\Backend\Block\Widget\Tab\TabInterface;
  7. use Magento\Backend\Block\Template\Context;
  8. use Magento\Framework\Registry;
  9. use Magento\Framework\Data\FormFactory;
  10. use Magento\Cms\Model\Wysiwyg\Config; // A utiliser quand on a un textarea
  11.  
  12. class Info extends Generic implements TabInterface
  13. {
  14.  
  15.     public function __construct(
  16.         Context $context,
  17.         Registry $registry,
  18.         FormFactory $formFactory,
  19.         Config $wysiwygConfig, // A utiliser quand on a un textarea
  20.         array $data = []
  21.     )
  22.     {
  23.         parent::__construct($context, $registry, $formFactory, $data);
  24.     }
  25.  
  26.  
  27.     protected function _prepareForm()
  28.     {
  29.         $model = $this->_coreRegistry->registry('ns_thorleif');
  30.  
  31.         $form = $this->_formFactory->create();
  32.         $form->setHtmlIdPrefix('commerciaux_');
  33.         $form->setFieldNameSuffix('commerciaux');
  34.  
  35.         $fieldset = $form->addFieldset(
  36.             'base_fieldset',
  37.             ['legend' => __('General')]
  38.         );
  39.  
  40.         if ($model->getId())
  41.         {
  42.             $fieldset->addField(
  43.                 'id',
  44.                 'hidden',
  45.                 ['name' => 'id']
  46.             );
  47.         }
  48.         $fieldset->addField(
  49.             'name',
  50.             'text',
  51.             [
  52.                 'name'        => 'name',
  53.                 'label'    => __('Name'),
  54.                 'required'     => true
  55.             ]
  56.         );
  57.         $fieldset->addField(
  58.             'city',
  59.             'text',
  60.             [
  61.                 'name'        => 'city',
  62.                 'label'    => __('City'),
  63.                 'required'     => true
  64.             ]
  65.         );
  66.  
  67.         $data = $model->getData();
  68.         $form->setValues($data);
  69.         $this->setForm($form);
  70.  
  71.         return parent::_prepareForm();
  72.     }
  73.  
  74.  
  75.     public function getTabLabel()
  76.     {
  77.         return __('Informations');
  78.     }
  79.  
  80.  
  81.     public function getTabTitle()
  82.     {
  83.         return __('Informations');
  84.     }
  85.  
  86.  
  87.     public function canShowTab()
  88.     {
  89.         return true;
  90.     }
  91.  
  92.  
  93.     public function isHidden()
  94.     {
  95.         return false;
  96.     }
  97. }

C'est terminé pour le formulaire d'ajout/suppression. Si tout s'est bien passé, en cliquant sur un enregistrement dans la liste des commerciaux, nous devrions tomber sur une page qui affiche le résultat suivant : 

creation-d-un-module-sous-magento-2-partie-5-le-grid-2

Les autres contrôleurs

Tous nos blocks sont créés, notre Grid fonctionne, et notre formulaire d'ajout/mise à jour fonctionne correctement. La dernière chose à faire est de créer les différents contrôleurs permettant l'affichage du formulaire d'ajout d'un commercial (il va simplement rediriger vers le formulaire d'édition), la sauvegarde de données suite à la soumission des formulaires d'ajout et de mise à jour, la suppression d'un enregistrement, et la suppression de masse. 

Commençons par le  plus simple, le contrôleur permettant d'afficher le formulaire d'ajout d'un commercial. On fait simplement une redirection vers le contrôleur d'édition comme on l'a vu : 

/app/code/Ns/Thorleif/Controller/Adminhtml/Index/NewAction.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Controller\Adminhtml\Index;
  4.  
  5. // Attention ici le nom du fichier est de la classe est NewAction et non pas New tout court !
  6. class NewAction extends \Magento\Backend\App\Action
  7. {
  8.     protected $resultForwardFactory;
  9.  
  10.     public function __construct(
  11.         \Magento\Backend\App\Action\Context $context,
  12.         \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
  13.     )
  14.     {
  15.         $this->resultForwardFactory = $resultForwardFactory;
  16.         parent::__construct($context);
  17.     }
  18.  
  19.  
  20.     public function execute()
  21.     {
  22.         $resultForward = $this->resultForwardFactory->create();
  23.         return $resultForward->forward('edit');
  24.     }
  25. }

Les trois dernières actions sont les actions pour la sauvegarde des données, la suppression et la suppression de masse. Voici le contenu de ces trois fichiers : 

/app/code/Ns/Thorleif/Controller/Adminhtml/Index/Save.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Controller\Adminhtml\Index;
  4.  
  5. class Save extends \Magento\Backend\App\Action
  6. {
  7.  
  8.     public function execute()
  9.     {
  10.         $isPost = $this->getRequest()->getPost();
  11.  
  12.         if ($isPost)
  13.         {
  14.             $model = $this->_objectManager->create('Ns\Thorleif\Model\Commerciaux');
  15.             $id = $this->getRequest()->getParam('id');
  16.  
  17.             if ($id)
  18.             {
  19.                 $model->load($id);
  20.             }
  21.             $formData = $this->getRequest()->getParam('commerciaux');
  22.             $model->setData($formData);
  23.  
  24.             try
  25.             {
  26.                 $model->save();
  27.  
  28.                 // Display success message
  29.                 $this->messageManager->addSuccess(__('Commercial bien enregistré.'));
  30.  
  31.                 // Check if 'Save and Continue'
  32.                 if ($this->getRequest()->getParam('back'))
  33.                 {
  34.                     $this->_redirect('*/*/edit', ['id' => $model->getId(), '_current' => true]);
  35.                     return;
  36.                 }
  37.  
  38.                 $this->_redirect('*/*/'); // Retour à la liste
  39.                 return;
  40.             }
  41.             catch (\Exception $e)
  42.             {
  43.                 $this->messageManager->addError($e->getMessage());
  44.             }
  45.  
  46.             $this->_getSession()->setFormData($formData);
  47.             $this->_redirect('*/*/edit', ['id' => $id]);
  48.         }
  49.     }
  50. }
/app/code/Ns/Thorleif/Controller/Adminhtml/Index/Delete.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Controller\Adminhtml\Index;
  4.  
  5. class Delete extends \Magento\Backend\App\Action
  6. {
  7.  
  8.     public function execute()
  9.     {
  10.         $id = (int) $this->getRequest()->getParam('id');
  11.  
  12.         if ($id)
  13.         {
  14.             $model = $this->_objectManager->create('Ns\Thorleif\Model\Commerciaux');
  15.             $model->load($id);
  16.  
  17.             if (!$model->getId())
  18.             {
  19.                 $this->messageManager->addError(__('Le commercial n\'existe pas.'));
  20.             }
  21.             else
  22.             {
  23.                 try
  24.                 {
  25.                     $model->delete();
  26.                     $this->messageManager->addSuccess(__('Commercial bien supprimé.'));
  27.                     $this->_redirect('*/*/'); // Redirection vers la liste des commerciaux
  28.                     return;
  29.                 }
  30.                 catch (\Exception $e)
  31.                 {
  32.                     $this->messageManager->addError($e->getMessage());
  33.                     $this->_redirect('*/*/edit', ['id' => $model->getId()]);
  34.                 }
  35.             }
  36.         }
  37.     }
  38. }
/app/code/Ns/Thorleif/Controller/Adminhtml/Index/MassDelete.php
  1. <?php
  2.  
  3. namespace Ns\Thorleif\Controller\Adminhtml\Index;
  4.  
  5. class MassDelete extends \Magento\Backend\App\Action
  6. {
  7.     /**
  8.      * @return void
  9.      */
  10.     public function execute()
  11.     {
  12.         $ids = $this->getRequest()->getParam('commerciaux');
  13.  
  14.         foreach ($ids as $id)
  15.         {
  16.             try
  17.             {
  18.                 $model = $this->_objectManager->create('Ns\Thorleif\Model\Commerciaux');
  19.                 $model->load($id)->delete();
  20.             }
  21.             catch (\Exception $e)
  22.             {
  23.                 $this->messageManager->addError($e->getMessage());
  24.             }
  25.         }
  26.         if (count($ids))
  27.         {
  28.             $this->messageManager->addSuccess( __('%1 commerciaux ont été supprimés.', count($ids))
  29.             );
  30.         }
  31.         $this->_redirect('*/*/'); // Redirection vers le grid
  32.     }
  33. }

Tout est à présent terminé. Les trois derniers contrôleurs sont vraiment simples à comprendre si vous avez suivi les parties précédentes. A noter les redirections lors de la sauvegarde par rapport au type de sauvegarde ("Save" ou "Save and Continue"). Vous pouvez maintenant effectuer plusieurs tests pour voir que tout fonctionne bien : L'ajout d'un commercial, la modification des données de ce commercial, la suppression de celui-ci, ...