Advertisement
  1. Code
  2. Web Development

Laravel Unwrapped: sesión, autenticación y caché

Scroll to top
Read Time: 21 min

() translation by (you can also view the original English article)

En los últimos años, Laravel se ha convertido en uno de los frameworks de software más destacados que utilizan los ingenieros de software para la creación de sus aplicaciones web. Similar a la popularidad de la que gozó CodeIgniter en su apogeo, Laravel ha sido elogiada por su facilidad de uso, amabilidad para los principiantes y su adherencia a los estándares de la industria.

Introducción

Sin embargo, una cosa que no muchos programadores aprovechan es el sistema basado en componentes de Laravel. Desde su conversión a componentes impulsados por compositores, Laravel 4 se ha convertido en un sistema muy modular, similar a la verbosidad de frameworks más maduros como Symfony. Esto se llama el grupo de componentes Illuminate, que en mi opinión, no es el framework real en sí, sino una compilación de bibliotecas que un framework puede usar potencialmente. El framework real de Laravel está representado por la aplicación de esqueleto de Laravel (que se encuentra en el repositorio de GitHub laravel/laravel) que hace uso de estos componentes para crear una aplicación web.

En este tutorial, nos sumergiremos en un grupo de estos componentes, aprenderemos cómo funcionan, cómo los utiliza el framework y cómo podemos ampliar su funcionalidad.

El componente Session

El componente Session de Laravel maneja las sesiones de la aplicación web. Hace uso de un sistema basado en controladores llamado Laravel Manager, que actúa como una fábrica y un contenedor para cualquier controlador que se establezca en el archivo de configuración. A partir de esta escritura, el componente Session tiene controladores para:

  • file: un controlador de sesión basado en archivos donde los datos de sesión se guardan en un archivo cifrado.
  • cookie: un controlador de sesión basado en cookies donde los datos de la sesión están encriptados en las cookies del usuario.
  • database: los datos de sesión se guardan en la base de datos configurada para la aplicación.
  • apc: los datos de la sesión se guardan en APC.
  • memcached: los datos de la sesión se guardan en Memcached.
  • redis: los datos de la sesión se guardan en Redis.
  • array: los datos de la sesión se guardan en una matriz PHP. Ten en cuenta que el controlador de sesión de matriz no admite la persistencia y normalmente solo se utiliza en los comandos de la consola.

Proveedores de servicios

La mayoría de los usuarios de Laravel no se dan cuenta, pero una gran parte de cómo funciona Laravel, está dentro de sus proveedores de servicios. Básicamente, son archivos de arranque para cada componente y están lo suficientemente abstraídos para que los usuarios puedan arrancar cualquier componente de cualquier forma.

Esta es una explicación aproximada de cómo funciona esto:

  1. Se inicia el componente de la aplicación Laravel. Este es el controlador principal de todo el framework, responsable de manejar la solicitud HTTP, ejecutar los proveedores de servicios y actuar como un contenedor de dependencia para el framework.
  2. Una vez que se ejecuta un proveedor de servicios, se llama a su método register. Esto nos permite crear una instancia de cualquier componente que queramos.
    • Ten en cuenta que todos los proveedores de servicios tienen acceso a la aplicación principal de Laravel (a través de $this->app), lo que le permitiría a los proveedores de servicios insertar instancias de las clases resueltas en el contenedor de dependencias.
  3. Una vez cargadas estas dependencias, deberíamos tener la libertad de usarlas llamando al contenedor, por ejemplo, a través del sistema Facade de Laravel, App::make.

Volviendo a Sessions, revisemos rápidamente a SessionServiceProivider:

1
 /**

2
     * Register the session manager instance.

3
	 *

4
	 * @return void

5
	 */
6
	protected function registerSessionManager()
7
	{
8
		$this->app->bindShared('session', function($app)
9
		{
10
			return new SessionManager($app);
11
		});
12
	}
13
14
	/**

15
	 * Register the session driver instance.

16
	 *

17
	 * @return void

18
	 */
