Brief Overview Of Design Patterns Used in Laravel

In this article , we will discuss the design patterns Laravel uses, and how and why are they used, using some realife Examples . we have divided article To 6 chapters to give you a Brief Overview Of Design Patterns Used in Laravel .

  1. Builder pattern
  2. Factory pattern
  3. Repository pattern
  4. Strategy pattern
  5. Provider pattern
  6. Facade Pattern

The Builder pattern

This design pattern aims to gain simpler, reusable objects. Its goal is to separate bigger and more convoluted object construction layers from the rest so that the separated layers can be used in different layers of the application.

The need for the Builder pattern

In Laravel, the AuthManager class needs to create some secure elements to reuse with selected auth storage drivers such as cookie, session, or custom elements. To achieve this, the AuthManager class needs to use storage functions such as callCustomCreator() and getDrivers() from theManager class.

Let’s see how the Builder (Manager) pattern is used in Laravel. To see what happens in this pattern, navigate to the vendor/Illuminate/Support/Manager.php andvendor/Illuminate/Auth/AuthManager.php files, as shown in the following code:

   public function driver($driver = null)
   {
      ...

   }

   protected function createDriver($driver)
   {
      $method = 'create'.ucfirst($driver).'Driver';

      ...
   }

   protected function callCustomCreator($driver)
   {
      return $this->customCreators[$driver]($this->app);
   }

   public function extend($driver, Closure $callback)
   {
      $this->customCreators[$driver] = $callback;

      return $this;
   }
   public function getDrivers()
   {
      return $this->drivers;
   }

 public function __call($method, $parameters)
   {
      return call_user_func_array(array($this->driver(), $method), $parameters);
   }

Now, navigate to the /vendor/Illuminate/Auth/AuthManager.php file, as shown in the following code:

   protected function createDriver($driver)
   {

     ....
   }

   protected function callCustomCreator($driver)
   {


   }

   public function createDatabaseDriver()
   {


   }

   protected function createDatabaseProvider()
   {

      ....
   }


   public function createEloquentDriver()
   {
      ...

   }

   protected function createEloquentProvider()
   {
      ...

   }

   public function getDefaultDriver()
   {
      ...
   }

   public function setDefaultDriver($name)
   {
      ...
   }

As we can see in the preceding code, the AuthManager class extends from the Manager class. Laravel ships with a basic auth mechanism. So, we need to store auth credentials in a database. First, the class checks our default database configuration with the AuthManager::setDefaultDriver()function. This function actually uses the Manager class for eloquent operations. All the database and auth options (such as cookie name) are obtained from the application’s config file, except the auth model table name.

To understand this Builder (Manager) pattern better, we can take the following presentation as an example:

 

 

In the preceding example diagram, we assumed that we want to fetch data, for example, pizza, from the previous illustration. The client ordered two pizzas: an Asian pizza and/or a Chinese pizza. This pizza is requested through the Waiter class. The PizzaBuilder class (which is the Manager class, in our case) made a pizza according to the AuthRequest request, in our case, and delivered the pizza through the waiter.Also, you can navigate to vendor/Illuminate/Session/SessionManage.php and check for the use of this pattern in Laravel Framework.

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:

  • 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.

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:

<?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:

 

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.

The Repository pattern

The Repository pattern is usually used to create an interface between two distinct layers of an application. In our case, the developers of Laravel use this pattern to create an abstract layer betweenNamespaceItemResolver (the class that resolves the namespaces and understands which file is in which namespace) and Loader (a class that requires and loads another class into the application). The Loader class simply loads the given namespace’s configuration group. As you might know, nearly all of the Laravel Framework code is developed using namespaces.

The need for the Repository pattern

Let’s assume you’re trying to fetch a product from your database using Eloquent ORM. The method will be something like Product::find(1) in your Controller. For abstraction purposes, this approach is not ideal. If you now put a code such as this, your Controller knows you’re using Eloquent, which ideally shouldn’t happen in a good and abstracted structure. If you want to contain the changes done to the database scheme so that the calls outside of the class do not reference to the fields directly but through a repository, you have to dig all codes one by one.

Now, let’s create an imaginart repository interface (a list of methods that will be used in the pattern) for the users. Let’s call it UserRepository.php:

