Back to Top

Magento 2: Collection List and Block

Updated 1 August 2024

Now that we have saved the form data in Magento, let’s create a list where customers can view all of his/her blogs.

Redirection and Messages

Earlier we displayed just a simple message saying “Saved” when the customer submitted the form. But it will be better to redirect to the list page after saving the data.

So we have to edit the Controller/Manage/Save.php file,

Updated code for Controller/Manage/Save.php file

<?php
namespace Webkul\BlogManager\Controller\Manage;

use Magento\Customer\Controller\AbstractAccount;
use Magento\Framework\App\Action\Context;
use Magento\Customer\Model\Session;

class Save extends AbstractAccount
{
    /**
     * @var \Webkul\BlogManager\Model\BlogFactory
     */
    protected $blogFactory;

    /**
     * @var Magento\Customer\Model\Session
     */
    protected $customerSession;

    /**
     * @var \Magento\Framework\Message\ManagerInterface
     */
    protected $messageManager;

    /**
     * Dependency Initilization
     *
     * @param Context $context
     * @param \Webkul\BlogManager\Model\BlogFactory $blogFactory
     */
    public function __construct(
        Context $context,
        \Webkul\BlogManager\Model\BlogFactory $blogFactory,
        Session $customerSession,
        \Magento\Framework\Message\ManagerInterface $messageManager
    ) {
        $this->blogFactory = $blogFactory;
        $this->customerSession = $customerSession;
        $this->messageManager = $messageManager;
        parent::__construct($context);
    }

    /**
     * Provides content
     *
     * @return \Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        $data = $this->getRequest()->getParams();
        $model = $this->blogFactory->create();
        $model->setData($data);

        $customer = $this->customerSession->getCustomer();
        $customerId = $customer->getId();
        $model->setUserId($customerId);

        $model->save();
        
        $this->messageManager->addSuccess(__('Blog saved successfully.'));
        return $this->resultRedirectFactory->create()->setPath('blog/manage');
    }
}

It’s a good practice to declare the member variables. So we declared them at the start of the class. To redirect we have used resultRedirectFactory and called the setPath method with the URL at which we want to redirect.

Searching for an experienced
Magento 2 Company ?
Find out More

As you may have noticed here we have given only two parts of the url that’s because it will autofill the missing part with “index”. So our URL will become blog/manage/index.

Now let’s talk about \Magento\Framework\Message\ManagerInterface class. This is used to show messages on the page. There are four types of messages available in Magento.
i) Success
ii) Error
iii) Notice
iv) Warning

2021-02-08_18-54-1

Also, notice that in the addSuccess method, we have passed the message enclosed in __(“”). All static text should be enclosed within __(‘some text’) so that it become translatable. Magento allows us to create translations for different languages with the help of a .csv file.

Now let’s create the index action in Contoller/Manage/Index.php which will be used to show the blogs list.

Code for Contoller/Manage/Index.php file

<?php
namespace Webkul\BlogManager\Controller\Manage;

use Magento\Customer\Controller\AbstractAccount;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;

class Index extends AbstractAccount
{
    /**
     * @var Magento\Framework\View\Result\PageFactory
     */
    protected $resultPageFactory;

    /**
     * Dependency Initilization
     *
     * @param Context $context
     * @param PageFactory $resultPageFactory
     */
    public function __construct(
        Context $context,
	    PageFactory $resultPageFactory
    ) {
	    $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }

    /**
     * Provides content
     *
     * @return \Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->set(__('Blogs'));
        $layout = $resultPage->getLayout();
        return $resultPage;
    }
}

Blocks

Here we will be showing a phtml file so we need to create a layout file as view/frontend/layout/blogmanager_manage_index.xml

Code for view/frontend/layout/blogmanager_manage_index.xml file

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="customer_account"/>
    <body>
        <referenceContainer name="content">
            <block class="Webkul\BlogManager\Block\BlogList" name="blogmanager.blog.list" template="Webkul_BlogManager::list.phtml" />
        </referenceContainer>
    </body>
</page>

Here everything should be familiar except the block class. Earlier we used the default block class for the Blog Add page but for the Blog List page, we will create a Block class Webkul\BlogManager\Block\BlogList.

Why do we need a block? The need for the block is to pass data to the template file. The block class contains the logical part of the view.

All the data needed by the template file should come from the block. We do not write complex code in the phtml file, instead, we write the complex codes in the block and pass the result to the phtml file.

Now let’s create the Block folder under the module directory. In the Block folder, we need to create the block file BlogList.php as

Code for Block/BlogList.php file

<?php
namespace Webkul\BlogManager\Block;

class BlogList extends \Magento\Framework\View\Element\Template
{
    /**
     * @var \Webkul\BlogManager\Model\ResourceModel\Blog\CollectionFactory
     */
    protected $blogCollection;