19
	protected function registerSessionDriver()
20
	{
21
		$this->app->bindShared('session.store', function($app)
22
		{
23
			// First, we will create the session manager which is responsible for the

24
			// creation of the various session drivers when they are needed by the

25
			// application instance, and will resolve them on a lazy load basis.

26
			$manager = $app['session'];
27
28
			return $manager->driver();
29
		});
30
	}

Estos dos métodos son llamados por la función register(). El primero, registerSessionManager(), se llama para registrar inicialmente el SessionManager. Esta clase extiende el Manager que mencioné arriba. El segundo, registerSessionDriver() registra un controlador de sesión para el administrador, basado en lo que configuramos. Esto finalmente llama a este método en la clase Illuminate\Support\Manager:

1
/**

2
     * Create a new driver instance.

3
	 *

4
	 * @param  string  $driver

5
	 * @return mixed

6
	 *

7
	 * @throws \InvalidArgumentException

8
	 */
9
	protected function createDriver($driver)
10
	{
11
		$method = 'create'.ucfirst($driver).'Driver';
12
13
		// We'll check to see if a creator method exists for the given driver. If not we

14
		// will check for a custom driver creator, which allows developers to create

15
		// drivers using their own customized driver creator Closure to create it.

16
		if (isset($this->customCreators[$driver]))
17
		{
18
			return $this->callCustomCreator($driver);
19
		}
20
		elseif (method_exists($this, $method))
21
		{
22
			return $this->$method();
23
		}
24
25
		throw new \InvalidArgumentException("Driver [$driver] not supported.");
26
	}

Desde aquí, podemos ver que en base al nombre del controlador, desde el archivo de configuración, se llama a un método específico. Entonces, si lo tenemos configurado para usar el controlador de sesión file, llamará a este método en la clase SessionManager:

1
/**

2
     * Create an instance of the file session driver.

3
	 *

4
	 * @return \Illuminate\Session\Store

5
	 */
6
	protected function createFileDriver()
7
	{
8
		return $this->createNativeDriver();
9
	}
10
11
	/**

12
	 * Create an instance of the file session driver.

13
	 *

14
	 * @return \Illuminate\Session\Store

15
	 */
16
	protected function createNativeDriver()
17
	{
18
		$path = $this->app['config']['session.files'];
19
20
		return $this->buildSession(new FileSessionHandler($this->app['files'], $path));
21
	}

Luego, la clase de controlador se inyecta en una clase Store, que es responsable de llamar a los métodos de sesión reales. Esto nos permite realmente separar la implementación de SessionHandlerInterface del SPL en los controladores, la clase Store lo facilita.

Creación de nuestro propio controlador de sesiones

Crearemos nuestro propio controlador de sesión, un controlador de sesión de MongoDB. En primer lugar, necesitaremos crear un MongoSessionHandler dentro de una instancia de proyecto Laravel recién instalada. (Pediremos prestado mucho de Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler).:

1
<?php namespace Illuminate\Session;
2
3
    use Mongo;
4
    use MongoDate;
5
    use MongoBinData;
6
7
    class MongoSessionHandler implements \SessionHandlerInterface
