Under de senaste åren har Laravel blivit en av de mest framträdande ramar som mjukvaruutvecklare använder för att bygga sina webbapplikationer. Liknande populariteten som CodeIgniter åtnjutit i sin storhetstid, har Laravel blivit lovad för sin användarvänlighet, vänlighet till nybörjare och dess efterlevnad av industristandarder.
En sak men det är inte mycket programmerare som dra fördel av Laravels komponentbaserade system. Sedan omvandlingen till kompositdrivna komponenter har Laravel 4 blivit ett väldigt modulärt system, som liknar de vuxna ramarna som Symfony. Detta kallas Belysa
grupp av komponenter, som enligt min mening inte är själva ramen själva, men är en samling av bibliotek som en ram kan använda. Laravels faktiska ramverk representeras av Laravel-skelettansökan (finns på laravel / laravel
GitHub repository) som använder dessa komponenter för att bygga en webbapplikation.
I denna handledning dyker vi in i en grupp av dessa komponenter, lär oss hur de fungerar, hur de används av ramverket och hur vi kan utöka deras funktionalitet.
Laravel-sessionen hanterar sessioner för webbapplikationen. Den använder sig av ett drivrutinsbaserat system som heter Laravel Manager, som fungerar som både en fabrik och ett omslag för vilken drivrutin som är inställd i konfigurationsfilen. Med denna skrivning har Session-komponenten drivrutiner för:
fil
- en filbaserad sessiondrivrutin där sessionsdata sparas i en krypterad fil.kaka
- en cookiebaserad sessiondrivrutin där sessionsdata krypteras i användarens cookies.databas
- Sessionsdata sparas i vilken databas som är konfigurerad för applikationen.apc
- Sessionsdata sparas i APC.memcached
- Sessionsdata sparas i Memcached.redis
- Sessionsdata sparas i Redis.array
- Sessionsdata sparas i en PHP-array. Observera att array-sessiondrivrutinen inte stöder uthållighet och brukar vanligtvis endast användas i konsolkommandon.De flesta Laravel-användare inser inte, men en stor del av hur Laravel fungerar, ligger inom sina tjänsteleverantörer. De är i huvudsak bootstrap-filer för varje komponent och de är abstraherade nog så att användare kan starta upp några komponenter på något sätt.
En grov förklaring till hur detta fungerar är nedan:
Registrera
Metoden heter. Detta gör det möjligt för oss att instansera vilken komponent vi vill ha. $ This-> app
), vilket skulle låta tjänsteleverantörer skicka instanser av de upplösta klasserna i beredskapsbehållaren.App :: make
.Kommer tillbaka till Sessioner, låt oss ta en snabb titt på SessionServiceProivider
:
/ ** * Registrera session manager instans. * * @return void * / protected function registerSessionManager () $ this-> app-> bindShare ('session', funktion ($ app) returnera nya SessionManager ($ app);); / ** * Registrera sessionens drivrutinsinstans. * * @return void * / skyddad funktion registerSessionDriver () $ this-> app-> bindShared ('session.store', funktion ($ app) // Först ska vi skapa session manager som ansvarar för / / skapandet av de olika sessionsdrivrutinerna när de behövs av // ansökningsinstansen och löser dem på en lat belastning. $ manager = $ app ['session'], returnera $ manager-> driver ();) ;
Dessa två metoder kallas av Registrera()
fungera. Den första, registerSessionManager ()
, kallas för att först registrera Session
. Denna klass sträcker sig Chef
som jag nämnde ovanpå. Den andra, registerSessionDriver ()
registrerar en sessionhanterare för chefen baserat på vad vi har konfigurerat. Detta kallar så småningom den här metoden i Illuminate \ Support \ chef
klass:
/ ** * Skapa en ny drivrutinsinstans. * * @paramsträng $ driver * @return mixed * * @throws \ InvalidArgumentException * / skyddad funktion createDriver ($ driver) $ method = 'create'.ucfirst ($ driver).' Driver '; // Vi kontrollerar om det finns en skapningsmetod för den angivna drivrutinen. Om inte vi // kommer att kolla efter en anpassad drivrutinsskapare, som tillåter utvecklare att skapa // drivrutiner med egen anpassad drivrutinsuppsättning för att skapa den. om (isset ($ this-> customCreators [$ driver])) return $ this-> callCustomCreator ($ driver); elseif (method_exists ($ this, $ method)) return $ this -> $ method (); kasta nytt \ InvalidArgumentException ("Driver [$ driver] stöds inte.");
Härifrån kan vi se att baserat på drivrutins namn, från konfigurationsfilen, kallas en viss metod. Så, om vi har det konfigurerat att använda fil
session handler, kommer det att ringa denna metod i Session
klass:
/ ** * Skapa en instans av filsessionen drivrutinen. * * @return \ Illuminate \ Session \ Store * / skyddad funktion createFileDriver () return $ this-> createNativeDriver (); / ** * Skapa en instans av filsessionen drivrutinen. * * @return \ Illuminate \ Session \ Store * / skyddad funktion createNativeDriver () $ path = $ this-> app ['config'] ['session.files']; returnera $ this-> buildSession (ny FileSessionHandler ($ this-> app ['files'], $ path));
Förarklassen injiceras sedan i a Lagra
klass, som är ansvarig för att ringa själva sessionen metoder. Det gör att vi faktiskt skiljer genomförandet av SessionHandlerInterface
från SPL till förare, den Lagra
klassen underlättar det.
Låt oss skapa vår egen Session Handler, en MongoDB Session Handler. Först måste vi skapa en MongoSessionHandler
inuti en nyinstallerad Laravel-projektinstans. (Vi kommer att låna tungt från Symfony \ Component \ HttpFoundation \ Session \ Förvaring \ Handler \ MongoDbSessionHandler
) .:
config = $ config; $ connection_string = 'mongodb: //'; om ! tom ($ this-> config ['användarnamn']) &&! tomt ($ 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 ['databas'], $ this-> config ['collection']); / ** * @inheritDoc * / allmän funktion öppen ($ savePath, $ sessionName) return true; / ** * @inheritDoc * / public function close () return true; / ** * @inheritDoc * / public function read ($ sessionId) $ session_data = $ this-> collection-> findOne (array ('_id' => $ sessionId,)); om is_null ($ session_data)) return "; annars return $ session_data ['session_data'] -> bin; / ** * @inheritDoc * / public function write ($ sessionId, $ data) $ this-> collection-> update (array ('_id' => $ sessionId), array ('$ set' => array ('session_data' => ny MongoBinData ($ data, MongoBinData :: BYTE_ARRAY) => ny MongoDate (),)), array ('upsert' => true, 'multipel' => false)); / ** * @inheritDoc * / public function förstöra ($ sessionId) $ this- > collection-> remove (array ('_id' => $ sessionId)); return true; / ** * @inheritDoc * / allmän funktion gc ($ livstid) $ time = new MongoDate $ lifetime); $ this-> collection-> remove (array ('timestamp' => array ('$ lt' => $ tid),)); returnera true;
Du borde spara det här i leverantör / laravel / ram / src / Illuminate / Session
mapp. För det här projektet kommer vi att lägga den här, men helst den här filen ska vara i sitt eget namn på biblioteket.
Därefter måste vi se till att Chef
klassen kan ringa den här drivrutinen. Vi kan göra detta genom att använda Chef :: förlänga
metod. Öppna leverantör / laravel / ram / src / Illuminate / Session / SessionServiceProvider.php
och lägg till följande kod. Helst bör vi utöka tjänsteleverantören, men det ligger utanför ramen för denna handledning.
/ ** * Ställ in Mongo-drivrutinen återuppringning * * @return void * / allmän funktion setupMongoDriver () $ manager = $ this-> app ['session']; $ manager-> extend ('mongo', funktion ($ app) returnera ny MongoSessionHandler (array ('host' => $ app ['config'] -> get ('session.mongo.host'), 'användarnamn' => $ app ['config'] -> få ('session.mongo.username'), 'lösenord' => $ app ['config'] -> get ('session.mongo.password'), 'databas' => $ app ['config'] -> få ('session.mongo.database'), 'samling' => $ app ['config'] -> get ('session.mongo.collection'))); );
Se till att uppdatera Registrera()
metod för att ringa denna metod:
/ ** * Registrera tjänsteleverantören. * * @return void * / public function register () $ this-> setupDefaultDriver (); $ This-> registerSessionManager (); $ This-> setupMongoDriver (); $ This-> registerSessionDriver ();
Därefter måste vi definiera Mongo DB-konfigurationen. Öppna app / config / session.php
och definiera följande konfigurationsinställningar:
/ ** * Mongo DB-inställningar * / 'mongo' => array ('host' => '127.0.0.1', 'användarnamn' => ", 'lösenord' =>", 'database' => 'laravel' 'samling' => 'laravel_session_collection')
Medan vi är på den här filen borde vi också uppdatera förare
konfiguration upptill:
'förare' => 'mongo'
Nu kan du försöka komma åt huvudsidan (vanligtvis, localhost / somefolder / public
). Om denna sida laddas utan att visa OJ DÅ
sida, grattis, vi har framgångsrikt skapat en helt ny sessionsdrivrutin! Testa det genom att ange några dummy data på sessionen, via Session :: set ()
och sedan echo den tillbaka via Session :: få ()
.
Laravel Auth-komponenten hanterar användarautentisering för ramverket, såväl som lösenordshantering. Vad Laravel-komponenten har gjort här är att skapa en abstrakt tolkning av det typiska användarhanteringssystemet som kan användas i de flesta webbapplikationer, vilket i sin tur hjälper programmeraren att enkelt implementera ett inloggningssystem. Liksom Session-komponenten använder den också Laravel Manager. För närvarande har Auth-komponenten drivrutiner för:
vältalig
- Detta använder sig av Laravels inbyggda ORM som heter Vältalig
. Det utnyttjar också den färdiga user.php
klass inne i modeller
mapp.databas
- Detta använder vilken databasanslutning som standard är konfigurerad. Det använder sig av a GenericUser
klass för att få tillgång till användardata.Eftersom detta följer samma implementering som Session
komponent, tjänsteleverantören är mycket lik den som vi sett på toppen:
/ ** * Registrera tjänsteleverantören. * * @return void * / public function register () $ this-> app-> bindShared ('auth', funktion ($ app) // När autentiseringstjänsten faktiskt har begärts av utvecklaren // en variabel i applikationen som indikerar sådan. Det hjälper oss // att vi behöver ställa in några kökkök i efterhand senare. $ app ['auth.loaded'] = true, returnera nya AuthManager ($ app);) ;
Här kan vi se att det i grunden skapar en authManager
klass som sveper runt vilken förare vi använder, samt fungerar som en fabrik för den. Inuti authManager
, det skapar igen den lämpliga drivrutinen, insvept runt a Vakt
klass, som fungerar på samma sätt som Lagra
klass från Session
.
Som tidigare, låt oss börja med att skapa en MongoUserProvider
:
config = $ config; $ connection_string = 'mongodb: //'; om ! tom ($ this-> config ['användarnamn']) &&! tomt ($ 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 ['databas'], $ this-> config ['collection']); / ** * Hämta en användare med sin unika identifierare. * * @param blandad $ identifierare * @return \ Illuminate \ Auth \ UserInterface | null * / allmän funktion retrieveById ($ identifierare) $ user_data = $ this-> collection-> findOne (array ('_id' => $ identifierare, )); om (! is_null ($ user_data)) returnera nya GenericUser ((array) $ user_data); / ** * Hämta en användare med angivna referenser. * * @param array $ credentials * @return \ Illuminate \ Auth \ UserInterface | null * / public function retrieveByCredentials (array $ credentials) // Försök att leta efter användaren först oavsett lösenord // Vi gör det i validateCredentials metod om (isset ($ credentials ['password'])) unset ($ credentials ['password']); $ user_data = $ this-> collection-> findOne ($ credentials); om (! is_null ($ user_data)) returnera nya GenericUser ((array) $ user_data); / ** * Validera en användare mot angivna referenser. * * @param \ Illuminate \ Auth \ UserInterface $ användare * @param array $ credentials * @return bool * / allmän funktion validateCredentials (UserInterface $ user, array $ credentials) om (! isset ($ credentials ['lösenord']) ) return false; returnera ($ credentials ['password'] === $ användare-> getAuthPassword ());
Det är viktigt att notera här att jag inte kontrollerar ett lösenord, det var för enkelhetens skull att göra det enklare för oss att skapa dummy-data och testa det senare. I produktionskod måste du se till att lösenordet har hash. Kolla in Illuminate \ Auth \ DatabaseUserProvider
klass för ett bra exempel på hur man gör det här.
Efteråt måste vi registrera vår anpassade drivrutinsanrop på authManager
. För att göra det måste vi uppdatera tjänsteleverantörens Registrera
metod:
/ ** * Registrera tjänsteleverantören. * * @return void * / public function register () $ this-> app-> bindShared ('auth', funktion ($ app) // När autentiseringstjänsten faktiskt har begärts av utvecklaren // en variabel i ansökan som indikerar sådant. Det hjälper oss // att vi behöver ställa in några kökkök i efterhand senare. $ app ['auth.loaded'] = true; $ auth_manager = ny AuthManager ($ app); $ auto [edit => $ app ['config'] -> get ('auth.mongo.username'), 'lösenord' => $ app ['config'] -> get ('auth.mongo.password'), 'databas' => $ app ['config'] -> få ('auth.mongo.database'), 'samling' => $ app ['config'] -> get ('auth.mongo.collection'))); ); returnera $ auth_manager;);
Slutligen behöver vi också uppdatera auth.php
konfigurationsfil för att utnyttja Mongo-drivrutinen, samt ge den rätt Mongo-konfigurationsvärdena:
'driver' => 'mongo', ... / ** * Mongo DB-inställningar * / 'mongo' => array ('host' => '127.0.0.1', 'användarnamn' => ", 'lösenord' => , 'database' => 'laravel', 'collection' => 'laravel_auth_collection')
Testa detta är lite svårare, för att göra det, använd Mongo DB CLI för att infoga en ny användare i samlingen:
mongo> använd laravel_auth bytt till db laravel_auth> db.laravel_auth_collection.insert (id: 1, email: "[email protected]", lösenord: "test_password")> db.laravel_auth_collection.find ()> "_id" : ObjectId ("530c609f2caac8c3a8e4814f"), "id" 1, "email": "[email protected]", "lösenord": "test_password"
Nu testa det genom att prova en Auth :: validera
metodsamtal:
var_dump (Auth :: validera (array ('email' => '[email protected]', 'lösenord' => 'test_password'))));
Detta bör dumpa en bool (true)
. Om det gör så har vi framgångsrikt skapat vår egen Auth-drivrutin!
Laravel Cache-komponenten hanterar cachemekanismer för användning i ramen. Liksom de båda komponenterna som vi har diskuterat använder den också Laravel Manager (märker du ett mönster?). Cacheskomponenten har drivrutiner för:
apc
memcached
redis
fil
- en filbaserad cache. Data sparas i app / lagring / cache
väg.databas
- databasbaserad cache. Data sparas i rader i databasen. Databasschemat beskrivs i Laravel-dokumentationen.array
- data "cachas" i en array. Tänk på att array
cacheminnet är inte ihållande och rensas på varje sidlast.Eftersom det här följer samma implementering som båda komponenterna som vi har diskuterat kan du säkert anta att tjänsteleverantören är ganska likadan:
/ ** * Registrera tjänsteleverantören. * * @return void * / public function register () $ this-> app-> bindShare ('cache', funktion ($ app) returnera nya CacheManager ($ app);); $ this-> app-> bindShared ('cache.store', funktion ($ app) return $ app ['cache'] -> drivrutin ();); $ this-> app-> bindShared ('memcached.connector', funktion () returnera ny MemcachedConnector;); $ This-> registerCommands ();
De Registrera()
metod här skapar en CacheManager
, Det fungerar igen som omslag och fabrik för förarna. Inom chefen slingrar den föraren runt en Repository
klass, som liknar Lagra
och Vakt
klasser.
Skapa MongoStore
, vilken bör förlänga Illuminate \ Cache \ StoreInterface
:
config = $ config; $ connection_string = 'mongodb: //'; om ! tom ($ this-> config ['användarnamn']) &&! tomt ($ 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 ['databas'], $ this-> config ['collection']); / ** * Hämta ett objekt från cachen med nyckel. * * @paramsträng $ key * @return mixed * / public function get ($ key) $ cache_data = $ this-> getObject ($ key); om (! $ cache_data) return null; returnera unserialize ($ cache_data ['cache_data']); / ** * Returnera hela objektet istället för bara cache_data * * @param string $ key * @return array | null * / skyddad funktion getObject ($ key) $ cache_data = $ this-> collection-> findOne ('key' => $ key,)); om (is_null ($ cache_data)) return null; om (isset ($ cache_data ['expire']) && time ()> = $ cache_data ['expire']) $ this-> glöm ($ key); returnera null; returnera $ cache_data; / ** * Spara ett objekt i cacheminnet under ett visst antal minuter. * * @param sträng $ key * @param blandat $ värde * @param int $ minuter * @return void * / public function put ($ key, $ värde, $ minuter) $ expiry = $ this-> utgång ); $ this-> collection-> update (array ('key' => $ nyckel), array ('$ set' => array ('cache_data' => serialize ($ värde), 'expiry' => $ expiry ttl '=> ($ minuter * 60))), array (' upsert '=> true,' multiple '=> false)); / ** * Öka värdet på ett objekt i cacheminnet. * * @param sträng $ key * @param blandat $ värde * @return void * * @throws \ LogicException * / allmän funktion inkrement ($ key, $ value = 1) $ cache_data = $ this-> getObject ($ key) ; om (! $ cache_data) $ new_data = array ('cache_data' => serialize ($ värde), 'expiry' => $ this-> utgången (0), 'ttl' => $ this-> utgången ); andra $ new_data = array ('cache_data' => serialize (unserialize ($ cache_data ['cache_data']) + $ värde), 'expiry' => $ this-> utgången ((int) ($ cache_data ['ttl '] / 60)),' ttl '=> $ cache_data [' ttl ']); $ this-> collection-> update (array ('key' => $ nyckel), array ('$ set' => $ new_data), array ('upsert' => true, 'multiple' => false)) ; / ** * Minska värdet på ett objekt i cacheminnet. * * @param sträng $ key * @param blandat $ värde * @return void * * @throws \ LogicException * / allmän funktion minskning ($ key, $ value = 1) $ cache_data = $ this-> getObject ($ key) ; om (! $ cache_data) $ new_data = array ('cache_data' => serialize ((0 - $ värde)), 'expiry' => $ this-> utgången (0), 'ttl' => $ this-> utgången (0)); $ $ new_data = array ('cache_data' => serialize (unserialize ($ cache_data ['cache_data']) - $ värde), 'expiry' => $ this-> utgå ((int) ($ cache_data ['ttl '] / 60)),' ttl '=> $ cache_data [' ttl ']); $ this-> collection-> update (array ('key' => $ nyckel), array ('$ set' => $ new_data), array ('upsert' => true, 'multiple' => false)) ; / ** * Spara ett objekt i cachen på obestämd tid. * * @param sträng $ key * @param blandat $ värde * @return void * / allmän funktion för alltid ($ key, $ value) return $ this-> put ($ key, $ value, 0); / ** * Ta bort ett objekt från cacheminnet. * * @param string $ key * @return void * / allmän funktion glömma ($ key) $ this-> collection-> remove (array ('key' => $ key)); / ** * Ta bort alla objekt från cacheminnet. * * @return void * / public function flush () $ this-> collection-> remove (); / ** * Få utgångstiden baserat på angivna minuter. * * @param int $ minutes * @return int * / skyddad funktionens utgång ($ minuter) if ($ minutes === 0) returnera 9999999999; returtid () + ($ minuter * 60); / ** * Hämta cache-nyckel prefixet. * * @returnsträng * / offentlig funktion getPrefix () return ";
Vi måste också lägga till Mongo-återuppringningen igen till chefen:
/ ** * Registrera tjänsteleverantören. * * @return void * / public function register () $ this-> app-> bindShare (cache), funktion ($ app) $ cache_manager = ny CacheManager ($ app); $ cache_manager-> extend ', funktion ($ app) returnera nya MongoStore (array (' host '=> $ app [' config '] -> get (' cache.mongo.host '),' användarnamn '=> $ app [' config ' ] -> få ('cache.mongo.username'), 'lösenord' => $ app ['config'] -> få ('cache.mongo.password'), 'database' => $ app ['config' ] -> få ('cache.mongo.database'), 'samling' => $ app ['config'] -> get ('cache.mongo.collection'));); returnera $ cache_manager;) ; $ this-> app-> bindShared ('cache.store', funktion ($ app) return $ app ['cache'] -> drivrutin ();); $ this-> app-> bindShared ('memcached.connector', funktion () returnera ny MemcachedConnector;); $ This-> registerCommands ();
Slutligen måste vi uppdatera cache.php
config-fil:
'driver' => 'mongo', ... / ** * Mongo DB-inställningar * / 'mongo' => array ('host' => '127.0.0.1', 'användarnamn' => ", 'lösenord' => , 'database' => 'laravel', 'collection' => 'laravel_cache_collection')
Försök nu att använda Cache :: sätta ()
och Cache :: få ()
metoder. Om det görs korrekt borde vi kunna använda MongoDB för att cache data!
I denna handledning lärde vi oss om följande:
Belysa
, som används av Laravel ramverket.Förhoppningsvis hjälper det programmerare att skapa egna drivrutiner och utöka den nuvarande funktionaliteten i Laravel-ramen.