<

div class=”section” title=”The need for the Builder (Manager) pattern”>

<

div class=”titlepage”>

The Factory pattern

In this subsection, we’ll examine the Factory pattern and its usage in Laravel Framework. The Factory pattern is based on creating template method objects, which is based on defining the algorithm of a class in a subclass to implement an algorithm. There is a subclass, which is derived from a big superclass, in this pattern structure. The main class, which we may call a superclass, only holds major and generic logic; the subclasses are derived from this superclass. As a result, there may be more than one subclass inherited from this superclass, which are aimed at different purposes.

Unlike other design patterns used in Laravel, the Factory method is more customizable. For an extended subclass plus main class, you don’t need to set a new class, just a new operation. This method is beneficial if the class or its components usually change, or methods need to be overridden, much like initialization.

While creating a design, developers usually start with using the Factory pattern in their applications. Such a pattern is changed into an abstract Factory, Builder, or Prototype pattern. Unlike the Factory pattern, the Prototype pattern requires initialization once. Due to the pattern’s architecture, the methods of the Factory pattern (Factory methods) are usually called inside template methods.

There are some differences between the Factory pattern and the Abstract Factory or Prototype pattern. They are as follows:

<

div class=”itemizedlist”>

  • Unlike an Abstract Factory pattern, the Factory pattern can’t be implemented using the Prototype pattern.
  • Unlike the Prototype pattern, the Factory pattern doesn’t need an initialization, but it needs subclassing. This is an advantage when compared with other patterns. Thanks to this approach, the Factory pattern can return an injected subclass instead of an object.
  • Since the classes designed with the Factory pattern may return subclasses directly for other components, no other class or component needs to know and access the constructor methods. Due to this, it’s recommended that all constructor methods and variables should be protected or private.
  • There is another thing to take into consideration. As this pattern might return subclasses aimed for the exact need, it’s not recommended to make a new instance of the class using this pattern using the key new.

<

div class=”section” title=”The need for the Factory pattern”>

<

div class=”titlepage”>

The need for the Factory pattern

Laravel ships various types of validation rules with the Validation class. When we develop applications, we usually need to validate data as we proceed. To do this, a common approach is to set the validation rules in the Model and call them from the Controller. By “rules” here, we mean both validation type and its range.

Sometimes, we need to set custom rules and custom error messages to validate the data. Let’s examine how it works and how we are able to extend the Validation class to create custom rules. The Controller in the MVC pattern can also be described as a bridge between Model and View. This can best be explained with a live world example.

Let’s assume we have a news aggregation website. In the administration panel, an administrator tries to delete the news item. In the SOLID design pattern, this happens if an admin clicks on the Delete News button.

First, as an example to check, let’s open the vendor/Illuminate/Validation/Factory.phpfile, as shown in the following code:

<

div class=”informalexample”>

<?php namespace Illuminate\Validation;

use Closure;
use Illuminate\Container\Container;
use Symfony\Component\Translation\TranslatorInterface;

class Factory {


   protected $translator;

   protected $verifier;

   protected $container;

   protected $extensions = array();

   protected $implicitExtensions = array();

   protected $replacers = array();

   protected $fallbackMessages = array();

   protected $resolver;

   public function __construct(TranslatorInterface $translator, Container $container = null)
   {
      $this->container = $container;
      $this->translator = $translator;
   }


   public function make(array $data, array $rules, array $messages = array(), array $customAttributes = array())
   {

      $validator = $this->resolve($data, $rules, $messages, $customAttributes);

      if ( ! is_null($this->verifier))
      {
         $validator->setPresenceVerifier($this->verifier);
      }


      if ( ! is_null($this->container))
      {
         $validator->setContainer($this->container);
      }

      $this->addExtensions($validator);

      return $validator;
   }


      protected function addExtensions(Validator $validator)
   {
      $validator->addExtensions($this->extensions);

      $implicit = $this->implicitExtensions;

      $validator->addImplicitExtensions($implicit);

      $validator->addReplacers($this->replacers);

      $validator->setFallbackMessages($this->fallbackMessages);
   }


   protected function resolve(array $data, array $rules, array $messages, array $customAttributes)
   {
      if (is_null($this->resolver))
      {
         return new Validator($this->translator, $data, $rules, $messages, $customAttributes);
      }
      else
      {
         return call_user_func($this->resolver, $this->translator, $data, $rules, $messages, $customAttributes);
      }
   }

      public function extend($rule, $extension, $message = null)
   {
      $this->extensions[$rule] = $extension;

      if ($message) $this->fallbackMessages[snake_case($rule)] =  $message;
   }

   public function extendImplicit($rule, $extension, $message =  null)
   {
      $this->implicitExtensions[$rule] = $extension;

      if ($message) $this->fallbackMessages[snake_case($rule)] =  $message;
   }

   public function replacer($rule, $replacer)
   {
      $this->replacers[$rule] = $replacer;
   }

   public function resolver(Closure $resolver)
   {
      $this->resolver = $resolver;
   }

   public function getTranslator()
   {
      return $this->translator;
   }

   public function getPresenceVerifier()
   {
      return $this->verifier;
   }

   public function setPresenceVerifier(PresenceVerifierInterface $presenceVerifier
   {
      $this->verifier = $presenceVerifier;
   }

}

As we can see in the preceding code, the Validation Factory class is constructed with theTranslator class and an IoC container. The addExtensions() function is set after this. This method includes the user-defined extensions to a Validator instance, thus allowing us to write the template (structure) to create the Validator class’s extensions. The functions, which are public, allow us to implement the Translator class, and by this we mean that they allow us to write custom validation rules and messages. Refer to the following CarFactory diagram:

 

factory

<

div class=”mediaobject”>

In the preceding diagram, you can see that all cars are based on CarFactory (the basics of all cars), regardless of the brand. For all brands, the main process is the same (all cars have an engine, tires, brakes, bulbs, gear, and so on). You may want either a Suzuki car or a Toyota car, and depending on this choice, the SuzukiFactory or ToyotaFactory creates a Suzuki car or a Toyota car from theCarFactory.