Может войдёшь?
Черновики Написать статью Профиль

Вскрываем Laravel: компоненты Session, Auth и Cache

перевод

  1. 1. Введение
  2. 2. Компонент Session
    1. 2.1. Сервис-провайдеры
    2. 2.2. Создание собственного обработчика сессий
  3. 3. Компонент Auth
    1. 3.1. Создание собственного обработчика аутентификации
  4. 4. Компонент Cache
    1. 4.1. Создание собственного обработчика кэша
  5. 5. Заключение

За последние годы Laravel стал одним из самых известных фреймворков, который используют разработчики для создания своих приложений. Имея такую же популярность, какую имел CodeIgniter во время своего расцвета, Laravel славится своей простотой в использовании, удобством для начинающих и верностью отраслевым стандартам.

Введение

Почему-то немногие разработчики пользуются тем преимуществом, что Laravel — компонентная система. С момента перехода к компонентам на основе Composer, Laravel 4 стал очень модульной системой, похожей по разнообразию возможностей на более взрослые фреймворки, такие как Symfony. Такая группа компонентов, называемая PHPIlluminate, на мой взгляд, не является самим фреймворком, но представляет собой подборку библиотек, которые потенциально могут быть использованы фреймворком. Сам фреймворк Laravel представлен приложением-каркасом Laravel (который находится в репозитории на GitHub PHPlaravel/laravel), в котором эти компоненты используются для создания реальных веб-приложений.

В этом уроке мы углубимся в группу этих компонентов, узнаем, как они работают, как они используются фреймворком, и как мы можем расширить их возможности.

Компонент Session

Компонент Laravel Session обрабатывает сессии в веб-приложении. Он использует систему на основе драйверов, которая называется Laravel Manager и выступает как фабрика и как обертка для любого драйвера, указанного в файле конфигурации. На момент написания этой статьи в компоненте Session есть драйверы для:

  • file — драйвер сессии на основе файлов, в котором данные сессии хранятся в зашифрованном файле.
  • cookie — драйвер сессии на основе cookie, в котором данные сессии шифруются в пользовательские cookie.
  • database — данные сессии хранятся в БД, настроенной для приложения.
  • apc — данные сессии хранятся в APC.
  • memcached — данные сессии хранятся в Memcached.
  • redis — данные сессии хранятся в Redis.
  • array — данные сессии хранятся в массиве PHP. Обратите внимание на то, что драйвер сессии на основе массива не поддерживает хранение и обычно используется в консольных командах.

Сервис-провайдеры

Многие пользователи Laravel не осознают это, но большая часть того, как работает Laravel, находится внутри его сервис-провайдеров. Они по существу являются загрузочными файлами для каждого компонента и достаточно абстрагированы, поэтому пользователи могут загружать любые компоненты, любыми способами.

Вот краткое объяснение того, как это работает:

  1. Инициируется компонент приложения Laravel Application. Это основной драйвер всего фреймворка, отвечающий за обработку HTTP-запросов, запускающий сервис-провайдеры, а также выступающий в качестве контейнера зависимостей для фреймворка.
  2. После запуска сервис-провайдера вызывается его метод PHPregister. Это позволяет нам получать экземпляр любого компонента.
    • Помните, что у всех сервис-провайдеров есть доступ к основному приложению Laravel (через PHP$this->app), что позволяет им размещать экземпляры реализованных классов в контейнере зависимостей.
  3. Когда эти зависимости загружены, мы можем свободно использовать их, вызывая в контейнере, например, через систему фасадов Laravel Facade, PHPApp::make.

Вернемся к сессиям и взглянем на PHPSessionServiceProivider:

PHP
/**
    * Регистрация экземпляра менеджера сессий.
    *
    * @return void
    */
   
protected function registerSessionManager()
   {
       
$this->app->bindShared('session', function($app)
       {
           return new 
SessionManager($app);
       });
   }

   
/**
    * Регистрация экземпляра драйвера сессий.
    *
    * @return void
    */
   
protected function registerSessionDriver()
   {
       
$this->app->bindShared('session.store', function($app)
       {
           
// Сначала мы создадим менеджер сессий, который отвечает за
           // создание различных драйверов сессий, когда они нужны
           // экземпляру приложения, и будем работать с ними в режиме "ленивой" нагрузки.
           
$manager $app['session'];

           return 
$manager->driver();
       });
   }

