现在,我们已经创建了一个不错的表单,让我们使用它来在表中保存一些数据。
Form Validation
您最有可能使用javascript或jquery进行表单验证。 但是magento通过扩展jQuery Validation库提供了各种开箱即用的表单验证技术。 让我们修改我们的phtml view / frontend / templates / add.phtml
<div class="blog-container">
<form class="blog-form" data-mage-init='{"validation": {}}'>
Title: <input type="text" name="title" class="required-entry"/>
Content: <textarea name="content" class="required-entry validate-no-html-tags"></textarea>
<button type="submit">Submit</button>
</form>
</div>

在开发过程中,我们可以禁用某些缓存,这样就不必在每次进行更改时都刷新缓存。 禁用整个 full page和Block html缓存将达到目的。
php bin/magento cache:disable full_page block_html
但是请记住在测试模块时启用缓存。
Saving Data
要保存表单提交的数据,我们需要创建一个新动作。 但在此之前,我们要先提及表单中的表单操作,即view / frontend / templates / add.phtml
<div class="blog-container">
<form class="blog-form" method="post" action= <?php echo $block->getUrl('blog/manage/save');?> data-mage-init='{"validation": {}}'>
Title: <input type="text" name="title" class="required-entry"/>
Content: <textarea name="content" class="required-entry validate-no-html-tags"></textarea>
<button type="submit">Submit</button>
</form>
</div>
在这里,我们提到了表单提交类型为post和action。 在action属性中,我们从block调用了getUrl方法。 getUrl方法采用网址,即frontName / controllerName / actionName,它将通过添加基本网址来返回完整的网址。 这样,如果我们在其他网站上安装此模块,则无需进行任何手动更改。
让我们创建一个新的操作来保存数据,Controller / Manage / Save.php操作文件,
<?php
namespace Yshuq\BlogManager\Controller\Manage;
use Magento\Customer\Controller\AbstractAccount;
use Magento\Framework\App\Action\Context;
class Save extends AbstractAccount
{
public function __construct(
Context $context,
\Yshuq\BlogManager\Model\BlogFactory $blogFactory
){
$this->blogFactory = $blogFactory;
parent::__construct($context);
}
public function execute()
{
$data = $this->getRequest()->getParams();
$model = $this->blogFactory->create();
$model->setTitle($data['title']);
$model->setContent($data['content']);
$model->save();
echo 'Saved';
}
}
$this->getRequest()->getParams()用于获取表单数据,类似于$ _GET和$ _POST。
Factory
现在让我们来谈谈\Yshuq \ BlogManager \ Model \ BlogFactory类。 如果您还记得我们创建了名为Blog而不是BlogFactory的类,那么如果未创建该类,我们该如何使用呢?还记得我们运行di compile命令时创建的generate / code文件夹吗? Magento为模型创建这些工厂类(请注意,仅为模型和集合创建工厂类)。 运行di compile命令后,可以在generate/code/Yshuq/BlogManager/Model /文件夹中找到此BlogFactory类。如果尚未使用,Magento将不会创建这些类,这意味着您将不会在此处看到CommentFactory类。 自动生成代码的过程称为code generation。 工厂是(Factory Design Pattern) 工厂设计模式的一部分,工厂设计模式是Magento使用的许多设计模式之一。
现在我们知道了,但是为什么我们需要这些工厂类? 为什么只有模型而不是其他类才需要?
Dependency Injection
当我们通过传入构造函数创建对象时,它不会每次都创建一个新对象。 它首先检查是否已经为该类创建了对象,如果有可用对象,则它将使用该对象,否则将创建可共享对象。 这整个过程称为(Dependency Injection)依赖注入设计模式。
Back To Factory
如果您还记得的话,模型类代表表中的一行。 因此,我们不想为所有行共享一个对象。 如果我们为每行创建一个新对象,那将是理想的选择。 这就是为什么我们需要模型和集合的工厂类,因为它们与表的数据有关。 Factory类将确保每次调用create()方法时都获得新对象。
在这里,我们为模型创建了新对象,并将其分配给$ model。 我们可以通过调用set方法来设置每一列的数据。 这些被称为getter和setter,它们遵循camelCase命名约定。 在这里,我们调用setTitle设置标题列,并调用setContent设置内容列。 现在要将其实际保存在表中,我们需要调用save()方法。
现在,如果您进行了编译并提交了表单,您将看到我们在结尾处打印的“已保存”消息。 如果您查看表格,您应该会看到新的条目,

我们还可以调用setData方法并传递一个关联数组,而不是为每个列调用setter。 关联数组的键将是表的列名。
<?php
namespace Yshuq\BlogManager\Controller\Manage;
use Magento\Customer\Controller\AbstractAccount;
use Magento\Framework\App\Action\Context;
class Save extends AbstractAccount
{
public function __construct(
Context $context,
\Yshuq\BlogManager\Model\BlogFactory $blogFactory
){
$this->blogFactory = $blogFactory;
parent::__construct($context);
}
public function execute()
{
$data = $this->getRequest()->getParams();
$model = $this->blogFactory->create();
//$model->setTitle($data['title']);
//$model->setContent($data['content']);
$model->setData($data);
$model->save();
echo 'Saved';
}
}
这里$ data是一个关联数组,您可以使用php的print_r函数进行打印来验证它。’
我们假设在user_id列中插入当前的客户ID。 我们可以从(session)客户会话中获取已登录的客户ID。
<?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 function __construct(
Context $context,
\Yshuq\BlogManager\Model\BlogFactory $blogFactory,
Session $customerSession
){
$this->blogFactory = $blogFactory;
$this->customerSession = $customerSession;
parent::__construct($context);
}
public function execute()
{
$data = $this->getRequest()->getParams();
$model = $this->blogFactory->create();
//$model->setTitle($data['title']);
//$model->setContent($data['content']);
$customer = $this->customerSession->getCustomer();
$customerId = $customer->getId();
$model->setUserId($customerId);
$model->setData($data);
$model->save();
echo 'Saved';
}
}
在这里,我们已经传递了客户会话类来获取已登录的客户数据。 在客户会话中,我们调用了getCustomer(),它将返回当前客户的客户模型。 然后我们可以通过调用getId()获得ID。 我们已使用setUserId方法在模型中设置了客户ID,因为我们的列名是user_id。
现在,如果您再次提交表单,那么如果您没有运行di compile命令,则可能会遇到类似下面的异常,

编译后,如果我们提交表单,则还将在表中设置用户ID,
Sessions
Magento有不同类型的会话.
- Magento\Backend\Model\Session– 他的会话用于Magento管理员
- Magento\Catalog\Model\Session–目录会话用于产品过滤器的前端。
- Magento\Checkout\Model\Session– Checkout会话用于存储与Checkout相关的信息。
- Magento\Customer\Model\Session– 客户会话用于登录的客户。
它还有更多的会话,例如消息会话,持久数据会话和新闻通讯会话。
请查看更多博客,以了解有关工厂设计模式和代码生成以及其他设计模式的信息。
到现在为止文件夹结构如下:
