Override Drupal 8 core services

Problem

I need to override the email validation service so that we can use a custom validation .

Solution

There are a few step to follow for this solution. Find the service that provides the validation service

  1. Find the service and the file 
    • There are a couple of ways to find the service
      1. GOTO https://api.drupal.org/api/drupal/services and just serach for it
      2. Use Drupal console 

        drupal debug:container | grep email

      3. Or even just search the code using an IDE
    • In this case the file is `core/lib/Drupal/Component/Utility/EmailValidator.php` the service name is or service ID is 
      email.validator
  2. Tell Drupal you are replacing it with another service
    • Create a custom module (other_examples is my module name) and then create a src folder if you don't have one already
    • Create a ServiceProvider class. The important thing to note here is the name of the file. It should be your module name in camel case followed by ServiceProvider . In this example it will be  OtherExamplesServiceProvider.php. Drupal looks for a file with this naming convention when the module is enabled. If it finds this file, Drupal then knows that you intend to override a service.
    • The class name here is also the same (OtherExamplesServiceProvider). The class needs to extend ServiceProviderBase and implement ServiceProviderInterface.
      <?php
      
      namespace Drupal\other_examples;
      
      use Drupal\Core\DependencyInjection\ContainerBuilder;
      use Drupal\Core\DependencyInjection\ServiceProviderBase;
      use Drupal\Core\DependencyInjection\ServiceProviderInterface;
      
      class OtherExamplesServiceProvider extends  ServiceProviderBase implements  ServiceProviderInterface {
      
        public function alter(ContainerBuilder $container) {
          $current_service_def = $container->getDefinition('email.validator');
          $current_service_def->setClass("Drupal\other_examples\Utility\OtherEmailValidator");
        }
      
      }
      
    •  
  3. Implement the custom replacement service class
    • Since we are overriding a already existing service we don't need a modulename.services.yml file and tell Drupal about our service
    • A best way here is to copy the original file and edit it.
      <?php
      
      namespace Drupal\other_examples\Utility;
      
      use Egulias\EmailValidator\EmailValidator as EmailValidatorUtility;
      use Egulias\EmailValidator\Validation\EmailValidation;
      
      /**
       * Validates email addresses.
       */
      class OtherEmailValidator extends EmailValidatorUtility implements EmailValidatorInterface {
      
        /**
         * Validates an email address.
         *
         * @param string $email
         *   A string containing an email address.
         * @param \Egulias\EmailValidator\Validation\EmailValidation|null $email_validation
         *   This argument is ignored. If it is supplied an error will be triggered.
         *   See https://www.drupal.org/node/2997196.
         *
         * @return bool
         *   TRUE if the address is valid.
         */
        public function isValid($email, EmailValidation $email_validation = NULL) {
          
          //TODO your code to validate the email
          return TRUE;
        }
      
      }
    • Clear the cache and see your implementation in action