Reading list Switch to dark mode

    Magento 2 Development 12: Editing and Updating

    Updated 6 March 2024

    Let’s give our users an option for editing and updating their blogs.

    First, we will edit the blogs page and add an edit link, let’s edit view/frontend/templates/list.phtml

    Updated code for view/frontend/templates/list.phtml file

    <table>
        <tr>
            <th>
                <?= __("Id")?>
            </th>
            <th>
                <?= __("Title")?>
            </th>
            <th>
                <?= __("Content")?>
            </th>
            <th>
                <?= __("Edit")?>
            </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>
            <td>
                <a href="<?= $escaper->escapeUrl($block->getUrl('blog/manage/edit', ['id'=>$escaper->escapeHtml($blog->getId())]))?>">
                    <?= __('Edit') ?>
                </a>
            </td>
        </tr>
        <?php } ?>
    </table>

    Here we are adding an edit column on the list page. You may have noticed that we are passing an associative array in the second param of the getUrl function. It gets appended to the URL as key-value pair (i.e. ?key=value) as in get requests.

    2021-02-16_16-46

    Here if you check the URL of the edit link you will find something like http://hostname/blog/manage/edit/id/203/ the id/203 is equivalent to ?id=203
    Anything after the frontName/controllerName/actionName is considered as key-value pair. That means we can think of the URL as http://hostname/frontName/controllerName/actionName/key1/value1/key2/value2

    Searching for an experienced
    Magento 2 Company ?
    Find out More

    Edit page

    Now we have to create the edit page. For that, we have to create a controller, layout file, template file, and block. Let’s create these files one by one.

    The controller file will be Controller/Manage/Edit.php

    Code for Controller/Manage/Edit.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;
    use Magento\Customer\Model\Session;
    
    class Edit extends AbstractAccount
    {
        /**
         * @var Magento\Framework\View\Result\PageFactory
         */
        protected $resultPageFactory;
    
        /**
         * @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 PageFactory $resultPageFactory
         * @param \Webkul\BlogManager\Model\BlogFactory $blogFactory
         * @param Session $customerSession
         * @param \Magento\Framework\Message\ManagerInterface $messageManager
         */
        public function __construct(
            Context $context,
    	    PageFactory $resultPageFactory,
            \Webkul\BlogManager\Model\BlogFactory $blogFactory,
            Session $customerSession,
            \Magento\Framework\Message\ManagerInterface $messageManager
        ) {
    	    $this->resultPageFactory = $resultPageFactory;
    	    $this->blogFactory = $blogFactory;
    	    $this->customerSession = $customerSession;
    	    $this->messageManager = $messageManager;
            parent::__construct($context);
        }
    
        /**
         * Provides content
         *
         * @return Magento\Framework\View\Result\Page
         * @return Magento\Framework\Controller\Result\Redirect
         */
        public function execute()
        {
            $blogId = $this->getRequest()->getParam('id');
            $customerId = $this->customerSession->getCustomerId();
            $isAuthorised = $this->blogFactory->create()
                                        ->getCollection()
                                        ->addFieldToFilter('user_id', $customerId)
                                        ->addFieldToFilter('entity_id', $blogId)
                                        ->getSize();
            if (!$isAuthorised) {
                $this->messageManager->addError(__('You are not authorised to edit this blog.'));
                return $this->resultRedirectFactory->create()->setPath('blog/manage');
            }
    
            $resultPage = $this->resultPageFactory->create();
            $resultPage->getConfig()->getTitle()->set(__('Edit Blog'));
            $layout = $resultPage->getLayout();
            return $resultPage;
        }
    }

    Here we have extracted the blog id from the get request then we have got the current customer id. We are collecting all of these to check if the current user is an authorized user of the blog. Because if we do not do this check then anyone can access any blog just by changing the id in the url.
    Here if you notice we are using the model factory and calling the getCollection method which will return the collection factory. And we are using two addFieldToFilter methods so these conditions will be combined with the AND operator. So the condition will look like “WHERE user_id=$customerId AND entity_id=$blogID“.

    We have already discussed all of these earlier also. But what is the getSize() method? The getSize will return the count, i.e. the number of rows or models in the collection. So the SQL query will be like select count(*)
    That means the actual query will be something like “SELECT COUNT(*) FROM blogmanager_blog WHERE user_id=$customerId AND entity_id=$blogID”
    As you can see here we can chain the methods one after the other which makes it easier to write complex queries.

    The $isAuthorised will contain the count, which will be zero if there is no such entry in the table. In that case, we have redirected the user to the list page with an error message. Otherwise, we will show the edit form.

    Now let’s create the layout file view/frontend/layout/blogmanager_manage_edit.xml

    Code for blogmanager_manage_edit.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\Blog" name="blogmanager.blog.edit" template="Webkul_BlogManager::edit.phtml" />
            </referenceContainer>
        </body>
    </page>

    There is nothing new here as we have seen a similar syntax for the list page as well.

    Now let’s create the template file view/frontend/templates/edit.phtml

    code for view/frontend/templates/edit.phtml file

    <?php
    $blog = $block->getBlog();
    ?>
    <div class="blog-container">
        <form class="blog-form" method="post" action=<?= $escaper->escapeUrl($block->getUrl('blog/manage/save')); ?> data-mage-init='{"validation": {}}'>
            <input type="hidden" name="id" value="<?= $escaper->escapeHtml($blog->getId())?>"/>
            Title: <input type="text" name="title" class="required-entry" value="<?= $escaper->escapeHtml($blog->getTitle()); ?>"/>
            Content: <textarea name="content" class="required-entry validate-no-html-tags" rows="10"><?= $escaper->escapeHtml($blog->getContent()); ?></textarea>
            <button type="submit">Submit</button>
        </form>
    </div>

    Here we are getting the blog data through the block class by calling the getBlog method. We are displaying the title and content in their respective input fields. One thing that you have to notice here is that we are using a hidden input field which will be used to pass the blog id along with the blog data when we submit the edited blog data.

    Now let’s create the block file, Block/Blog.php

    Code for Block/Blog.php file

    <?php
    namespace Webkul\BlogManager\Block;
    
    class Blog extends \Magento\Framework\View\Element\Template
    {
        /**
         * @var \Webkul\BlogManager\Model\BlogFactory
         */
        protected $blogFactory;
    
        /**
         * Dependency Initilization
         *
         * @param \Magento\Framework\View\Element\Template\Context $context
         * @param \Webkul\BlogManager\Model\BlogFactory $blogFactory
         * @param array $data
         */
        public function __construct(
            \Magento\Framework\View\Element\Template\Context $context,
            \Webkul\BlogManager\Model\BlogFactory $blogFactory,
            array $data = []
        ) {
            $this->blogFactory = $blogFactory;
            parent::__construct($context, $data);
        }
    
        /**
         * Get Blog
         *
         * @return \Webkul\BlogManager\Model\Blog
         */
        public function getBlog()
        {
            $blogId = $this->getRequest()->getParam('id');
            return $this->blogFactory->create()->load($blogId);
        }
    }

    Here we have loaded the blog model by the blog id by calling the load method and passing the blog id in the param because the id is the primary key. And we have returned the loaded model. Which we have used in the template file.

    Now let’s see what the edit page looks like,

    2021-02-16_18-07

    Updating Blog

    Instead of creating a new controller to submit the edit data, we will be modifying the Controller/Save.php which we used to save new blogs.

    Updated code for Controller/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
         * @param Session $customerSession
         * @param \Magento\Framework\Message\ManagerInterface $messageManager
         */
        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\Controller\Result\Redirect
         */
        public function execute()
        {
            $data = $this->getRequest()->getParams();
            $customerId = $this->customerSession->getCustomerId();
            if (isset($data['id']) && $data['id']) {
                $isAuthorised = $this->blogFactory->create()
                                            ->getCollection()
                                            ->addFieldToFilter('user_id', $customerId)
                                            ->addFieldToFilter('entity_id', $data['id'])
                                            ->getSize();
                if (!$isAuthorised) {
                    $this->messageManager->addError(__('You are not authorised to edit this blog.'));
                    return $this->resultRedirectFactory->create()->setPath('blog/manage');
                } else {
                    $model = $this->blogFactory->create()->load($data['id']);
                    $model->setTitle($data['title'])
                        ->setContent($data['content'])
                        ->save();
                    $this->messageManager->addSuccess(__('You have updated the blog successfully.'));
                }
            } else {
                $model = $this->blogFactory->create();
                $model->setData($data);
                $model->setUserId($customerId);
                $model->save();
                $this->messageManager->addSuccess(__('Blog saved successfully.'));
            }        
            return $this->resultRedirectFactory->create()->setPath('blog/manage');
        }
    }

    Here first we have checked whether the id field exists or not. If id already exists in the post data then the user is updating a blog otherwise s/he is creating a new blog. So we have put the previous code in the else section.
    Let’s focus on the if section, here we have again checked if it’s the right user because someone can change the id field with inspect element feature.
    To save the updated data we have loaded the model with the load method and in that, we have set the updated title and content with setTitle and setContent respectively. After that, we saved the model and added a success message, and in the end, we redirected to the list page.

    2021-02-16_19-47

    As we can see our blogs are editing and updating successfully.

    The folder structure should look like this,

    Selection_113
    Folder Structure

    Next Blog -> Magento 2 Development 13: Deleting

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

    . . .

    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