8
    {
9
        /**

10
         * Mongo db config

11
         *

12
         * @var array

13
         */
14
        protected $config;
15
16
        /**

17
         * Mongo db connection

18
         * 

19
         * @var \Mongo

20
         */
21
        protected $connection;
22
23
        /**

24
         * Mongodb collection

25
         * 

26
         * @var \MongoCollection

27
         */
28
        protected $collection;
29
        /**

30
         * Create a new Mongo driven handler instance.

31
         *

32
         * @param  array $config

33
         *  - $config['host']       Mongodb host

34
         *  - $config['username']   Mongodb username

35
         *  - $config['password']   Mongodb password

36
         *  - $config['database']     Mongodb database

37
         *  - $config['collection'] Mongodb collection

38
         * @return void

39
         */
40
        public function __construct(array $config)
41
        {
42
            $this->config = $config;
43
44
            $connection_string = 'mongodb://';
45
46
            if (!empty($this->config['username']) && !empty($this->config['password'])) {
47
                $connection_string .= "{$this->config['user']}:{$this->config['password']}@";
48
            }
49
50
            $connection_string .= "{$this->config['host']}";
51
52
            $this->connection = new Mongo($connection_string);
53
54
            $this->collection = $this->connection->selectCollection($this->config['database'], $this->config['collection']);
55
        }
56
57
        /**

58
         * {@inheritDoc}

59
         */
60
        public function open($savePath, $sessionName)
61
        {
62
            return true;
63
        }
64
65
        /**

66
         * {@inheritDoc}

67
         */
68
        public function close()
69
        {
70
            return true;
71
        }
72
73
        /**

74
         * {@inheritDoc}

75
         */
76
        public function read($sessionId)
77
        {
78
            $session_data = $this->collection->findOne(array(
79
                '_id' => $sessionId,
80
            ));
81
82
            if (is_null($session_data)) {
83
                return '';
84
            } else {
85
                return $session_data['session_data']->bin;
86
            }
87
        }
88
89
        /**

90
         * {@inheritDoc}

91
         */
92
        public function write($sessionId, $data)
93
        {
94
            $this->collection->update(
95
                array(
96
                    '_id' => $sessionId
97
                ),
98
                array(
99
                    '$set' => array(
100
                        'session_data' => new MongoBinData($data, MongoBinData::BYTE_ARRAY),
101
                        'timestamp' => new MongoDate(),
102
                    )
103
                ),
104
                array(
105
                    'upsert' => true,
106
                    'multiple' => false
107
                )
108
            );
109
        }
110
111
        /**

112
         * {@inheritDoc}

113
         */
114
        public function destroy($sessionId)
115
        {
116
            $this->collection->remove(array(
117
                '_id' => $sessionId
118
            ));
119
120
            return true;
121
        }
122
123
        /**

124
         * {@inheritDoc}

125
         */
126
        public function gc($lifetime)
127
        {
128
            $time = new MongoDate(time() - $lifetime);
129
130
            $this->collection->remove(array(
131
                'timestamp' => array('$lt' => $time),
132
            ));
133
134
            return true;
135
        }
136
    }

Debes guardar esto en la carpeta vendor/laravel/framework/src/Illuminate/Session. Para los propósitos de este proyecto, lo pondremos aquí, pero lo ideal es que este archivo esté dentro de su propio espacio de nombres de biblioteca.

Luego, debemos asegurarnos de que la clase Manager pueda llamar a este controlador. Podemos hacer esto utilizando el método Manager::extend. Abre vendor/laravel/framework/src/Illuminate/Session/SessionServiceProvider.php y agrega el siguiente código. Idealmente, deberíamos ampliar el proveedor de servicios, pero eso está fuera del alcance de este tutorial.

1
/**

2
     * Setup the Mongo Driver callback

3
	 *

4
	 * @return  void

5
	 */
6
	public function setupMongoDriver()
7
	{
8
		$manager = $this->app['session'];
9
10
		$manager->extend('mongo', function($app) {
11
		    return new MongoSessionHandler(array(
12
		        'host'       => $app['config']->get('session.mongo.host'),
13
		        'username'   => $app['config']->get('session.mongo.username'),
14
		        'password'   => $app['config']->get('session.mongo.password'),
15
		        'database'   => $app['config']->get('session.mongo.database'),
16
		        'collection' => $app['config']->get('session.mongo.collection')
17
		    ));
18
		});
19
	}

Asegúrate de actualizar el método register() para llamar a este método:

1
/**

2
     * Register the service provider.

3
	 *

4
	 * @return void

5
	 */
6
	public function register()
7
	{
8
		$this->setupDefaultDriver();
9
10
		$this->registerSessionManager();
11
12
		$this->setupMongoDriver();
13
14
		$this->registerSessionDriver();
15
	}

