Magento2 Editing and Updating

让我们为用户提供一个编辑博客的选项。

首先,我们将编辑博客页面和一个编辑链接,让我们编辑 view / frontend / templates / list.phtml

<table>
    <tr>
        <th>
            <?= __("Id")?>
        </th>
        <th>
            <?= __("Title")?>
        </th>
        <th>
            <?= __("Content")?>
        </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>

在这里,我们在列表页面上添加了一个编辑列。 您可能已经注意到,我们在getUrl函数的第二个参数中传递了一个关联数组。 像在get请求中一样,将其作为键值对(即?key = value)附加到URL。

在这里,如果您检查编辑链接的网址,您会发现类似http:// hostname / blog / manage / edit / id / 203 /的id / 203等于?id = 203

frontName / controllerName / actionName之后的任何内容均视为键值对。 这意味着我们可以将网址视为http:// hostname / frontName / controllerName / actionName / key1 / value1 / key2 / value2

Edit page

现在我们必须创建编辑页面。 为此,我们必须创建控制器,布局文件,模板文件和块。 让我们一一创建这些文件。

控制器文件将为Controller / Manage / Edit.php

<?php

namespace Yshuq\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,
        \Yshuq\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()
    {
        // TODO: Implement execute() method.
        $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;
    }

}

在这里,我们从获取请求中提取了博客ID,然后获得了当前客户ID。 我们正在收集所有这些信息,以检查当前用户是否是博客的授权用户。 因为如果我们不执行此检查,那么任何人都可以访问任何博客,而只需更改url中的ID。

在这里,如果您注意到我们正在使用模型工厂并调用getCollection方法,该方法将返回收集工厂。 而且我们使用了两个addFieldToFilter方法,因此这些条件将与AND运算符结合在一起。 因此条件将看起来像“ WHERE user_id = $ customerId AND entity_id = $ blogID”。

我们前面也已经讨论了所有这些。 但是什么是getSize()方法? getSize将返回计数,即集合中的行数或模型数。 因此,SQL查询将类似于select count(*)

这意味着实际的查询将类似于“从blogmanager_blog中的SELECT COUNT(*),其中user_id = $ customerId和entity_id = $ blogID”

如您在这里看到的,我们可以将方法一个接一个地链接,这使得编写复杂的查询变得更加容易。

$ isAuthorised将包含计数,如果表中没有此类条目,则计数将为零。 在这种情况下,我们已将用户重定向到带有错误消息的列表页面。 否则,我们将显示编辑表单。

现在,让我们创建布局文件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="Yshuq\BlogManager\Block\Blog" name="blogmanager.blog.edit" template="Yshuq_BlogManager::edit.phtml" />
        </referenceContainer>
    </body>
</page>

这里没有新内容,因为我们也看到了列表页面的类似语法。

现在,让我们创建模板文件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>

在这里,我们通过调用getBlog方法通过block类获取博客数据。 我们正在其各自的输入字段中显示标题和内容。 您在这里需要注意的一件事是,我们使用了一个隐藏的输入字段,当我们提交编辑的博客数据时,该字段将用于传递博客ID和博客数据。

现在,让我们创建一个Block文件Block / Blog.php

<?php
namespace Yshuq\BlogManager\Block;

class Blog extends \Magento\Framework\View\Element\Template
{
    public $blogFactory;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Yshuq\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);
    }
}

在这里,我们通过调用load方法并通过在参数中传递博客ID来通过博客ID加载博客模型,因为ID是主键。 我们已经返回了加载的模型。 我们已经在模板文件中使用过。

现在,让我们来看看编辑页面的外观,

编辑修界面

Updating Blog

我们将修改用于保存新博客的Controller / Save.php,而不是创建一个新的控制器来提交编辑数据。

<?php
namespace Yshuq\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,
 		\Yshuq\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');
 	}
}

在这里,我们首先检查id字段是否存在。 如果帖子数据中存在id,则用户正在更新博客,否则将在创建新博客。 因此,我们已将之前的代码放在了else部分中。

让我们集中讨论if部分,在这里我们再次检查了它是否是正确的用户,因为有人可以使用inspect element功能更改id字段。

为了保存更新的数据,我们使用load方法加载了模型,并通过setTitle和setContent分别设置了更新的标题和内容。 之后,我们保存了模型并添加了成功消息,最后,我们已重定向到列表页面。

修改保存后

文件夹结构应该是什么样,