Advertisement
  1. Code
  2. Web Development

Laravel Unwrapped: Sitzung, Authentifizierung und Cache

Scroll to top
Read Time: 20 min

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

In den letzten Jahren hat sich Laravel zu einem der bekanntesten Frameworks entwickelt, mit denen Softwareentwickler ihre Webanwendungen erstellen. Ähnlich wie die Popularität, die CodeIgniter in seiner Blütezeit genoss, wurde Laravel für seine Benutzerfreundlichkeit, Freundlichkeit für Anfänger und die Einhaltung von Industriestandards gelobt.

Einführung

Eine Sache, die nicht viele Programmierer nutzen, ist das komponentenbasierte System von Laravel. Seit seiner Umstellung auf Komponenten mit Komponistenunterstützung ist Laravel 4 zu einem sehr modularen System geworden, ähnlich der Ausführlichkeit ausgereifterer Frameworks wie Symfony. Dies wird als Illuminate-Gruppe von Komponenten bezeichnet, die meiner Meinung nach nicht das eigentliche Framework selbst ist, sondern eine Zusammenstellung von Bibliotheken, die ein Framework möglicherweise verwenden kann. Das eigentliche Framework von Laravel wird durch die Laravel-Skeleton-Anwendung (im GitHub-Repository von laravel/laravel) dargestellt, die diese Komponenten zum Erstellen einer Webanwendung verwendet.

In diesem Tutorial werden wir uns mit einer Gruppe dieser Komponenten befassen und lernen, wie sie funktionieren, wie sie vom Framework verwendet werden und wie wir ihre Funktionalität erweitern können.

Die Sitzungskomponente

Die Laravel-Sitzungskomponente verarbeitet Sitzungen für die Webanwendung. Es verwendet ein treiberbasiertes System namens Laravel Manager, das sowohl als Factory als auch als Wrapper für den in der Konfigurationsdatei festgelegten Treiber fungiert. Zum jetzigen Zeitpunkt verfügt die Sitzungskomponente über Treiber für:

  • file - Ein dateibasierter Sitzungstreiber, bei dem Sitzungsdaten in einer verschlüsselten Datei gespeichert werden.
  • cookie - Ein Cookie-basierter Sitzungstreiber, bei dem Sitzungsdaten in den Cookies des Benutzers verschlüsselt werden.
  • database - Sitzungsdaten werden in der für die Anwendung konfigurierten Datenbank gespeichert.
  • apc - Sitzungsdaten werden in APC gespeichert.
  • memcached - Sitzungsdaten werden in Memcached gespeichert.
  • redis - Sitzungsdaten werden in Redis gespeichert.
  • array - Sitzungsdaten werden in einem PHP-Array gespeichert. Beachten Sie, dass der Array-Sitzungstreiber keine Persistenz unterstützt und normalerweise nur in Konsolenbefehlen verwendet wird.

Dienstleister

Die meisten Laravel-Benutzer wissen nicht, aber ein großer Teil der Funktionsweise von Laravel liegt bei seinen Dienstleistern. Sie sind im Wesentlichen Bootstrap-Dateien für jede Komponente und sie sind so weit abstrahiert, dass Benutzer beliebige Komponenten auf beliebige Weise booten können.

Eine grobe Erklärung, wie dies funktioniert, finden Sie unten:

  1. Die Laravel-Anwendungskomponente wird initiiert. Dies ist der Haupttreiber des gesamten Frameworks, der für die Verarbeitung der HTTP-Anforderung, die Ausführung der Dienstanbieter sowie als Abhängigkeitscontainer für das Framework verantwortlich ist.
  2. Sobald ein Dienstanbieter ausgeführt wird, wird seine register-Methode aufgerufen. Auf diese Weise können wir die gewünschte Komponente instanziieren.
    • Beachten Sie, dass alle Dienstanbieter Zugriff auf die Hauptanwendung von Laravel haben (über $this->app), mit der Dienstanbieter Instanzen der aufgelösten Klassen in den Abhängigkeitscontainer verschieben können.
  3. Sobald diese Abhängigkeiten geladen sind, sollten wir sie verwenden können, indem wir den Container beispielsweise über Laravels Facade-System App::make aufrufen.

Gehen wir zurück zu den Sitzungen und werfen einen kurzen Blick auf den 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
	}