Después, necesitamos definir la configuración de Mongo DB. Abre app/config/session.php y define los siguientes valores de configuración:

1
/**

2
     * Mongo DB settings

3
	 */
4
	'mongo' => array(
5
		'host' => '127.0.0.1',
6
		'username' => '',
7
		'password' => '',
8
		'database' => 'laravel',
9
		'collection' => 'laravel_session_collection'
10
	)

Mientras estamos en este archivo, también deberíamos actualizar la configuración driver en la parte de arriba:

1
'driver' => 'mongo'

Ahora, intenta acceder a la página principal (normalmente, localhost/somefolder/public). Si esta página se carga sin mostrar la página WHOOPS, entonces felicitaciones, ¡creamos con éxito un nuevo controlador de sesión! Pruébalo configurando algunos datos ficticios en la sesión, a través de Session::set() y luego repitiéndolos a través de Session::get().

El componente Auth

El componente Auth de Laravel maneja la autenticación de usuarios para el framework, así como la administración de las contraseñas. Lo que hizo el componente Laravel aquí es crear una interpretación abstracta del sistema típico de administración de usuarios que se puede usar en la mayoría de las aplicaciones web, lo que a su vez ayuda al programador a implementar fácilmente un sistema de inicio de sesión. Al igual que el componente Session, también utiliza Laravel Manager. Actualmente, el componente Auth tiene controladores para:

  • eloquent: esto hace uso del ORM incorporado de Laravel llamado Eloquent. También utiliza la clase User.php prefabricada dentro de la carpeta models.
  • database: utiliza cualquier conexión de base de datos configurada de forma predeterminada. Hace uso de una clase GenericUser para acceder a los datos del usuario.

Dado que sigue la misma implementación que el componente Session, el proveedor de servicios es muy similar a lo que  vimos en la parte superior:

1
/**

2
     * Register the service provider.

3
	 *

4
	 * @return void

5
	 */
6
	public function register()
7
	{
8
		$this->app->bindShared('auth', function($app)
9
		{
10
			// Once the authentication service has actually been requested by the developer

11
			// we will set a variable in the application indicating such. This helps us

12
			// know that we need to set any queued cookies in the after event later.

13
			$app['auth.loaded'] = true;
14
15
			return new AuthManager($app);
16
		});
17
	}

Aquí, podemos ver que básicamente crea una clase AuthManager que envuelve cualquier controlador que estemos usando, además de actuar como una fábrica para él. Dentro de AuthManager, vuelve a crear el controlador adecuado, envuelto alrededor de una clase Guard, que actúa de la misma manera que la clase Store de Session.

Creación de nuestro propio controlador de autenticación

Como antes, comencemos creando un MongoUserProvider:

1
<?php namespace Illuminate\Auth;
2
3
    use Mongo;
4
    use Illuminate\Hashing\HasherInterface;
