Magento 2 Development 06: Form Validation and Saving Data

0

 

Now that we have created a nice form let’s use it to save some data in the table.

Form Validation

Most probably you have used javascript or jquery for form validation. But magento provides various form validation techniques out of the box by extending the jQuery Validation library. Let’s modify our 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>

We have data-mage-init to initialise the validation on this form. And we have added required-entry class in each fields, which implies that this field is required. Also in the content field we have added “validate-no-html-tags” class which will check for html tags. Magento provides multiples ways to initialise the form validation and also multiple ways to add the validation rules, which you should explore on your own.

There are multiple rules present in Magento to validate email, number, url, etc. which will cover most of our need. You can find the most of the available validation rules in vendor/magento/magento2-base/lib/web/mage/validation.js

Now when we flush cache and reload the page and try to submit the form. You should see error message.


2021-02-08_13-37

During development we can disable some of the cache so that we do not have to flush cache every time we make changes. Disabling full page and block html cache will do the trick.

php bin/magento cache:disable full_page block_html

But please keep in mind to enable the cache when you are testing your module.

Saving Data

To save the form submitted data we need to create a new action. But before that let’s mention the form action in our form, 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>

Here we have mentioned the form submit type as post and the action. In the action attribute we have called getUrl method from block. The getUrl method takes the url i.e. frontName/controllerName/actionName and it will return full url by adding the base url. So that if we install this module in other website, we do not have to make any manual changes.

Let’s create the new action to save the data, Controller/Manage/Save.php action file,

<?php
namespace Webkul\BlogManager\Controller\Manage;
use Magento\Customer\Controller\AbstractAccount;
use Magento\Framework\App\Action\Context;
class Save extends AbstractAccount
{
public function __construct(
Context $context,
\Webkul\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';
}
}

The $this->getRequest()->getParams() is use to get the form data, which is similar to $_GET and $_POST.

Factory

Now let’s talk about \Webkul\BlogManager\Model\BlogFactory class a little bit. If you recall we created class with name Blog not BlogFactory, so how can we use this class if it’s not created? Remember generated/code folder which created when we run di compile command? Magento creates these factory classes for the Models (note that the factory classes are get created for models and collections only). You can find this BlogFactory class in generated/code/Webkul/BlogManager/Model/ folder after running the di compile command. Magento will not create these classes if it has not been used yet, that means you will not see the CommentFactory class there. This process of generating code automatically known as code generation. And the factories are part of Factory Design Pattern which one of the many design patterns that Magento usage.

Now we know how but why do we need these factory classes? and why it is required only for models and not other class?

Dependency Injection

When we create objects by passing in the constructor, it does not create a new object every time. It first checks if there is an object has been already created for that class, if an object is available then it will use that object otherwise it will create a shareable object. This whole process is known as Dependency Injection design pattern.

Back To Factory

If you recall the model class represents a single row in the table. So we do not want to share a single object for all rows. It will be ideal if we create new object for each row. That’s why we need factory classes for models and collections because these are related to data of the tables. The Factory class will ensure that we get new object every time we call the create() method.

Here we have created the new object for the model and assigned to $model. We can set data for each column by calling the set methods. These are called getter and setter which follows camelCase naming convention. Here we have called setTitle to set the title column and setContent to set the content column. Now to actually save this in the table, we need to call the save() method.

Now if you do di compile and submit the form, you will see the message “Saved” that we have printed at the end. And if you check the table you should see the new entry,

2021-02-08_15-27

We can also call setData method and pass an associative array instead of calling setter for each columns. The key for the associative array will be the column name of the table.

<?php
namespace Webkul\BlogManager\Controller\Manage;
use Magento\Customer\Controller\AbstractAccount;
use Magento\Framework\App\Action\Context;
class Save extends AbstractAccount
{
public function __construct(
Context $context,
\Webkul\BlogManager\Model\BlogFactory $blogFactory
) {
$this->blogFactory = $blogFactory;
parent::__construct($context);
}
public function execute()
{
$data = $this->getRequest()->getParams();
$model = $this->blogFactory->create();
$model->setData($data);
$model->save();
echo 'Saved';
}
}

Here $data is an associative array, you can verify it by printing it with print_r function of php.

In the user_id column we were suppose to insert the current customers id. We can get the logged in customer’s id from the customer session.

<?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 function __construct(
Context $context,
\Webkul\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->setData($data);
$customer = $this->customerSession->getCustomer();
$customerId = $customer->getId();
$model->setUserId($customerId);
$model->save();
echo 'Saved';
}
}

Here we have passed customer session class to get the logged in customer data. From customer session we have called getCustomer() which will return customer model for the current customer. And from that we can get the id by calling getId() . We have set the customer id in our model with setUserId method because our column name is user_id.

Now if you again submit the form, you might get some exception like below if you have not run di compile command,

2021-02-08_15-44

After compiling if we submit the form the user id will also be set in the table,

2021-02-08_15-53

Sessions

Magento have different types of session,
1. Magento\Backend\Model\Session– This session is used for Magento Admin.
2. Magento\Catalog\Model\Session– Catalog session is used for the frontend for product filters.
3. Magento\Checkout\Model\Session– Checkout session is used to store checkout related information.
4. Magento\Customer\Model\Session– Customer session is used for logged in customer.
It has few more sessions like Message Session, Persistent Data Session and Newsletter Session.

Please check out more blogs to know about factory design pattern and code generation and other design patterns.

Folder Structure till now,

2021-02-08_16-03

Post a Comment

0Comments
Post a Comment (0)
To Top