Эти два метода вызываются функцией PHPregister(). Первый PHPregisterSessionManager() вызывается для начальной регистрации PHPSessionManager. Этот класс наследует PHPManager, который я упоминал выше. Второй PHPregisterSessionDriver() регистрирует обработчик сессий для менеджера на основе нашей конфигурации. В конечном итоге в классе PHPIlluminate\Support\Manager вызывается этот метод:

PHP
/**
     * Создание нового экземпляра драйвера.
     *
     * @param  string  $driver
     * @return mixed
     *
     * @throws \InvalidArgumentException
     */
    
protected function createDriver($driver)
    {
        
$method 'create'.ucfirst($driver).'Driver';

        
// Мы проверяем, существует ли метод-конструктор для данного драйвера. Если нет, мы
        // проверяем пользовательский конструктор драйвера, который позволяет пользователям создавать
        // драйверы, используя собственное замыкание.
        
if (isset($this->customCreators[$driver]))
        {
            return 
$this->callCustomCreator($driver);
        }
        elseif (
method_exists($this$method))
        {
            return 
$this->$method();
        }

        throw new \
InvalidArgumentException("Driver [$driver] not supported.");
    }

Здесь мы видим что, исходя из имени драйвера в файле конфигурации, вызывается определенный метод. Поэтому, если у нас настроено использование обработчика PHPfile-сессий, в классе PHPSessionManager будет вызван этот метод:

PHP
/**
     * Создание экземпляра драйвера file-сессий.
     *
     * @return \Illuminate\Session\Store
     */
    
protected function createFileDriver()
    {
        return 
$this->createNativeDriver();
    }

    
/**
     * Создание экземпляра драйвера file-сессий.
     *
     * @return \Illuminate\Session\Store
     */
    
protected function createNativeDriver()
    {
        
$path $this->app['config']['session.files'];

        return 
$this->buildSession(new FileSessionHandler($this->app['files'], $path));
    }

Затем класс драйвера вводится в класс PHPStore, который отвечает за вызов методов текущей сессии. Это позволяет нам отделить реализацию PHPSessionHandlerInterface от SPL в драйверах, класс PHPStore способствует этому.

Создание собственного обработчика сессий

Давайте создадим наш собственный обработчик для сессий MongoDB. Сначала нам надо создать PHPMongoSessionHandler внутри свежеустановленного проекта Laravel. (Мы позаимствуем его из PHPSymfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler):

PHP
<?php namespace Illuminate\Session;

    use 
Mongo;
    use 
MongoDate;
    use 
MongoBinData;

    class 
MongoSessionHandler implements \SessionHandlerInterface
    
