Creating a web route and controller to display data

In order to display data from your extension on the frontend (the public part of the website), the following is necessary:

  • A configured route
  • A controller handling the request
  • A layout file to specify what to show
  • The block class as specified in the layout file
  • A template file (optional)

How to do it…

Follow these steps to extend your module with a frontend web route and output data from a template file:

  1. Create a route in the frontend area:

    etc/frontend/routes.xml

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
      <router id="standard">
        <route id="sample" frontName="sample">
          <module name="Genmato_Sample" />
        </route>
      </router>
    </config>
  2. Create the controller that handles the request and renders the output:

    Controller/Index/Index.php

    <?php
    namespace GenmatoSampleControllerIndex;
    use MagentoFrameworkAppActionAction;
    
    class Index extends Action
    {
      /**
      * @var MagentoFrameworkViewResultPageFactory
      */
      protected $resultPageFactory;
    
      /**
      * @param MagentoFrameworkAppActionContext $context
      * @param MagentoFrameworkViewResultPageFactory resultPageFactory
      */
      public function __construct(
        MagentoFrameworkAppActionContext $context,
        MagentoFrameworkViewResultPageFactory $resultPageFactory
      )
      {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
      }
    
      /**
      * Renders Sample Index
      */
      public function execute()
      {
        return $this->resultPageFactory->create();
      }
    }
  3. Create the layout file to specify what to display:

    view/frontend/layout/sample_index_index.xml

    <?xml version="1.0"?>
    <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
      <head>
        <title>Sample DemoList</title>
      </head>
      <body>
        <referenceContainer name="content">
          <block class="GenmatoSampleBlockDemoList" name="demoList" template="Genmato_Sample::list.phtml" />
        </referenceContainer>
      </body>
    </page>
  4. In order to show the data, the Block class is called to render the template specified:

    Block/DemoList.php

    <?php
    namespace GenmatoSampleBlock;
    
    use MagentoFrameworkViewElementTemplate;
    use GenmatoSampleModelResourceModelDemoCollection as DemoCollection;
    use MagentoStoreModelScopeInterface;
    
    class DemoList extends Template
    {
      /**
      * Demo collection
      *
      * @var DemoCollection
      */
      protected $_demoCollection;
    
      /**
      * Demo resource model
      *
      * @var GenmatoSampleModelResourceModelDemoCollectionFactory
      */
      protected $_demoColFactory;
    
      /**
      * @param TemplateContext $context
      * @param GenmatoSampleModelResourceModelDemoCollectionFactory $collectionFactory
      * @param array $data
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
      public function __construct(
        TemplateContext $context,
        GenmatoSampleModelResourceModelDemoCollectionFactory $collectionFactory,
        array $data = []
      ) {
        $this->_demoColFactory = $collectionFactory;
        parent::__construct(
          $context,
          $data
        );
      }
    
      /**
      * Get Demo Items Collection
      * @return DemoCollection
      */
      public function getDemoItems()
      {
        if (null === $this->_demoCollection) {
          $this->_demoCollection = $this->_demoColFactory->create();
        }
        return $this->_demoCollection;
      }
    }
  5. In the template, the data collected in the Block class can be used to build the page:

    view/frontend/templates/list.phtml

    <table>
      <tr>
        <td>ID</td>
        <td>Title</td>
      </tr>
      <?php foreach($block->getDemoItems() as $item): ?>
      <tr>
        <td><?php echo $item->getId(); ?></td>
        <td><?php echo $item->getTitle();?></td>
      </tr>
      <?php endforeach; ?>
    </table>
  6. Refresh the cache to update the configuration:

    bin/magento cache:clean

    In your browser, open http://[your hostname]/sample/index/index/. This will result in the following page when you access the URL:

    How to do it…

Tip

If you have not set the deploy mode to developer, it is possible that the accessed URL will not render. If this is the case, you need to run the compile command:

bin/magento setup:di:compile

How it works…

When a request is received in the application, the path is evaluated and executed in the following order:

  1. A request is received by index.php.
  2. The index.php file creates a bootstrap:
    $bootstrap = MagentoFrameworkAppBootstrap::create(BP, $_SERVER);
  3. The bootstrap creates a new HTTP application:
    $app = $bootstrap->createApplication('MagentoFrameworkAppHttp');
  4. The bootstrap application is started:
    $bootstrap->run($app);
  5. In the run function of the bootstrap class, the created application is launched:
    $response = $application->launch();
  6. The application launch function will instantiate the frontcontroller and dispatch the request:
    $frontController = $this->_objectManager->get('MagentoFrameworkAppFrontControllerInterface');
    $result = $frontController->dispatch($this->_request);
  7. The frontcontroller loops through all the available configured controllers and checks whether there is a match. When a match is found, the controller is instantiated and the execute method is called:
    $result = $actionInstance->execute();
  8. This will evaluate the layout file for the route loaded and render the blocks that are specified there.

To activate a route on the frontend, it needs to be configured by specifying the first part of the URL. This first part maps the request to the extension that will handle the request.

Here, frontName (sample) is mapped to the extension, Genmato_Sample, allowing it to handle all requests on the frontend.

In order to handle the request to a URL, there needs to be a controller. In Magento 2, the controller now handles only one action (whereas Magento 1 has a controller that has the option to handle multiple actions). Every request consists of three parts:

[route]/[controller]/[action]

[route]: This is the configured frontName

[controller]: This is the path to identify the controller

[action]: This is the action that is executed (the PHP class)

In this case, a request is made to the following:

http://example.com/sample/

This will result with a request to the following:

http://example.com/sample/index/index

This will load the following file:

GenmatoSampleControllerIndexIndex.php

The executed controller relies on the layout file to render the page by including the specified blocks in the page. Just like the controllers, the layout files are now separate files per page handle. The name of the file is built in the same way as the controllers:

[route]_[controller]_[action].xml

This makes it easier to change a specific page handle in a theme.

The loaded Block class is the location to handle the collection of the data necessary to be shown in the template (just like in Magento 1). Here, we load the collection from the database so that it can be used in the template.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.183.210