5
6
    class MongoUserProvider implements UserProviderInterface {
7
8
        /**

9
         * The mongo instance

10
         *

11
         * @param  \Mongo

12
         */
13
        protected $connection;
14
15
        /**

16
         * The mongo connection instance

17
         *

18
         * @param  \MongoConnection

19
         */
20
        protected $collection;
21
22
        /**

23
         * The Mongo config array

24
         *

25
         * @var array

26
         */
27
        protected $config;
28
29
        /**

30
         * Create a new Mongo user provider.

31
         *

32
         * @param  array $config

33
         *     - $config['host']       Mongodb host

34
         *     - $config['username']   Mongodb username

35
         *     - $config['password']   Mongodb password

36
         *     - $config['database']   Mongodb database

37
         *     - $config['collection'] Mongodb collection

38
         * @return void

39
         */
40
        public function __construct(array $config)
41
        {
42
            $this->config = $config;
43
44
            $connection_string = 'mongodb://';
45
46
            if (!empty($this->config['username']) && !empty($this->config['password'])) {
47
                $connection_string .= "{$this->config['user']}:{$this->config['password']}@";
48
            }
49
50
            $connection_string .= "{$this->config['host']}";
51
52
            $this->connection = new Mongo($connection_string);
53
54
            $this->collection = $this->connection->selectCollection($this->config['database'], $this->config['collection']);
55
        }
56
57
        /**

58
         * Retrieve a user by their unique identifier.

59
         *

60
         * @param  mixed  $identifier

61
         * @return \Illuminate\Auth\UserInterface|null

62
         */
63
        public function retrieveById($identifier)
64
        {
65
            $user_data = $this->collection->findOne(array(
66
                '_id' => $identifier,
67
            ));
68
69
            if (!is_null($user_data)) {
70
                return new GenericUser((array) $user_data);
71
            }
72
        }
73
74
        /**

75
         * Retrieve a user by the given credentials.

76
         *

77
         * @param  array  $credentials

78
         * @return \Illuminate\Auth\UserInterface|null

79
         */
80
        public function retrieveByCredentials(array $credentials)
81
        {
82
            // Attempt to look for the user first regardless of password

83
            // We'll do that in the validateCredentials method

84
            if (isset($credentials['password'])) {
85
                unset($credentials['password']);
86
            }
87
88
            $user_data = $this->collection->findOne($credentials);
89
90
            if (!is_null($user_data)) {
91
                return new GenericUser((array) $user_data);
92
            }
93
        }
94
95
        /**

96
         * Validate a user against the given credentials.

97
         *

98
         * @param  \Illuminate\Auth\UserInterface  $user

99
         * @param  array  $credentials

100
         * @return bool

101
         */
102
        public function validateCredentials(UserInterface $user, array $credentials)
103
        {
104
            if (!isset($credentials['password'])) {
105
                return false;
106
            }
107
            
108
            return ($credentials['password'] === $user->getAuthPassword());
109
        }
110
    }

Es importante tener en cuenta aquí que no estoy comprobando una contraseña codificada, esto se hizo por simplicidad para que sea más fácil de nuestra parte crear datos ficticios y probarlos más adelante. En el código de producción, debes asegurarte de codificar la contraseña. Consulta la clase Illuminate\Auth\DatabaseUserProvider para ver un gran ejemplo de cómo hacerlo.

Después, necesitamos registrar nuestra devolución de llamada de controlador personalizada en el AuthManager. Para ello, necesitamos actualizar el método register del proveedor de servicios:

1
/**

2
     * Register the service provider.

3
	 *

4
	 * @return void

5
	 */
6
	public function register()
7
	{
8
		$this->app->bindShared('auth', function($app)
9
		{
10
			// Once the authentication service has actually been requested by the developer

11
			// we will set a variable in the application indicating such. This helps us

12
			// know that we need to set any queued cookies in the after event later.

13
			$app['auth.loaded'] = true;
14
15
			$auth_manager = new AuthManager($app);
16
17
			$auth_manager->extend('mongo', function($app) {
18
				return new MongoUserProvider(
19
					array(
20
						'host'       => $app['config']->get('auth.mongo.host'),
21
				        'username'   => $app['config']->get('auth.mongo.username'),
22
				        'password'   => $app['config']->get('auth.mongo.password'),
23
				        'database'   => $app['config']->get('auth.mongo.database'),
24
				        'collection' => $app['config']->get('auth.mongo.collection')
25
					)
26
				);
27
			});
28
29
			return $auth_manager;
30
		});
31
	}

Por último, también necesitamos actualizar el archivo de configuración auth.php para hacer uso del controlador Mongo, así como proporcionarle los valores de configuración adecuados de Mongo:

1
'driver' => 'mongo',
2
    ...
3
    ...
4
    ...
5
    /**

6
     * Mongo DB settings

7
	 */