    /**
     * Dependency Initilization
     *
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param \Webkul\BlogManager\Model\ResourceModel\Blog\CollectionFactory $blogCollection
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Webkul\BlogManager\Model\ResourceModel\Blog\CollectionFactory $blogCollection,
        array $data = []
    ) {
        $this->blogCollection = $blogCollection;
        parent::__construct($context, $data);
    }

    /**
     * Get Blog List
     *
     * @return \Webkul\BlogManager\Model\ResourceModel\Blog\Collection
     */
    public function getBlogs()
    {
        $collection = $this->blogCollection->create();
        return $collection;
    }
}

All Blocks must extend the default block class \Magento\Framework\View\Element\Template. We will use this block to load the blog data.

Note here we are using the collection \Webkul\BlogManager\Model\ResourceModel\Blog\CollectionFactory because we need to load multiple rows from the table. Just like the model the model collection also has the factory class.

Here we have the getBlogs() method in which we are loading the collection and returning the whole collection. Just like the model factory here also we need to call the create() method to create a new object of the collection.

Now that we have created the block let’s create the list.phtml file for this block under the view/frontend/templates folder.

Code for view/frontend/templates/list.phtml file

<table>
    <tr>
        <th>
            <?= __("Id")?>
        </th>
        <th>
            <?= __("Title")?>
        </th>
        <th>
            <?= __("Content")?>
        </th>
    </tr>
    <?php
    $blogs = $block->getBlogs();

    foreach ($blogs as $blog) {?>
    <tr>
        <td>
            <?= $escaper->escapeHtml($blog->getId())?>
        </td>
        <td>
            <?= $escaper->escapeHtml($blog->getTitle())?>
        </td>
        <td>
            <?= substr($escaper->escapeHtml($blog->getContent()), 0, 20).'...'?>
        </td>
    </tr>
    <?php } ?>
</table>

The <?= ?> is nothing but a shorthand notation for <?php echo ?>. You can find it in the PHP manual. I have already told you about the __(“”), it’s used for translation and $escaper->escapeHtml() is used to remove any HTML content from the data.

Now see the important line $blogs = $block->getBlogs(); here we are calling the getBlogs() function of the block which will return the blogs collection.

Remember I told you that collection is a collection of models, so when we loop over the collection with a foreach loop then we will get a model in each iteration. That means in each iteration we will get a row from the table.

The $blog->getId() will return the entity_id which means it acts as getEntityId() that’s because in the model we have written this method,

2021-02-08_20-32

Just like the setters that we saw in the previous blog, the getters get internally managed, we just have to use the camelCase naming convention for each column.

So we can use getTitle(), and getContent() to access the title and content column respectively, even though we have not written these methods in the model file.

Now when you submit the add blog form you will be redirected to the blog list page with a success message like,

2021-02-08_17-51

Let’s create a customer navigation link for this page also, we have to edit view/frontend/layout/customer_account.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="customer_account_navigation">
            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-blog-add" after="-" >
                <arguments>
                    <argument name="label" xsi:type="string" translate="true">Add Blog</argument>
                    <argument name="path" xsi:type="string">blog/manage/add</argument>
                </arguments>
            </block>
            <block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-blog-list" before="customer-account-navigation-blog-add" >
                <arguments>
                    <argument name="label" xsi:type="string" translate="true">Blogs</argument>
                    <argument name="path" xsi:type="string">blog/manage</argument>
                </arguments>
            </block>
        </referenceBlock>
    </body>
</page>

Here in the block node, we have added before=”customer-account-navigation-blog-add” so it will add the blog list menu before the blog add menu. You will be able to see the Blogs link in the customer navigation,

2021-02-09_11-43

PS. We can get the collection from the model class also. When we call the $model->getCollection() it returns the collection of the model.

PS. Just like setData the model and collections have getData, which returns the data in associative array format. So during development or debugging when we have to view data, we use echo ‘<pre>; print_r($collection->getData()); die; which prints out the data in a nice viewable format.

Folder structure till now,

Selection_109

Next Blog -> Magento 2 Development 11: Filter and Sorting

Previous Blog -> Magento 2 Development 09: Form Validation and Saving Data

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home