Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the database class in Laravel use the "Singleton Pattern"?

I am new to Laravel. Does the Laravel create a database connection every time for each query of the program or use the same database object throughout the program using the "Singleton" Pattern? Does the strategy have an impact on performance, especially for Enterprise Level Applications?

like image 714
Mohit Verma Avatar asked Nov 28 '14 05:11

Mohit Verma


People also ask

Does Laravel use singleton?

The database layer of Laravel is also implemented using singletons. This means that there is only one database connection per request. This helps to keep the database layer of the application clean and easy to use.

Is DB connection singleton?

A DB connection should not normally be a Singleton. Two reasons: many DB drivers are not thread safe. Using a singleton means that if you have many threads, they will all share the same connection.

How is Singleton design pattern implemented in Laravel?

Digging around, I found that the typical way to implement the singleton pattern is to create a singleton trait (basically a Ruby module) that can be used by any class that wants to be a singleton. Most notably, the singleton trait implements the constructor and clone function as protected.

What is singleton method in Laravel?

The singleton method binds a class or interface into the service container so that Laravel can maintain dependency (when using an interface as the constructor parameter). (Actually Singleton is a design pattern. Singleton implementation always returns the same object on subsequent calls instead of a new instance).


1 Answers

Short answer

No, it's not a singleton, but a factory pattern. However the same connection will be reused if possible and you don't manually request it to reconnect. There is no performance hit.

Long answer

At the beginning of ever request lifecycle, in app/bootstrap/start.php an instance of Illuminate\Foundation\Application gets created. This servers as IoC container.

Shortly after creating the application all service providers will be loaded. The service providers are defined in app/config/app.php

'providers' => array(
    // ...
    'Illuminate\Database\DatabaseServiceProvider',
    // ...
),

Let's have a look at the Illuminate\Database\DatabaseServiceProvider shall we? The important part is the register function

$this->app->bindShared('db', function($app)
{
    return new DatabaseManager($app, $app['db.factory']);
});

An instance of DatabaseManager gets bound to db. This instance will stay the same over the whole request and will be used for every database request.

Example from "reverse" direction

Say you call

DB::table('users')->get();

First, the DB facade will resolve to the instance of DatabaseManager that gets bound in the DatabaseServiceProvider using bindShared('db')

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


Then the table('users') call gets forwarded because the method doesn't exist in Database Manager

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

It is called on the return value of $this->connection()

public function connection($name = null)
{
    list($name, $type) = $this->parseConnectionName($name);

    // If we haven't created this connection, we'll create it based on the config
    // provided in the application. Once we've created the connections we will
    // set the "fetch mode" for PDO which determines the query return types.
    if ( ! isset($this->connections[$name]))
    {
        $connection = $this->makeConnection($name);

        $this->setPdoForType($connection, $type);

        $this->connections[$name] = $this->prepare($connection);
    }

    return $this->connections[$name];
}

With if (!isset($this->connections[$name])) it will check if the connection already has been established and will only make a new connection if not.

Then it returns the connection and table('users')->get() will be executed.

like image 75
lukasgeiter Avatar answered Nov 15 '22 08:11

lukasgeiter