8
	'mongo' => array(
9
		'host' => '127.0.0.1',
10
		'username' => '',
11
		'password' => '',
12
		'database' => 'laravel',
13
		'collection' => 'laravel_auth_collection'
14
	)

Probar esto es un poco más complicado, para hacerlo, usa la CLI de Mongo DB para insertar un nuevo usuario en la colección:

1
mongo
2
3
    > use laravel_auth
4
    switched to db laravel_auth
5
    > db.laravel_auth_collection.insert({id: 1, email:"nikko@nikkobautista.com", password:"test_password"})
6
    > db.laravel_auth_collection.find()
7
    > { "_id" : ObjectId("530c609f2caac8c3a8e4814f"), "id" 1, "email" : "nikko@emailtest.com", "password" : "test_password" }

Ahora, pruébalo con una llamada al método Auth::validate:

1
var_dump(Auth::validate(array('email' => 'nikko@emailtest.com', 'password' => 'test_password')));

Esto debería arrojar un bool(true). Si lo hace, entonces ¡creamos con éxito nuestro propio controlador Auth!

El componente Caché

El componente Caché de Laravel controla los mecanismos de almacenamiento en caché para su uso en el framework. Al igual que los dos componentes que discutimos, también hace uso del Laravel Manager (¿estás notando un patrón?). El componente Caché tiene controladores para:

  • apc
  • memcached
  • redis
  • file: una caché basada en archivos. Los datos se guardan en la ruta de acceso app/storage/cache.
  • database: caché basada en la base de datos. Los datos se guardan en filas en la base de datos. El esquema de la base de datos se describe en la documentación de Laravel.
  • array: los datos se "almacenan en caché" en una matriz. Ten en cuenta que la caché array no es persistente y se borra en cada carga de la página.

Dado que esto sigue la misma implementación que ambos componentes que discutimos, puedes asumir con seguridad que el proveedor de servicios es bastante similar:

1
/**

2
     * Register the service provider.

3
	 *

4
	 * @return void

5
	 */
6
	public function register()
7
	{
8
		$this->app->bindShared('cache', function($app)
9
		{
10
			return new CacheManager($app);
11
		});
12
13
		$this->app->bindShared('cache.store', function($app)
14
		{
15
			return $app['cache']->driver();
16
		});
17
18
		$this->app->bindShared('memcached.connector', function()
19
		{
20
			return new MemcachedConnector;
21
		});
22
23
		$this->registerCommands();
24
	}

El método register() aquí crea un CacheManager, que nuevamente actúa como contenedor y fábrica para los controladores. Dentro del administrador, envuelve el controlador alrededor de una clase Repository, similar a las clases Store y Guard.

Creación de nuestro propio controlador de caché

Crea MongoStore, que debería extender Illuminate\Cache\StoreInterface:

1
<?php namespace Illuminate\Cache;
2
3
    use Mongo;
4
5
    class MongoStore implements StoreInterface