<?php namespace Arda\Storage\User;
 
interface UserRepository {
   
   public function all();

   public function get();

   public function create($input);

   public function update($input);

   public function delete($input);

   public function find($id);

}

Here, you can see that all the methods’ names used in the Model are declared one by one. Now, let’s create the repository and name it EloquentUserRepository.php:

<?php namespace Arda\Storage\User;
 
use User;
 
class EloquentUserRepository implements UserRepository {
 
  public function all()
  {
    return User::all();
  }
 
  public function get()
  {
    return User::get();
  }
 
  public function create($input)
  {
    return User::create($input);
  }

  public function update($input)
  {
    return User::update($input);
  }

  public function delete($input)
  {
    return User::delete($input);
  }

  public function find($input)
  {
    return User::find($input);
  }
 
}

As you can see, this repository class implemented our UserRepository that we created earlier. Now, you need to bind the two so that when the UserRepositoryInterface interface is called, we actually acquire EloquentUserRepository.

This can be done either with a service provider or by a simple command, such as the following, in Laravel:

App:bind(
   'Arda\Storage\User\UserRepository',
   'Arda\Storage\User\EloquentUserRepository'
);

Now, in your Controllers, you can simply use the repositories as Use Arda\Storage\User\UserRepository as User.

Every time the controller uses a User::find($id) code, it first goes to the interface, and then goes to the binded repository, which is the Eloquent repository in our case. Through this, it goes to the Eloquent ORM. This way, it’s impossible for the Controller to know how the data is fetched.

The Strategy pattern

The best approach to describe the Strategy pattern is through a problem.

The need for the Strategy pattern

In this design pattern, the logic is extracted from complex classes into easier components so that they can be replaced easily with simpler methods. For example, you want to show popular blog posts on your website. In a classic approach, you will calculate the popularity, make the pagination, and list the items relative to the current paginated offset and popularity, and make all calculations in a simple class. This pattern aims to separate each algorithm into separate components so that they can be reused or combined in other parts of the application easily. This approach also brings flexibility and makes it easy to change an algorithm system wide.

To understand this better, let’s take a look at the following loader interface located atvendor/Illuminate/Config/LoaderInterface:

<?php namespace Illuminate\Config;

interface LoaderInterface {

   public function load($environment, $group, $namespace = null);

   public function exists($group, $namespace = null);

    public function addNamespace($namespace, $hint);

   public function getNamespaces();

   public function cascadePackage($environment, $package, $group, $items);

}

When we dig the code, the LoaderInterface works will follow a certain structure. ThegetNamespaces() function loads all namespaces defined in the app\config\app.php file. TheaddNamespace() method passes the namespaces to the load() function as grouped. If theexist() function returns true, there is at least one configuration group that belongs to a given namespace. For the full structure, you can refer to the repository section of this chapter. As a result, you can easily call the method that you need through an interface of the Loader class to load various configuration options. If we download a package through the composer, or implement a package to an application that is being authored, the pattern makes all of them available and loads them from their own namespaces without any conflicts, though they are inside different namespaces or have the same filenames.

The Provider pattern