{
        
/**
         * Настройки Mongo
         *
         * @var array
         */
        
protected $config;

        
/**
         * Соединение с Mongo
         *
         * @var \Mongo
         */
        
protected $connection;

        
/**
         * Коллекция Mongo
         *
         * @var \MongoCollection
         */
        
protected $collection;
        
/**
         * Создание нового экземпляра обработчика для Mongo.
         *
         * @param  array $config
         *  - $config['host']       Mongodb-хост
         *  - $config['username']   Mongodb-логин
         *  - $config['password']   Mongodb-пароль
         *  - $config['database']   Mongodb-БД
         *  - $config['collection'] Mongodb-коллекция
         * @return void
         */
        
public function __construct(array $config)
        {
            
$this->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}
         */
        
public function write($sessionId$data)
        {
            
$this->collection->update(
                array(
                    
'_id' => $sessionId
                
),
                array(
                    
'$set' => array(
                        
'session_data' => new MongoBinData($dataMongoBinData::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;
        }
    }

Вам надо сохранить его в папке PHPvendor/laravel/framework/src/Illuminate/Session. Для этого примера мы поместим его сюда, но правильнее размещать этот файл в пространстве имен его собственной библиотеки.

Далее нам надо убедиться в том, что класс PHPManager может вызвать этот драйвер. Это можно сделать с помощью метода PHPManager::extend. Откройте vendor/laravel/framework/src/Illuminate/Session/SessionServiceProvider.php и добавьте следующий код. Правильнее было бы наследовать сервис-провайдер, но это выходит за рамки данного урока.

PHP
/**
     * Установка обратного вызова драйвера 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')
            ));
        });
    }

Не забудьте обновить метод PHPregister() для вызова этого метода:

PHP
/**
     * Регистрация сервис-провайдера.
     *
     * @return void
     */
    
public function register()
    {
        
$this->setupDefaultDriver();

        
$this->registerSessionManager();

        
$this->setupMongoDriver();

        
$this->registerSessionDriver();
    }

Далее нам надо задать конфигурацию Mongo DB. Откройте app/config/session.php и задайте следующие настройки:

PHP
/**
     * Настройки Mongo DB
     */
    
'mongo' => array(
        
'host' => '127.0.0.1',
        
'username' => '',
        
'password' => '',
        
'database' => 'laravel',
        
'collection' => 'laravel_session_collection'
    
)

Пока мы в этом файле, нам также надо обновить настройку driver вверху:

PHP
'driver' => 'mongo'

Теперь попробуем зайти на главную страницу (обычно это localhost/somefolder/public). Если эта страница загружается без отображения страницы WHOOPS, тогда примите мои поздравления, мы успешно создали совершенно новый драйвер сессий! Протестируем его, задавая какие-либо данные о сессии через PHPSession::set(), и затем получая их обратно через PHPSession::get().

Компонент Auth

Компонент Laravel Auth выполняет проверку подлинности пользователя для фреймворка, а также управляет паролями. Компонент Laravel создает абстрактную интерпретацию типичной системы управления пользователями, которая используется в большинстве веб-приложений, и помогает программисту легко внедрить систему регистрации и входа. Как и компонент Session он использует Laravel Manager. В настоящее время компонент Auth имеет драйверы для:

  • eloquent — для использования встроенной в Laravel ORM, которая называется Eloquent. Он также использует готовый класс User.php из папки models.
  • database — для использования подключения к БД, которое настроено по умолчанию. Он использует класс PHPGenericUser для доступа к данным пользователя.

Поскольку этот компонент следует той же реализации, что и PHPSession, сервис-провайдер очень похож на тот, который мы видели вначале:

PHP
/**
     * Регистрация сервис-провайдера.
     *
     * @return void
     */
    
public function register()
    {
        
$this->app->bindShared('auth', function($app)
        {
            
// Когда разработчиком запрашивается служба аутентификации
            // мы задаем значение переменной в приложении для индикации этого. Это дает нам
            // знать, что нам надо будет задать некоторые очередные cookies в последующем событии.
            
$app['auth.loaded'] = true;

            return new 
AuthManager($app);
        });
    }

Здесь мы видим, что создается класс PHPAuthManager, который служит оберткой для используемого нами драйвера, а также выступает в качестве фабрики для него. Внутри PHPAuthManager он снова создает соответствующий драйвер, обернутый вокруг класса PHPGuard, который действует так же, как класс PHPStore из PHPSession.

Создание собственного обработчика аутентификации

Так же как раньше, давайте начнем с создания PHPMongoUserProvider:

PHP
<?php namespace Illuminate\Auth;

    use 
Mongo;
    use 
Illuminate\Hashing\HasherInterface;

    class 
MongoUserProvider implements UserProviderInterface {

        
/**
         * Экземпляр mongo
         *
         * @param  \Mongo
         */
        
protected $connection;

        
/**
         * Экземпляр подключения mongo
         *
         * @param  \MongoConnection
         */
        
protected $collection;

        
/**
         * Массив конфигурации Mongo
         *
         * @var array
         */
        
protected $config;

        
/**
         * Создание нового user-провайдера Mongo.
         *
         * @param  array $config
         *  - $config['host']       Mongodb-хост
         *  - $config['username']   Mongodb-логин
         *  - $config['password']   Mongodb-пароль
         *  - $config['database']   Mongodb-БД
         *  - $config['collection'] Mongodb-коллекция
         * @return void
         */
        
public function __construct(array $config)
        {
            
$this->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']);
        }

        
/**
         * Получение пользователя по его уникальному идентификатору.
         *
         * @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);
            }
        }

        
/**
         * Получение пользователя по введенным данным авторизации.
         *
         * @param  array  $credentials
         * @return \Illuminate\Auth\UserInterface|null
         */
        
public function retrieveByCredentials(array $credentials)
        {
            
// Попытка найти пользователя сначала независимо от пароля
            // Мы сделаем это в методе 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);
            }
        }

        
/**
         * Подтверждение пользователя на основе введенных данных авторизации.
         *
         * @param  \Illuminate\Auth\UserInterface  $user
         * @param  array  $credentials
         * @return bool
         */
        
public function validateCredentials(UserInterface $user, array $credentials)
        {
            if (!isset(
$credentials['password'])) {
                return 
false;
            }

            return (
$credentials['password'] === $user->getAuthPassword());
        }
    }

Важно заметить, что я не проверяю хешированный пароль, это сделано для упрощения примера, чтобы облегчить создание тестовых данных и дальнейшую проверку. В рабочем коде вам надо убедиться, что пароль хешируется. Замечательный пример того, как это сделать, есть в классе PHPIlluminate\Auth\DatabaseUserProvider.

После этого нам надо зарегистрировать наш обратный вызов драйвера в PHPAuthManager. Для этого нам необходимо обновить метод PHPregister сервис-провайдера:

PHP
/**
     * Регистрация сервис-провайдера.
     *
     * @return void
     */
    
public function register()
    {
        
$this->app->bindShared('auth', function($app)
        {
            
// Когда разработчиком запрашивается служба аутентификации
            // мы задаем значение переменной в приложении для индикации этого. Это дает нам
            // знать, что нам надо будет задать некоторые очередные cookies в последующем событии.
            
$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')
                    )
                );
            });

            return 
$auth_manager;
        });
    }