6
    {
7
        /**

8
         * The mongo instance

9
         *

10
         * @param  \Mongo

11
         */
12
        protected $connection;
13
14
        /**

15
         * The mongo connection instance

16
         *

17
         * @param  \MongoConnection

18
         */
19
        protected $collection;
20
21
        /**

22
         * The Mongo config array

23
         *

24
         * @var array

25
         */
26
        protected $config;
27
28
        /**

29
         * Create a new Mongo cache store.

30
         *

31
         * @param  array $config

32
         *     - $config['host']       Mongodb host

33
         *     - $config['username']   Mongodb username

34
         *     - $config['password']   Mongodb password

35
         *     - $config['database']   Mongodb database

36
         *     - $config['collection'] Mongodb collection

37
         * @return void

38
         */
39
        public function __construct(array $config)
40
        {
41
            $this->config = $config;
42
43
            $connection_string = 'mongodb://';
44
45
            if (!empty($this->config['username']) && !empty($this->config['password'])) {
46
                $connection_string .= "{$this->config['user']}:{$this->config['password']}@";
47
            }
48
49
            $connection_string .= "{$this->config['host']}";
50
51
            $this->connection = new Mongo($connection_string);
52
53
            $this->collection = $this->connection->selectCollection($this->config['database'], $this->config['collection']);
54
        }
55
56
        /**

57
         * Retrieve an item from the cache by key.

58
         *

59
         * @param  string  $key

60
         * @return mixed

61
         */
62
        public function get($key)
63
        {
64
            $cache_data = $this->getObject($key);
65
66
            if (!$cache_data) {
67
                return null;
68
            }
69
70
            return unserialize($cache_data['cache_data']);
71
        }
72
73
        /**

74
         * Return the whole object instead of just the cache_data

75
         * 

76
         * @param  string  $key

77
         * @return array|null

78
         */
79
        protected function getObject($key)
80
        {
81
            $cache_data = $this->collection->findOne(array(
82
                'key' => $key,
83
            ));
84
85
            if (is_null($cache_data)) {
86
                return null;
87
            }
88
89
            if (isset($cache_data['expire']) && time() >= $cache_data['expire']) {
90
                $this->forget($key);
91
                return null;
92
            }
93
94
            return $cache_data;
95
        }
96
97
        /**

98
         * Store an item in the cache for a given number of minutes.

99
         *

100
         * @param  string  $key

101
         * @param  mixed   $value

102
         * @param  int     $minutes

103
         * @return void

104
         */
105
        public function put($key, $value, $minutes)
106
        {
107
            $expiry = $this->expiration($minutes);
108
109
            $this->collection->update(
110
                array(
111
                    'key' => $key
112
                ),
113
                array(
114
                    '$set' => array(
115
                        'cache_data' => serialize($value),
116
                        'expiry' => $expiry,
117
                        'ttl' => ($minutes * 60)
118
                    )
119
                ),
120
                array(
121
                    'upsert' => true,
122
                    'multiple' => false
123
                )
124
            );
125
        }
126
127
        /**

128
         * Increment the value of an item in the cache.

129
         *

130
         * @param  string  $key

131
         * @param  mixed   $value

132
         * @return void

133
         *

134
         * @throws \LogicException

135
         */
136
        public function increment($key, $value = 1)
137
        {
138
            $cache_data = $this->getObject($key);
139
140
            if (!$cache_data) {
141
                $new_data = array(
142
                    'cache_data' => serialize($value),
143
                    'expiry' => $this->expiration(0),
144
                    'ttl' => $this->expiration(0)
145
                );
146
            } else {
147
                $new_data = array(
148
                    'cache_data' => serialize(unserialize($cache_data['cache_data']) + $value),
149
                    'expiry' => $this->expiration((int) ($cache_data['ttl']/60)),
150
                    'ttl' => $cache_data['ttl']
151
                );
152
            }
153
154
            $this->collection->update(
155
                array(
156
                    'key' => $key
157
                ),
158
                array(
159
                    '$set' => $new_data
160
                ),
161
                array(
162
                    'upsert' => true,
163
                    'multiple' => false
164
                )
165
            );
166
        }
167
168
        /**

169
         * Decrement the value of an item in the cache.

170
         *

171
         * @param  string  $key

172
         * @param  mixed   $value

173
         * @return void

174
         *

175
         * @throws \LogicException

176
         */
177
        public function decrement($key, $value = 1)
178
        {
179
            $cache_data = $this->getObject($key);
180
181
            if (!$cache_data) {
182
                $new_data = array(
183
                    'cache_data' => serialize((0 - $value)),
184
                    'expiry' => $this->expiration(0),
185
                    'ttl' => $this->expiration(0)
186
                );
187
            } else {
188
                $new_data = array(
189
                    'cache_data' => serialize(unserialize($cache_data['cache_data']) - $value),
190
                    'expiry' => $this->expiration((int) ($cache_data['ttl']/60)),
191
                    'ttl' => $cache_data['ttl']
192
                );
193
            }
194
195
            $this->collection->update(
196
                array(
197
                    'key' => $key
198
                ),
199
                array(
200
                    '$set' => $new_data
201
                ),
202
                array(
203
                    'upsert' => true,
204
                    'multiple' => false
205
                )
206
            );
207
        }
208
209
        /**

210
         * Store an item in the cache indefinitely.

211
         *

212
         * @param  string  $key

213
         * @param  mixed   $value

214
         * @return void

215
         */
216
        public function forever($key, $value)
217
        {
218
            return $this->put($key, $value, 0);
219
        }
220
221
        /**

222
         * Remove an item from the cache.

223
         *

224
         * @param  string  $key

225
         * @return void

226
         */
227
        public function forget($key)
228
        {
229
            $this->collection->remove(array(
230
                'key' => $key
231
            ));
232
        }
233
234
        /**

235
         * Remove all items from the cache.

236
         *

237
         * @return void

238
         */
239
        public function flush()
240
        {
241
            $this->collection->remove();
242
        }
243
244
        /**

245
         * Get the expiration time based on the given minutes.

246
         *

247
         * @param  int  $minutes

248
         * @return int

249
         */
250
        protected function expiration($minutes)
251
        {
252
            if ($minutes === 0) return 9999999999;
253
254
            return time() + ($minutes * 60);
255
        }
256
257
        /**

258
         * Get the cache key prefix.

259
         *

260
         * @return string

261
         */
262
        public function getPrefix()
263
        {
264
            return '';
265
        }
266
    }

