En los últimos años, Laravel se ha convertido en uno de los frameworks más destacados que los ingenieros de software utilizan para construir sus aplicaciones web. Similar a la popularidad que CodeIgniter disfrutó en su apogeo, Laravel ha sido alabado por su facilidad de uso, su facilidad para los principiantes y su adhesión a los estándares de la industria..
Sin embargo, una cosa que muchos programadores no aprovechan es el sistema basado en componentes de Laravel. Desde su conversión a componentes potenciados por el compositor, Laravel 4 se ha convertido en un sistema muy modular, similar a la verbosidad de marcos más maduros como Symfony. Esto se llama Iluminar
grupo de componentes, que en mi opinión, no es el marco real en sí, sino una compilación de bibliotecas que un marco puede utilizar potencialmente. El marco real de Laravel está representado por la aplicación de esqueleto Laravel (que se encuentra en el laravel / laravel
Repositorio GitHub) que hace uso de estos componentes para construir una aplicación web.
En este tutorial, nos sumergiremos en un grupo de estos componentes, aprenderemos cómo funcionan, cómo los utiliza el marco y cómo podemos ampliar su funcionalidad..
El componente de sesión de Laravel maneja sesiones para 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 este escrito, el componente Session tiene controladores para:
expediente
- un controlador de sesión basado en archivos donde los datos de sesión se guardan en un archivo cifrado.Galleta
- un controlador de sesión basado en cookies donde los datos de sesión están cifrados en las cookies del usuario.base de datos
- Los datos de la 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..formación
- Los datos de la sesión se guardan en una matriz de PHP. Tenga en cuenta que el controlador de sesión de matriz no admite la persistencia y, por lo general, solo se usa en los comandos de la consola.La mayoría de los usuarios de Laravel no se dan cuenta, pero una gran parte de cómo funciona Laravel está en sus proveedores de servicios. Básicamente, son archivos de arranque para cada componente y están lo suficientemente abstractos para que los usuarios puedan iniciar cualquier componente de cualquier manera..
Una explicación aproximada de cómo funciona esto es a continuación:
registro
se llama metodo Esto nos permite instanciar cualquier componente que queramos. $ this-> app
), que permitiría a los proveedores de servicios enviar instancias de las clases resueltas al contenedor de dependencias.App :: make
.Volviendo a las sesiones, echemos un vistazo rápido a la SessionServiceProivider
:
/ ** * Registrar la instancia del administrador de sesión. * * @return void * / función protegida registerSessionManager () $ this-> app-> bindShared ('session', function ($ app) devolver nuevo SessionManager ($ app);); / ** * Registrar la instancia del controlador de sesión. * * @return void * / función protegida registerSessionDriver () $ this-> app-> bindShared ('session.store', function ($ app) // Primero, crearemos el administrador de sesión que es responsable de / / creación de los diversos controladores de sesión cuando los necesita // la instancia de la aplicación, y los resolverá de forma diferida. $ manager = $ app ['sesión']; devolver $ manager-> driver ();) ;
Estos dos métodos son llamados por el registro()
función. El primero, registrarSessionManager ()
, Se llama para registrar inicialmente el SessionManager
. Esta clase extiende la Gerente
que he mencionado en la parte superior. El segundo, registerSessionDriver ()
registra un controlador de sesión para el administrador, basado en lo que hemos configurado. Esto eventualmente llama a este método en el Illuminate \ Support \ Manager
clase:
/ ** * Crear una nueva instancia de controlador. * * @param string $ driver * @return mixed * * @throws \ InvalidArgumentException * / función protegida createDriver ($ driver) $ method = 'create'.ucfirst ($ driver).' Driver '; // Verificaremos si existe un método creador para el controlador dado. Si no es así, // buscaremos un creador de controladores personalizado, lo que permitirá a los desarrolladores crear // controladores utilizando su propio cierre de creador de controladores personalizado para crearlo. if (isset ($ this-> customCreators [$ driver])) return $ this-> callCustomCreator ($ driver); elseif (method_exists ($ this, $ method)) return $ this -> $ method (); lanzar nueva \ InvalidArgumentException ("Driver [$ driver] no es compatible.");
Desde aquí, podemos ver que, en función del nombre del controlador, del archivo de configuración, se llama a un método específico. Entonces, si lo tenemos configurado para usar el expediente
manejador de sesión, llamará a este método en el SessionManager
clase:
/ ** * Crear una instancia del controlador de sesión de archivo. * * @return \ Illuminate \ Session \ Store * / protected function createFileDriver () return $ this-> createNativeDriver (); / ** * Crear una instancia del controlador de sesión de archivo. * * @return \ Illuminate \ Session \ Store * / función protegida createNativeDriver () $ path = $ this-> app ['config'] ['session.files']; devuelve $ this-> buildSession (nuevo FileSessionHandler ($ this-> app ['files'], $ path));
La clase de conductor se inyecta en un Almacenar
clase, que es responsable de llamar a los métodos de sesión real. Esto nos permite separar realmente la implementación del SessionHandlerInterface
del SPL a los drivers, el Almacenar
la clase lo facilita.
Vamos a crear nuestro propio manejador de sesión, un manejador de sesión MongoDB. En primer lugar, tendremos que crear un MongoSessionHandler
Dentro de una instancia de proyecto Laravel recién instalada. (Estaremos prestando mucho de Symfony \ Component \ HttpFoundation \ Session \ Storage \ Handler \ MongoDbSessionHandler
) .:
config = $ config; $ connection_string = 'mongodb: //'; if (! empty ($ this-> config ['username']) &&! empty ($ this-> config ['password'])) $ connection_string. = "$ this-> config ['user'] : $ this-> config ['password'] @ "; $ connection_string. = "$ this-> config ['host']"; $ this-> connection = new Mongo ($ connection_string); $ this-> collection = $ this-> connection-> selectCollection ($ this-> config ['database'], $ this-> config ['collection']); / ** * @inheritDoc * / public function open ($ savePath, $ sessionName) return true; / ** * @inheritDoc * / public function close () return true; / ** * @inheritDoc * / public function read ($ sessionId) $ session_data = $ this-> collection-> findOne (array ('_id' => $ sessionId,)); if (is_null ($ session_data)) return "; else return $ session_data ['session_data'] -> bin; / ** * @inheritDoc * / función pública write ($ sessionId, $ data) $ this-> collection-> update (array ('_id' => $ sessionId), array ('$ set' => array ('session_data' => new MongoBinData ($ data, MongoBinData :: BYTE_ARRAY), 'timestamp' => new MongoDate (),)), array ('upsert' => true, 'multiple' => false)); / ** * @inheritDoc * / public function destroy ($ sessionId) $ this- > collection-> remove (array ('_id' => $ sessionId)); return true; / ** * @inheritDoc * / public function gc ($ lifetime) $ time = new MongoDate (time () - $ lifetime); $ this-> collection-> remove (array ('timestamp' => array ('$ lt' => $ time),)); return true;
Deberías guardar esto en el proveedor / laravel / framework / src / Illuminate / Session
carpeta. Para los propósitos de este proyecto, lo pondremos aquí, pero idealmente este archivo debería estar dentro de su propio espacio de nombres de biblioteca.
A continuación, necesitamos asegurarnos de que Gerente
clase puede llamar a este controlador. Podemos hacer esto utilizando el Gerente :: extender
método. Abierto proveedor / laravel / framework / src / Illuminate / Session / SessionServiceProvider.php
y añada el siguiente código. Idealmente, deberíamos ampliar el proveedor de servicios, pero eso está fuera del alcance de este tutorial..
/ ** * Configurar la devolución de llamada del controlador Mongo * * @return void * / public function setupMongoDriver () $ manager = $ this-> app ['session']; $ manager-> extend ('mongo', function ($ app) return new MongoSessionHandler (array ('host' => $ app ['config'] -> get ('session.mongo.host'), 'username' => $ app ['config'] -> get ('session.mongo.username'), 'password' => $ app ['config'] -> get ('session.mongo.password'), 'database' => $ app ['config'] -> get ('session.mongo.database'), 'collection' => $ app ['config'] -> get ('session.mongo.collection'))); );
Asegúrese de actualizar el registro()
Método para llamar a este método:
/ ** * Registrar el proveedor de servicios. * * @return void * / public function register () $ this-> setupDefaultDriver (); $ this-> registerSessionManager (); $ this-> setupMongoDriver (); $ this-> registerSessionDriver ();
A continuación, necesitamos definir la configuración de Mongo DB. Abierto app / config / session.php
y define los siguientes ajustes de configuración:
/ ** * Configuración de la base de datos Mongo * / 'mongo' => array ('host' => '127.0.0.1', 'username' => ", 'password' =>", 'database' => 'laravel', 'collection' => 'laravel_session_collection')
Mientras estamos en este archivo, también debemos actualizar el conductor
configuración arriba arriba
'driver' => 'mongo'
Ahora, intenta y accede a la página principal (normalmente, localhost / somefolder / public
). Si esta página se carga sin mostrar el WHOOPS
página, luego felicitaciones, ¡hemos creado con éxito un nuevo controlador de sesión! Pruébelo configurando algunos datos ficticios en la sesión, a través de Session :: set ()
y luego haciéndolo repetir a través de Sesión :: get ()
.
El componente Laravel Auth maneja la autenticación del usuario para el marco, así como la administración de contraseñas. Lo que el componente Laravel ha hecho 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:
elocuente
- Esto hace uso del ORM incorporado de Laravel llamado Elocuente
. También utiliza el prefabricado. Usuario.php
clase dentro del modelos
carpeta.base de datos
- esto utiliza la conexión de base de datos configurada de forma predeterminada. Hace uso de un GenericUser
Clase para acceder a los datos del usuario..Dado que esto sigue la misma implementación que la Sesión
componente, el proveedor de servicios es muy similar a lo que hemos visto en la parte superior:
/ ** * Registrar el proveedor de servicios. * * @return void * / public function register () $ this-> app-> bindShared ('auth', function ($ app) // Una vez que el desarrollador haya solicitado el servicio de autenticación // lo configuraremos una variable en la aplicación que lo indica. Esto nos ayuda a // saber que debemos configurar las cookies en cola en el evento posterior posterior. $ app ['auth.loaded'] = true; devolver el nuevo AuthManager ($ app);) ;
Aquí, podemos ver que básicamente crea una AuthManager
clase que envuelve al conductor que estamos usando, además de actuar como una fábrica para ello. Dentro de AuthManager
, nuevamente crea el controlador apropiado, envuelto alrededor de un Guardia
clase, que actúa de la misma manera que la Almacenar
clase de Sesión
.
Como antes, comencemos creando una Proveedor de MongoUser
:
config = $ config; $ connection_string = 'mongodb: //'; if (! empty ($ this-> config ['username']) &&! empty ($ this-> config ['password'])) $ connection_string. = "$ this-> config ['user'] : $ this-> config ['password'] @ "; $ connection_string. = "$ this-> config ['host']"; $ this-> connection = new Mongo ($ connection_string); $ this-> collection = $ this-> connection-> selectCollection ($ this-> config ['database'], $ this-> config ['collection']); / ** * Recuperar un usuario por su identificador único. * * @param mixed $ identifier * @return \ Illuminate \ Auth \ UserInterface | null * / public function retrieveById ($ identifier) $ user_data = $ this-> collection-> findOne (array ('_id' => $ identifier, )); if (! is_null ($ user_data)) return new GenericUser ((array) $ user_data); / ** * Recuperar un usuario por las credenciales dadas. * * @param array $ credentials * @return \ Illuminate \ Auth \ UserInterface | null * / public function retrieveByCredentials (array $ credentials) // Intentar buscar primero al usuario sin importar la contraseña // Lo haremos en el Método validateCredentials if (isset ($ credentials ['password'])) unset ($ credentials ['password']); $ user_data = $ this-> collection-> findOne ($ credentials); if (! is_null ($ user_data)) return new GenericUser ((array) $ user_data); / ** * Validar un usuario con las credenciales dadas. * * @param \ Illuminate \ Auth \ UserInterface $ user * @param array $ credentials * @return bool * / public function validateCredentials (UserInterface $ user, array $ credentials) if (! isset ($ credentials ['contraseña']) ) falso retorno; return ($ credenciales ['contraseña'] === $ usuario-> getAuthPassword ());
Es importante tener en cuenta que no estoy comparando con una contraseña con hash, esto se hizo por simplicidad para que sea más fácil para nosotros crear datos ficticios y probar esto más adelante. En el código de producción, debe asegurarse de marcar la contraseña. Revisar la Illuminate \ Auth \ DatabaseUserProvider
clase para un gran ejemplo de cómo hacer esto.
Luego, debemos registrar nuestra devolución de llamada del controlador personalizado en el AuthManager
. Para ello, necesitamos actualizar el proveedor de servicios. registro
método:
/ ** * Registrar el proveedor de servicios. * * @return void * / public function register () $ this-> app-> bindShared ('auth', function ($ app) // Una vez que el desarrollador haya solicitado el servicio de autenticación // lo configuraremos una variable en la aplicación que lo indica. Esto nos ayuda a // saber que debemos configurar las cookies en cola en el evento posterior más adelante. $ app ['auth.loaded'] = true; $ auth_manager = new AuthManager ($ app); $ auth_manager-> extend ('mongo', function ($ app) return new MongoUserProvider (array ('host' => $ app ['config'] -> get ('auth.mongo.host'), 'username' => $ app ['config'] -> get ('auth.mongo.username'), 'password' => $ app ['config'] -> get ('auth.mongo.password'), 'database' => $ app ['config'] -> get ('auth.mongo.database'), 'collection' => $ app ['config'] -> get ('auth.mongo.collection'))); ); devuelve $ auth_manager;);
Por último, también necesitamos actualizar el auth.php
archivo de configuración para hacer uso del controlador Mongo, así como proporcionarle los valores de configuración de Mongo adecuados:
'driver' => 'mongo',… / ** * Configuración de la base de datos de Mongo * / 'mongo' => array ('host' => '127.0.0.1', 'username' => ", 'password' =>" , 'database' => 'laravel', 'collection' => 'laravel_auth_collection')
Probar esto es un poco más complicado, para hacerlo, use el CLI de la base de datos de Mongo para insertar un nuevo usuario en la colección:
mongo> use laravel_auth cambiado a db laravel_auth> db.laravel_auth_collection.insert (id: 1, correo electrónico: "[email protected]", contraseña: "test_password"))> db.laravel_auth_collection.find ()> "_id" : ObjectId ("530c609f2caac8c3a8e4814f"), "id" 1, "email": "[email protected]", "password": "test_password"
Ahora, pruébalo probando una Auth :: validate
método de llamada:
var_dump (Auth :: validate (array ('email' => '[email protected]', 'password' => 'test_password')));
Esto debería volcar un bool (verdadero)
. Si lo hace, entonces hemos creado con éxito nuestro propio controlador de autenticación.!
El componente Laravel Cache maneja los mecanismos de almacenamiento en caché para su uso en el marco. Al igual que los dos componentes que hemos analizado, también utiliza el Administrador de Laravel (¿Está notando un patrón?). El componente Cache tiene controladores para:
apc
memcached
Redis
expediente
- un caché basado en archivos. Los datos se guardan en el aplicación / almacenamiento / caché
camino.base de datos
- 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..formación
- los datos se "guardan en caché" en una matriz. Tenga en cuenta que la formación
el caché no es persistente y se borra en cada carga de página.Dado que esto sigue la misma implementación que los dos componentes que hemos analizado, puede asumir con seguridad que el proveedor de servicios es bastante similar:
/ ** * Registrar el proveedor de servicios. * * @return void * / public function register () $ this-> app-> bindShared ('cache', function ($ app) devolver nuevo CacheManager ($ app);); $ this-> app-> bindShared ('cache.store', function ($ app) return $ app ['cache'] -> driver ();); $ this-> app-> bindShared ('memcached.connector', function () return new MemcachedConnector;); $ this-> registerCommands ();
los registro()
método aquí crea una CacheManager
, que de nuevo actúa como una envoltura y fábrica para los conductores. Dentro del gerente, envuelve al conductor alrededor de un Repositorio
clase, similar a la Almacenar
y Guardia
clases.
Crear el MongoStore
, lo que debería extender el Illuminate \ Cache \ StoreInterface
:
config = $ config; $ connection_string = 'mongodb: //'; if (! empty ($ this-> config ['username']) &&! empty ($ this-> config ['password'])) $ connection_string. = "$ this-> config ['user'] : $ this-> config ['password'] @ "; $ connection_string. = "$ this-> config ['host']"; $ this-> connection = new Mongo ($ connection_string); $ this-> collection = $ this-> connection-> selectCollection ($ this-> config ['database'], $ this-> config ['collection']); / ** * Recuperar un elemento de la caché por clave. * * @param string $ key * @return mixed * / public function get ($ key) $ cache_data = $ this-> getObject ($ key); if (! $ cache_data) return null; return unserialize ($ cache_data ['cache_data']); / ** * Devuelve el objeto completo en lugar de solo cache_data * * @param string $ key * @return array | null * / protected function getObject ($ key) $ cache_data = $ this-> collection-> findOne (array ('clave' => $ clave,)); if (is_null ($ cache_data)) return null; if (isset ($ cache_data ['expire']) && time ()> = $ cache_data ['expire']) $ this-> forget ($ key); retorno nulo devolver $ cache_data; / ** * Almacenar un elemento en el caché durante un número determinado de minutos. * * @param string $ key * @param mixed $ value * @param int $ minutes * @return void * / public function put ($ key, $ value, $ minutes) $ expiry = $ this-> expiration ($ minutes ); $ this-> collection-> update (array ('key' => $ key), array ('$ set' => array ('cache_data' => serialize ($ value), 'expiry' => $ expiry, ' ttl '=> ($ minutos * 60))), array (' upsert '=> true,' multiple '=> false)); / ** * Incrementa el valor de un elemento en el caché. * * @param string $ key * @param mixed $ value * @return void * * @throws \ LogicException * / función pública increment ($ key, $ value = 1) $ cache_data = $ this-> getObject ($ key) ; if (! $ cache_data) $ new_data = array ('cache_data' => serialize ($ value), 'expiry' => $ this-> expiration (0), 'ttl' => $ this-> expiration (0) ); else $ new_data = array ('cache_data' => serialize (unserialize ($ cache_data ['cache_data']) + $ value), 'expiry' => $ this-> expiration ((int) ($ cache_data ['ttl '] / 60)),' ttl '=> $ cache_data [' ttl ']); $ this-> collection-> update (array ('key' => $ key), array ('$ set' => $ new_data), array ('upsert' => true, 'multiple' => false)) ; / ** * Disminuye el valor de un elemento en el caché. * * @param string $ key * @param mixed $ value * @return void * * @throws \ LogicException * / decremento de la función pública ($ key, $ value = 1) $ cache_data = $ this-> getObject ($ key) ; if (! $ cache_data) $ new_data = array ('cache_data' => serialize ((0 - $ value)), 'expiry' => $ this-> expiration (0), 'ttl' => $ this-> vencimiento (0)); else $ new_data = array ('cache_data' => serialize (unserialize ($ cache_data ['cache_data']) - $ value), 'expiry' => $ this-> expiration ((int) ($ cache_data ['ttl '] / 60)),' ttl '=> $ cache_data [' ttl ']); $ this-> collection-> update (array ('key' => $ key), array ('$ set' => $ new_data), array ('upsert' => true, 'multiple' => false)) ; / ** * Almacenar un elemento en el caché de forma indefinida. * * @param string $ key * @param mixed $ value * @return void * / public function para siempre ($ key, $ value) return $ this-> put ($ key, $ value, 0); / ** * Eliminar un elemento de la caché. * * @param string $ key * @return void * / public function forget ($ key) $ this-> collection-> remove (array ('key' => $ key)); / ** * Eliminar todos los elementos de la caché. * * @return void * / public function flush () $ this-> collection-> remove (); / ** * Obtener el tiempo de caducidad basado en los minutos dados. * * @param int $ minutes * @return int * / caducidad de la función protegida ($ minutes) if ($ minutes === 0) return 9999999999; tiempo de retorno () + ($ minutos * 60); / ** * Obtener el prefijo de clave de caché. * * @return string * / public function getPrefix () return ";
También necesitaremos agregar nuevamente la devolución de llamada de Mongo al administrador:
/ ** * Registrar el proveedor de servicios. * * @return void * / public function register () $ this-> app-> bindShared ('cache', function ($ app) $ cache_manager = new CacheManager ($ app); $ cache_manager-> extend ('mongo ', function ($ app) return new MongoStore (array (' host '=> $ app [' config '] -> get (' cache.mongo.host '),' username '=> $ app [' config ' ] -> get ('cache.mongo.username'), 'password' => $ app ['config'] -> get ('cache.mongo.password'), 'database' => $ app ['config' ] -> get ('cache.mongo.database'), 'collection' => $ app ['config'] -> get ('cache.mongo.collection')));); return $ cache_manager;) ; $ this-> app-> bindShared ('cache.store', function ($ app) return $ app ['cache'] -> driver ();); $ this-> app-> bindShared ('memcached.connector', function () return new MemcachedConnector;); $ this-> registerCommands ();
Por último, tendremos que actualizar el cache.php
archivo de configuración:
'driver' => 'mongo',… / ** * Configuración de la base de datos de Mongo * / 'mongo' => array ('host' => '127.0.0.1', 'username' => ", 'password' =>" , 'database' => 'laravel', 'collection' => 'laravel_cache_collection')
Ahora, intenta usar el Caché :: put ()
y Caché :: get ()
metodos Si se hace correctamente, deberíamos poder usar MongoDB para almacenar en caché los datos!
En este tutorial, aprendimos sobre lo siguiente:
Iluminar
, que es utilizado por el marco de Laravel.Esperemos que esto ayude a los programadores a crear sus propios controladores y extender la funcionalidad actual del marco Laravel.