Magento 2 Development 09: Editing and Updating

0

 

Let’s give our users an option to edit their blogs.

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

<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>
<?= $blog->getId()?>
</td>
<td>
<?= $blog->getTitle()?>
</td>
<td>
<?= substr($blog->getContent(), 0, 20).'...'?>
</td>
<td>
<a href="<?= $block->getUrl('blog/manage/edit', ['id'=>$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


Edit page

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

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

<?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
{
public $resultPageFactory;
public $blogFactory;
public $customerSession;
public $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);
}
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 get the current customer id. We are collecting all of these to check if the current user is authorised user of the blog. Because if we do not do this check then any one can access any blog just be 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 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 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 another which makes 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 error message. Otherwise we will show the edit form.

Now let’s create the layout file view/frontend/layout/blogmanager_manage_edit.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">
<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 similar syntax for list page as well.

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

<?php
$blog = $block->getBlog();
?>
<div class="blog-container">
<form class="blog-form" method="post" action=<?php echo $block->getUrl('blog/manage/save'); ?> data-mage-init='{"validation": {}}'>
<input type="hidden" name="id" value="<?= $blog->getId()?>"/>
Title: <input type="text" name="title" class="required-entry" value="<?= $blog->getTitle(); ?>"/>
Content: <textarea name="content" class="required-entry validate-no-html-tags" rows="10"><?= $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 an 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

<?php
namespace Webkul\BlogManager\Block;
class Blog extends \Magento\Framework\View\Element\Template
{
public $blogFactory;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Webkul\BlogManager\Model\BlogFactory $blogFactory,
array $data = []
) {
$this->blogFactory = $blogFactory;
parent::__construct($context, $data);
}
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 how 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.

<?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
{
public $blogFactory;
public $customerSession;
public $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);
}
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 exist or not. If id exist 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 id field with inspect element feature.
To save the updated data we have loaded the model with load method and in that we have set the updated title and content with setTitle and setContent respectively. After that we have saved the model and added a success message, and in the end we have redirected to list page.

2021-02-16_19-47

Folder structure should look like,

2021-02-16_19-51


Post a Comment

0Comments
Post a Comment (0)
To Top