También necesitaremos agregar la devolución de llamada de Mongo nuevamente al administrador:

1
/**

2
     * Register the service provider.

3
	 *

4
	 * @return void

5
	 */
6
	public function register()
7
	{
8
		$this->app->bindShared('cache', function($app)
9
		{
10
			$cache_manager = new CacheManager($app);
11
12
			$cache_manager->extend('mongo', function($app) {
13
				return new MongoStore(
14
					array(
15
						'host'       => $app['config']->get('cache.mongo.host'),
16
				        'username'   => $app['config']->get('cache.mongo.username'),
17
				        'password'   => $app['config']->get('cache.mongo.password'),
18
				        'database'   => $app['config']->get('cache.mongo.database'),
19
				        'collection' => $app['config']->get('cache.mongo.collection')
20
					)
21
				);
22
			});
23
24
			return $cache_manager;
25
		});
26
27
		$this->app->bindShared('cache.store', function($app)
28
		{
29
			return $app['cache']->driver();
30
		});
31
32
		$this->app->bindShared('memcached.connector', function()
33
		{
34
			return new MemcachedConnector;
35
		});
36
37
		$this->registerCommands();
38
	}

Por último, necesitaremos actualizar el archivo de configuración cache.php:

1
'driver' => 'mongo',
2
    ...
3
    ...
4
    ...
5
    /**

6
	 * Mongo DB settings

7
	 */
8
	'mongo' => array(
9
		'host' => '127.0.0.1',
10
		'username' => '',
11
		'password' => '',
12
		'database' => 'laravel',
13
		'collection' => 'laravel_cache_collection'
14
	)

Ahora, intenta utilizar los métodos Cache::put() y Cache::get(). Si se hace correctamente, ¡deberíamos poder usar MongoDB para almacenar los datos en la caché!

Conclusión

En este tutorial, aprendimos sobre lo siguiente:

  • El sistema basado en componentes de Laravel llamado Illuminate, que es utilizado por el framework de Laravel.
  • Los proveedores de servicios de Laravel y un poco sobre cómo funcionan.
  • El sistema Manager de Laravel, que actúa como contenedor y fábrica para los controladores.
  • Los componentes Session, Auth y Caché y cómo crear nuevos controladores para cada uno.
  • Las bibliotecas Store, Guard y Repository que utilizan estos controladores.

Con suerte, esto ayudará a los programadores a crear sus propios controladores y ampliar la funcionalidad actual del framework de Laravel.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.