Diese beiden Methoden werden von der Funktion register() aufgerufen. Der erste, registerSessionManager(), wird aufgerufen, um den SessionManager zunächst zu registrieren. Diese Klasse erweitert den oben erwähnten Manager. Das zweite, registerSessionDriver(), registriert einen Sitzungshandler für den Manager, basierend auf dem, was wir konfiguriert haben. Dies ruft schließlich diese Methode in der Klasse Illuminate\Support\Manager auf:

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
	}

Von hier aus können wir sehen, dass basierend auf dem Namen des Treibers aus der Konfigurationsdatei eine bestimmte Methode aufgerufen wird. Wenn wir es für die Verwendung des file-Sitzungshandlers konfiguriert haben, ruft es diese Methode in der SessionManager-Klasse auf:

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
	}

Die Treiberklasse wird dann in eine Store-Klasse eingefügt, die für den Aufruf der eigentlichen Sitzungsmethoden verantwortlich ist. Auf diese Weise können wir die Implementierung des SessionHandlerInterface von der SPL in die Treiber trennen. Die Store-Klasse erleichtert dies.

Erstellen eines eigenen Sitzungshandlers

Lassen Sie uns unseren eigenen Session Handler erstellen, einen MongoDB Session Handler. Zunächst müssen wir einen MongoSessionHandler in einer neu installierten Laravel-Projektinstanz erstellen. (Wir werden viel von 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
    }

Sie sollten dies im Ordner vendor/laravel/framework/src/Illuminate/Session speichern. Für die Zwecke dieses Projekts werden wir es hier einfügen, aber im Idealfall sollte sich diese Datei in einem eigenen Bibliotheks-Namespace befinden.

Als nächstes müssen wir sicherstellen, dass die Manager-Klasse diesen Treiber aufrufen kann. Wir können dies tun, indem wir die Manager::extend-Methode verwenden. Öffnen Sie vendor/laravel/framework/src/Illuminate/Session/SessionServiceProvider.php und fügen Sie den folgenden Code hinzu. Im Idealfall sollten wir den Dienstanbieter erweitern, dies liegt jedoch außerhalb des Bereichs dieses Lernprogramms.

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
	}

Stellen Sie sicher, dass Sie die register()-Methode aktualisieren, um diese Methode aufzurufen:

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
	}

Als nächstes müssen wir die Mongo DB-Konfiguration definieren. Öffnen Sie app/config/session.php und definieren Sie die folgenden Konfigurationseinstellungen:

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
	)

Während wir uns in dieser Datei befinden, sollten wir auch die driver-Konfiguration oben aktualisieren:

1
'driver' => 'mongo'

Versuchen Sie nun, auf die Hauptseite zuzugreifen (normalerweise localhost/somefolder/public). Wenn diese Seite geladen wird, ohne die WHOOPS-Seite anzuzeigen, dann herzlichen Glückwunsch, wir haben erfolgreich einen brandneuen Sitzungstreiber erstellt! Testen Sie es, indem Sie einige Dummy-Daten in der Sitzung über Session::set() festlegen und dann über Session::get() zurücksenden.

Die Auth-Komponente

Die Laravel Auth-Komponente übernimmt die Benutzerauthentifizierung für das Framework sowie die Kennwortverwaltung. Die Laravel-Komponente hat hier eine abstrakte Interpretation des typischen Benutzerverwaltungssystems erstellt, das in den meisten Webanwendungen verwendet werden kann, was wiederum dem Programmierer hilft, ein Anmeldesystem einfach zu implementieren. Wie die Sitzungskomponente wird auch der Laravel-Manager verwendet. Derzeit verfügt die Auth-Komponente über Treiber für:

  • eloquent - dies nutzt Laravels eingebautes ORM namens Eloquent. Es wird auch die vorgefertigte User.php-Klasse im models-Ordner verwendet.
  • database - Hierbei wird die standardmäßig konfigurierte Datenbankverbindung verwendet. Es verwendet eine GenericUser-Klasse für den Zugriff auf die Benutzerdaten.

Da dies der gleichen Implementierung wie die Session-komponente folgt, ist der Dienstanbieter dem, was wir oben gesehen haben, sehr ähnlich:

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
	}