Наконец, нам также надо обновить файл конфигурации auth.php для использования драйвера Mongo, а также предоставить ему соответствующие значения конфигурации Mongo:

PHP
'driver' => 'mongo',
    ...
    ...
    ...
    
/**
     * Mongo DB settings
     */
    
'mongo' => array(
        
'host' => '127.0.0.1',
        
'username' => '',
        
'password' => '',
        
'database' => 'laravel',
        
'collection' => 'laravel_auth_collection'
    
)

Проверка будет немного сложнее, для этого используйте командную строку Mongo DB, чтобы вставить нового пользователя в коллекцию:

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

Теперь протестируем его, попробовав вызвать метод PHPAuth::validate:

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

Должно получиться bool(true). Если получилось, значит мы успешно создали свой собственный драйвер Auth!

Компонент Cache

Компонент Laravel Cache обрабатывает механизмы кэширования для использования в фреймворке. Как и оба рассмотренных компонента, он также использует Laravel Manager (заметили шаблон?). Компонент Cache имеет драйверы для:

  • apc
  • memcached
  • redis
  • file — кэш на основе файлов. Данные хранятся в папке app/storage/cache.
  • database — кэш на основе БД. Данные хранятся в строках в БД. Схема БД описана в документации Laravel.
  • array — данные кэшируются в массив. Помните, что кэш в массиве не сохраняется и зачищается при каждой загрузке страницы.

Поскольку используется та же реализация, что и в рассмотренных выше компонентах, вы можете с уверенностью предположить, что и сервис-провайдер очень похож:

PHP
/**
     * Регистрация сервис-провайдера.
     *
     * @return void
     */
    
public function register()
    {
        
$this->app->bindShared('cache', function($app)
        {
            return new 
CacheManager($app);
        });

        
$this->app->bindShared('cache.store', function($app)
        {
            return 
$app['cache']->driver();
        });

        
$this->app->bindShared('memcached.connector', function()
        {
            return new 
MemcachedConnector;
        });

        
$this->registerCommands();
    }

Здесь метод PHPregister() создает PHPCacheManager, который снова выступает в качестве обертки и фабрики для драйвера. В менеджере он оборачивает драйвер вокруг класса PHPRepository, подобно классам PHPStore и PHPGuard.

Создание собственного обработчика кэша

Создайте PHPMongoStore, который должен наследовать PHPIlluminate\Cache\StoreInterface:

PHP
<?php namespace Illuminate\Cache;

    use 
Mongo;

    class 
MongoStore implements StoreInterface
    
