Magento – Add email field to Review Form – Magento 2

formsmagento-2.1review

Working with Magento 2.1. I've hit a bit of a bump in adding a field to the review form.

These are the only requirements. An email address field added to the review form. Once the review is submitted, the email address is saved with the review. The email address is displayed ONLY with the review on the admin. Reviews can be searched in the admin by email address.

I found this question: Adding custom fields to review form but is Magento 1 and seems to go off on attaching the email to an order(?).

I listed all of the requirements, but I can't expect anyone to address each of them. I understand that, but I'm at a bit of a loss, and appreciate any help that can be given.

Best Answer

Seeing as how there's no clear answer on this yet, this might help some people. To add an e-mail field (or any other field) to the frontend review form and display it in the admin we have to create a custom module.

With this module we'll:

  1. Create a custom field in the database
  2. Save data
  3. Display in the admin

NOTE: Be sure to replace "Vendor" with your desired vendor name.

app\code\Vendor\ReviewEmail\registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_ReviewEmail',
    __DIR__
);

app\code\Vendor\ReviewEmail\etc\module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_ReviewEmail" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Review" />
        </sequence>
    </module>
</config>

app\code\Vendor\ReviewEmail\etc\di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <type name="Magento\Review\Block\Adminhtml\Edit\Form">
        <plugin name="modify_review_edit_form" type="Vendor\ReviewEmail\Plugin\Magento\Review\Block\Adminhtml\Edit\Form" />
    </type>    

</config>

app\code\Vendor\ReviewEmail\etc\events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">

    <event name='review_save_after'>
        <observer name='vendor_reviewemail_save_after' instance='Vendor\ReviewEmail\Model\Observer\ReviewSave'/>
    </event>    

</config>

app\code\Vendor\ReviewEmail\Setup\InstallSchema.php

<?php
namespace Vendor\ReviewEmail\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallSchema implements InstallSchemaInterface
{
    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;

        $installer->startSetup();

        $installer->getConnection()->addColumn(
            $installer->getTable('review_detail'),
            'email',
            [
                'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                'length' => 255,
                'nullable' => true,
                'comment' => 'Email address'
            ]
        );

        $setup->endSetup();

    }
}

app\code\Vendor\ReviewEmail\Model\Observer\ReviewSave.php

<?php

namespace Vendor\ReviewEmail\Model\Observer;

use Magento\Framework\Event\ObserverInterface;

class ReviewSave implements ObserverInterface
{
    public function __construct(
        \Magento\Framework\App\ResourceConnection $resource
    ) {
        $this->_resource = $resource;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $review = $observer->getEvent()->getDataObject();
        $connection = $this->_resource;

        $tableName = $connection->getTableName('review_detail');
        $detail = [
            'email' => $review->getEmail(),
        ];

        if (empty($review->getEmail())) return;

        $select = $connection->getConnection()->select()->from($tableName)->where('review_id = :review_id');
        $detailId = $connection->getConnection()->fetchOne($select, [':review_id' => $review->getId()]);

        if ($detailId) {
            $condition = ["detail_id = ?" => $detailId];
            $connection->getConnection()->update($tableName, $detail, $condition);
        } else {
            $detail['store_id'] = $review->getStoreId();
            $detail['customer_id'] = $review->getCustomerId();
            $detail['review_id'] = $review->getId();
            $connection->getConnection()->insert($tableName, $detail);
        }   
    }
}

app\code\Vendor\ReviewEmail\Plugin\Magento\Review\Block\Adminhtml\Edit\Form.php

<?php

namespace Vendor\ReviewEmail\Plugin\Magento\Review\Block\Adminhtml\Edit;

class Form extends \Magento\Review\Block\Adminhtml\Edit\Form
{
    public function beforeSetForm(\Magento\Review\Block\Adminhtml\Edit\Form $object, $form) {

        $review = $object->_coreRegistry->registry('review_data');

        $fieldset = $form->addFieldset(
            'review_details_extra',
            ['legend' => __('Review Details Extra Data'), 'class' => 'fieldset-wide']
        );

        $fieldset->addField(
            'email',
            'text',
            ['label' => __('E-mail'), 'required' => false, 'name' => 'email']
        );

        $form->setValues($review->getData());

        return [$form];
    }
}

app\code\Vendor\ReviewEmail\view\adminhtml\ui_component\review_listing.xml (Optional, only if you want to show the field in the admin grid as well)

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="review_columns">
        <column name="email">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">E-mail</item>
                    <item name="sortOrder" xsi:type="number">45</item>
                    <item name="truncate" xsi:type="number">50</item>
                    <item name="nl2br" xsi:type="boolean">true</item>
                    <item name="escape" xsi:type="boolean">true</item>
                </item>
            </argument>
        </column>
    </columns>
</listing>

After this all we have left to do is add the field to the review form. In app\design\frontend\Vendor\yourtheme\Magento_Review\templates\form.phtml

<input type="text" name="email" id="email_field" class="block mb2 full-width validate-email" data-validate="{required:true}"/>

Make sure to add this between the form tags.

After installing the module and clearing your caches you should now have an e-mail field in your review form. Which should be visible in the admin grid and admin review detail view.