The Provider pattern was formulated by Microsoft for use in the ASP.NET Starter Kits and formalized in .NET Version 2.0 (http://en.wikipedia.org/wiki/Provider_model). It is a mid layer between an API class and the Business Logic/Data Abstraction Layer of the application. The provider is the implementation of the API separated from the API itself.

This pattern, its aims, and its usage are quite similar to the Strategy pattern. This is why many developers are already discussing whether to accept this approach as a design pattern.

To understand these patterns better, let’s openvendor/Illuminate/Auth/AuthServiceProvider.php andvendor/Illuminate/Hashing/HashServiceProvider.php:

<?php namespace Illuminate\Auth;

use Illuminate\Support\ServiceProvider;

class AuthServiceProvider extends ServiceProvider {

   protected $defer = true;

   public function register()
   {
      $this->app->bindShared('auth', function($app)
      {
           // Once the authentication service has actually been requested by the developer
          // we will set a variable in the application indicating this, which helps us
          // to know that we need to set any queued cookies in the after event later.
         $app['auth.loaded'] = true;

          return new AuthManager($app);
      });
   }

   public function provides()
   {
      return array('auth');
   }

}


<?php namespace Illuminate\Hashing;

use Illuminate\Support\ServiceProvider;

class HashServiceProvider extends ServiceProvider {

   protected $defer = true;

   public function register()
   {
      $this->app->bindShared('hash', function() { return new BcryptHasher; });
   }

   public function provides()
   {
      return array('hash');
   }

}

As you can see, both the classes extend ServiceProvider. The AuthServiceProvider class allows us to provide all services to AuthManager when an authentication request, such as checking whether a cookie and session is created or whether the content is invalid, is sent. After the authentication service has been requested, the developer can define whether a session or cookie is set through the response through AuthDriver.

However, HashServiceProvider provides us with the related methods when a secure hash request is done so that we can use, fetch, check, or do other things with these hashes. Both providers return the values as an array.

The Facade pattern

The Facade (façade) pattern allows a developer to unite various complicated interfaces into a single class interface. This pattern also allows you to wrap various methods from various classes into a single structure.

In Laravel 4, as you may already know, almost every method looks like a static method, for example,Input::has(), Config::get(), URL::route(), View::make(), and HTML::style(). However, they are not static methods. If they were static methods, it would be quite hard to make tests for them all. They are actually the mimics of this behavior. In the background, with the help of the IoC Container (a way to inject dependencies into a class), Laravel actually calls another class(es) through a Facade class. The Facade base class benefits from PHP’s own __callStatic() magic method to call the required methods, such as static methods.For example, let’s assume we have a method called URL::to('home'). Let’s check what the URL is and what it refers to. First, let’s open app/config/app.php. In the aliases array, there is a line like the following:

'URL' => 'Illuminate\Support\Facades\URL',

So, if we call URL::to('home'), we actually call Illuminate\Support\Facades \URL::to('home').

Now, let’s check what’s inside the file. Open thevendor/Illuminate/Support/Facades/URL.php file:

<?php namespace Illuminate\Support\Facades;

class URL extends Facade {


   protected static function getFacadeAccessor() { return 'url'; }

}

As you can see, the class actually extends from the Facade class, and there is no static method calledto(). Instead, there is a method called getFacadeAccessor(), which returns the string url. ThegetFacadeAccessor() method’s purpose is to define what to inject. This way, Laravel understands that this class is looking for $app['url'].

This is defined in vendor/Illuminate/Routing/RoutingServiceProvider.php, as follows:

protected function registerUrlGenerator()
{
   $this->app['url'] = $this->app->share(function($app)
      {

      $routes = $app['router']->getRoutes();

      return new UrlGenerator($routes, $app->rebinding('request', function($app, $request)
      {
         $app['url']->setRequest($request);
      }));
   });
}

As you can see, it returns a new instance of the UrlGenerator class in the same namespace, which holds the to() method we’re looking for:

//Illuminate/Routing/UrlGenerator.php
public function to($path, $extra = array(), $secure = null)
{
   //...
}

So each time you use a method like this, Laravel first goes to and checks the facade, it then checks what’s injected through, and then the real method through the injected class is called.

Wrapping up

In this article , we learned about various design pattern uses in the Laravel PHP framework, how and why they are used, and what problems they can solve.

Deven Rathore

Deven is an Entrepreneur, and Full-stack developer, Constantly learning and experiencing new things. He currently runs CodeSource.io and Dunebook.com.

Published by
Deven Rathore

Recent Posts

3 Ways to Get the Most Out of Your University’s Virtual Computer Lab

IT is more important than ever in the world of higher education, and yet with…

20 hours ago

Top Tips for Learning Java Programming

If you’re here for the top tips, we assume you’re ahead of the “how to…

1 day ago

Neural Networks for Creating Blog Texts

The world is progressing at unprecedented rates at the current moment, especially in terms of…

2 days ago

Top 20 Opensource Python Tkinter Projects

This article will highlight the Top 20 Opensource Python Tkinter Projects which we believe will…

4 days ago

Beginners guide to Sneaker Proxies

With their numerous applications in streamlining the data flow, securing both the servers and the…

1 week ago

Top 20 Node.js dashboard templates

In this article, We will be looking at some of the top Node.js dashboard templates.…

1 week ago