Create a before plugin in Magento
Video Lesson: Create a before plugin in Magento
Before plugins can modify argument values passed to existing functions or carry out a task before it executes.
Published 2 weeks ago
Share with colleagues:
Lesson Content
Before plugins “intercept” functions. They can modify the argument values passed to existing functions, or carry out a task before the original function executes.
Let’s say we wanted to block registrations which occur from emails that contain specific domain names. We can easily do this with a plugin.
Our first step is to identify the function responsible for this action. After tracking the flow of the request, we’ll notice a createAccount()
function in the AccountManagementInterface
of the Customer module:
// ...
/**
* Create customer account. Perform necessary business operations like sending email.
*
* @param \Magento\Customer\Api\Data\CustomerInterface $customer
* @param string $password
* @param string $redirectUrl
* @return \Magento\Customer\Api\Data\CustomerInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function createAccount(
\Magento\Customer\Api\Data\CustomerInterface $customer,
$password = null,
$redirectUrl = ''
);
// ...
One of the restrictions of plugins is that they can only be created on public
functions. Luckily this is one, so we can hook into it and tap into the customer data to add our domain restriction to new registrations.
The common convention is to put all custom plugins in a Plugin
folder. Then, it’s typically a good idea to name your file and class after the action the plugin carries out. Let’s name it ValidateEmailDomain
.
We will then create a public
function with the original function name, createAccount
, then make the first letter uppercase and append before
. This makes the function name beforeCreateAccount()
.
The first argument in before
plugins is the original class or interface we are plugging into, so this will be AccountManagementInterface
. The common convention for this alias is $subject
. Next comes all of the arguments from the original function.
Finally, we will add in our logic to block registrations from specific domains. We’ll do this by comparing the customer’s email domain against an array of blocked domains.
<?php
declare(strict_types=1);
namespace Vendor\Module\Plugin;
use Magento\Customer\Api\AccountManagementInterface;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Framework\Exception\LocalizedException;
class ValidateEmailDomain
{
private array $blockedDomains = [
'xyz.com',
];
/**
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function beforeCreateAccount(
AccountManagementInterface $subject,
CustomerInterface $customer,
$password = null,
$redirectUrl = '',
): array {
$email = $customer->getEmail();
$domain = substr(strrchr($email, "@"), 1);
if (in_array($domain, $this->blockedDomains)) {
throw new LocalizedException(
__("Registration from this domain is not allowed.")
);
}
return [$customer, $password, $redirectUrl];
}
}
We then need to make sure that Magento knows about our plugin by registering it in the di.xml
file:
<?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\Customer\Api\AccountManagementInterface">
<plugin name="vendor_module_validate_email_domain" type="Vendor\Module\Plugin\ValidateEmailDomain"/>
</type>
</config>
After we flush the cache with bin/magento cache:flush
, we’re good to go!
Now when someone tries to register with an email address in the list of blocked domains, they'll see an error message instead of being able to create an account.