Hier können wir sehen, dass im Grunde genommen eine AuthManager-Klasse erstellt wird, die den von uns verwendeten Treiber umschließt und als Factory dafür fungiert. Im AuthManager wird erneut der entsprechende Treiber erstellt, der um eine Guard-Klasse gewickelt ist und sich genauso verhält wie die Store-Klasse aus Session.

Erstellen eines eigenen Auth-Handlers

Beginnen wir wie zuvor mit der Erstellung eines MongoUserProviders:

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 ist wichtig zu beachten, dass ich nicht gegen ein Hash-Passwort prüfe. Dies wurde der Einfachheit halber durchgeführt, um es uns zu erleichtern, Dummy-Daten zu erstellen und diese später zu testen. Im Produktionscode müssen Sie sicherstellen, dass Sie das Kennwort hashen. In der Klasse Illuminate\Auth\DatabaseUserProvider finden Sie ein hervorragendes Beispiel dafür.

Anschließend müssen wir unseren benutzerdefinierten Treiberrückruf im AuthManager registrieren. Dazu müssen wir die register-Methode des Dienstanbieters aktualisieren:

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
	}

Zuletzt müssen wir auch die Konfigurationsdatei auth.php aktualisieren, um den Mongo-Treiber verwenden zu können, und ihm die richtigen Mongo-Konfigurationswerte bereitstellen:

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
	)

Das Testen ist etwas schwieriger. Verwenden Sie dazu die Mongo DB-CLI, um einen neuen Benutzer in die Sammlung einzufügen:

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" }

Testen Sie es jetzt, indem Sie einen Auth::validate-Methodenaufruf ausprobieren:

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

Dies sollte einen bool(true) ausgeben. Wenn ja, haben wir erfolgreich unseren eigenen Auth-Treiber erstellt!

Die Cache-Komponente

Die Laravel-Cache-Komponente verwaltet Caching-Mechanismen zur Verwendung im Framework. Wie die beiden Komponenten, die wir besprochen haben, wird auch der Laravel-Manager verwendet (bemerken Sie ein Muster?). Die Cache-Komponente verfügt über Treiber für:

  • apc
  • memcached
  • redis
  • file - ein dateibasierter Cache. Daten werden im Pfad app/storage/cache gespeichert.
  • database - Datenbankbasierter Cache. Daten werden in Zeilen in der Datenbank gespeichert. Das Datenbankschema ist in der Laravel-Dokumentation beschrieben.
  • array - Daten werden in einem Array "cached". Beachten Sie, dass der array-Cache nicht persistent ist und bei jedem Laden der Seite gelöscht wird.

Da dies der gleichen Implementierung folgt wie die beiden Komponenten, die wir besprochen haben, können Sie davon ausgehen, dass der Dienstanbieter ziemlich ähnlich ist:

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
	}

Die register()-Methode erstellt hier einen CacheManager, der wiederum als Wrapper und Factory für die Treiber fungiert. Innerhalb des Managers wird der Treiber um eine Repository-Klasse gewickelt, ähnlich wie bei den Store- und Guard-Klassen.

Erstellen eines eigenen Cache-Handlers

Erstellen Sie den MongoStore, der das Illuminate\Cache\StoreInterface erweitern soll:

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
    }

Wir müssen dem Manager auch den Mongo-Rückruf erneut hinzufügen:

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
	}

Zuletzt müssen wir die Konfigurationsdatei cache.php aktualisieren:

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
	)

Versuchen Sie nun, die Methoden Cache::put() und Cache::get() zu verwenden. Wenn es richtig gemacht wird, sollten wir MongoDB verwenden können, um die Daten zwischenzuspeichern!

Abschluss

In diesem Tutorial haben wir Folgendes gelernt:

  • Laravels komponentenbasiertes System namens Illuminate, das vom Laravel-Framework verwendet wird.
  • Laravel Service Providers und ein bisschen darüber, wie sie funktionieren.
  • Laravels Manager-System, das sowohl als Wrapper als auch als Factory für die Treiber fungiert.
  • Sitzungs-, Authentifizierungs- und Cache-Komponenten und Erstellen neuer Treiber für jede Komponente.
  • Store-, Guard- und Repository-Bibliotheken, die diese Treiber verwenden.

Hoffentlich hilft dies Programmierern dabei, ihre eigenen Treiber zu erstellen und die aktuelle Funktionalität des Laravel-Frameworks zu erweitern.

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.