{
        
/**
         * Экземпляр mongo
         *
         * @param  \Mongo
         */
        
protected $connection;

        
/**
         * Экземпляр подключения mongo
         *
         * @param  \MongoConnection
         */
        
protected $collection;

        
/**
         * Массив конфигурации Mongo
         *
         * @var array
         */
        
protected $config;

        
/**
         * Создание нового хранилища кэша Mongo.
         *
         * @param  array $config
         *  - $config['host']       Mongodb-хост
         *  - $config['username']   Mongodb-логин
         *  - $config['password']   Mongodb-пароль
         *  - $config['database']   Mongodb-БД
         *  - $config['collection'] Mongodb-коллекция
         * @return void
         */
        
public function __construct(array $config)
        {
            
$this->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']);
        }

        
/**
         * Извлечение элемента из кэша по ключу.
         *
         * @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']);
        }

        
/**
         * Возвращение целого объекта, а не только cache_data
         *
         * @param  string  $key
         * @return array|null
         */
        
protected function getObject($key)
        {
            
$cache_data $this->collection->findOne(array(
                
'key' => $key,
            ));

            if (
is_null($cache_data)) {
                return 
null;
            }

            if (isset(
$cache_data['expire']) && time() >= $cache_data['expire']) {
                
$this->forget($key);
                return 
null;
            }

            return 
$cache_data;
        }

        
/**
         * Сохранение элемента в кэше на заданное количество минут.
         *
         * @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' => ($minutes 60)
                    )
                ),
                array(
                    
'upsert' => true,
                    
'multiple' => false
                
)
            );
        }

        
/**
         * Инкрементирование значения элемента в кэше.
         *
         * @param  string  $key
         * @param  mixed   $value
         * @return void
         *
         * @throws \LogicException
         */
        
public function 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
                
)
            );
        }

        
/**
         * Декрементирование значения элемента в кэше.
         *
         * @param  string  $key
         * @param  mixed   $value
         * @return void
         *
         * @throws \LogicException
         */
        
public function decrement($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
                
)
            );
        }

        
/**
         * Сохранение элемента в кэше на неопределенное время.
         *
         * @param  string  $key
         * @param  mixed   $value
         * @return void
         */
        
public function forever($key$value)
        {
            return 
$this->put($key$value0);
        }

        
/**
         * Удаление элемента из кэша.
         *
         * @param  string  $key
         * @return void
         */
        
public function forget($key)
        {
            
$this->collection->remove(array(
                
'key' => $key
            
));
        }

        
/**
         * Удаление всех элементов из кэша.
         *
         * @return void
         */
        
public function flush()
        {
            
$this->collection->remove();
        }

        
/**
         * Получение срока хранения на основе введенных минут.
         *
         * @param  int  $minutes
         * @return int
         */
        
protected function expiration($minutes)
        {
            if (
$minutes === 0) return 9999999999;

            return 
time() + ($minutes 60);
        }

        
/**
         * Получение префикса ключа кэша.
         *
         * @return string
         */
        
public function getPrefix()
        {
            return 
'';
        }
    }

Нам также надо снова добавить обратный вызов Mongo в менеджер:

PHP
/**
     * Регистрация сервис-провайдера.
     *
     * @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();
    }

Наконец, нам надо обновить файл конфигурации cache.php:

PHP
'driver' => 'mongo',
    
// ...

    /**
     * Mongo DB settings
     */
    
'mongo' => array(
        
'host' => '127.0.0.1',
        
'username' => '',
        
'password' => '',
        
'database' => 'laravel',
        
'collection' => 'laravel_cache_collection'
    
)

Теперь попробуем использовать методы PHPCache::put() и PHPCache::get(). Если все сделано правильно, то мы сможем использовать MongoDB для кэширования данных!

Заключение

В этом уроке мы изучили:

  • Систему на основе компонентов Laravel PHPIlluminate, используемую в фреймворке Laravel.
  • Сервис-провайдеры Laravel, и немного о том, как они работают.
  • Систему Laravel Manager, которая выступает в качестве обертки и фабрики для драйверов.
  • Компоненты Session, Auth и Cache, и как создавать драйверы для каждого из них.
  • Библиотеки Store, Guard и Repository, которые используют эти драйверы.

Надеюсь, это поможет программистам создавать их собственные драйверы и расширять имеющуюся функциональность фреймворка Laravel.

Как вы считаете, полезен ли этот материал? Да Нет

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.