Работая в качестве разработчика CodeIgniter, вы, возможно, сталкивались с концепцией библиотеки, которая обогащает функциональность базовой платформы, а сам CodeIgniter предоставляет множество полезных библиотек в ядре.
Точно так же драйвер — это особый вид библиотеки, который позволяет добавлять пользовательские функции, так что основной класс драйвера действует как родительский класс, а адаптеры рассматриваются как дочерние классы.
Лучший способ понять концепцию драйверов — посмотреть, как кэширование реализовано в базовой структуре CodeIgniter. Основной класс Cache действует как родительский класс и расширяет класс CI_Driver_Library. С другой стороны, вы в конечном итоге найдете дочерние классы для APC, Memcached, Redis и т.п., реализованные в виде сменных адаптеров. Дочерние классы расширяют класс CI_Driver вместо основного класса драйвера.
Прелесть этого подхода в том, что вы можете легко расширить функциональность драйвера, добавив новый адаптер по мере необходимости. Как и в случае с кэшированием, если вам нужно добавить собственную стратегию кэширования, вы просто в шаге от ее реализации в виде специального адаптера.
Создание пользовательского драйвера в приложении CodeIgniter — цель сегодняшней статьи. В ходе этого мы рассмотрим реальный пример, который создает драйвер MediaRenderer, используемый для рендеринга медиа из различных сервисов, таких как YouTube, Vimeo и аналогичных. Различные сервисы будут реализованы в виде классов адаптеров.
Настройка файла
Драйвер, который мы собираемся реализовать в этой статье, называется MediaRenderer. Давайте кратко рассмотрим список файлов, необходимых для желаемой настройки:
-
application/libraries/MediaRenderer/MediaRendererInterface.php
: это интерфейс, который должен реализовать адаптер. -
application/config/mediarenderer.php
: файл конфигурации, в котором хранятся настройки, связанные с нашим пользовательским драйвером. -
application/libraries/MediaRenderer/MediaRenderer.php
: это класс, который расширяет CI_Driver_Library и используется для работы с различными адаптерами, доступными в приложении. -
application/libraries/MediaRenderer/drivers/MediaRenderer_youtube.php
: это класс, который реализует адаптер YouTube. -
application/libraries/MediaRenderer/drivers/MediaRenderer_vimeo.php
: это класс, который реализует адаптер Vimeo. -
application/controllers/Media.php
: это класс контроллера, который мы реализуем, чтобы продемонстрировать использование нашего пользовательского драйвера.
Вот список файлов, которые мы собираемся реализовать в этой статье.
Создать драйверы
В этом разделе мы создадим базовые файлы нашего пользовательского драйвера.
Первое, что нам нужно сделать, это определить файл конфигурации нашего пользовательского драйвера. Давайте определим файл application/config/mediarenderer.php
как показано ниже.
1
2
3
|
<?php
$config[‘media_services’] = array(‘youtube’, ‘vimeo’);
$config[‘media_default’] = ‘youtube’;
|
Это указывает на то, что мы собираемся реализовать два адаптера — YouTube и Vimeo. Адаптер по умолчанию установлен на YouTube.
Создайте файл application/libraries/MediaRenderer/MediaRendererInterface.php
со следующим содержимым.
01
02
03
04
05
06
07
08
09
10
|
<?php
defined(‘BASEPATH’) OR exit(‘No direct script access allowed’);
/**
* MediaRendererInterface
*/
interface MediaRendererInterface
{
public function display($id);
}
|
Как видите, это довольно простой интерфейс, который гарантирует, что адаптер, реализующий этот интерфейс, должен реализовывать метод отображения.
Далее, давайте посмотрим на MediaRenderer
драйвера MediaRenderer
. Создайте файл application/libraries/MediaRenderer/MediaRenderer.php
со следующим содержимым.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
<?php
if ( ! defined(‘BASEPATH’)) exit(‘No direct script access allowed’);
interface_exists(‘MediaRendererInterface’, FALSE) OR require_once(APPPATH.’/libraries/MediaRenderer/MediaRendererInterface.php’);
/**
* MediaRenderer Class
*/
class MediaRenderer extends CI_Driver_Library {
public $valid_drivers;
public $CI;
protected $_adapter = ‘youtube’;
/**
* Class constructor
*/
public function __construct()
{
$this->CI =& get_instance();
$this->CI->config->load(‘mediarenderer’);
$this->valid_drivers = $this->CI->config->item(‘media_services’);
$this->_adapter = $this->CI->config->item(‘media_default’);
}
/**
* Overrided __get method to check if the adapter implements MediaRendererInterface interface
* @see CI_Driver_Library::__get()
*/
public function __get($child)
{
if (in_array($child, $this->valid_drivers))
{
$object = $this->load_driver($child);
if ($object instanceof MediaRendererInterface)
{
return $object;
}
else
{
show_error(«MediaRenderer: Adapter ‘».$child.»‘ doesn’t implement MediaRendererInterface. Aborting.»);
return;
}
}
else
{
show_error(‘Unable to load the requested adapter: ‘.$child);
return;
}
}
/**
* @param string $adapter Adapter name
* @return MediaRenderer
*/
public function setAdapter($adapter)
{
$this->_adapter = $adapter;
return $this;
}
/**
* @param string $id Media ID
*/
public function display($id)
{
return $this->{$this->_adapter}->display($id);
}
}
|
В начале файла мы MediaRendererInterface
интерфейс MediaRendererInterface
который мы уже определили ранее в этом разделе.
Согласно стандартам драйвера CodeIgniter, наш класс MediaRenderer
расширяет CI_Driver_Library
класс, обеспечивающий
load_driver
доступ к адаптерам драйверов с load_driver
метода load_driver
определенного в классе CI_Driver_Library
.
Далее, давайте внимательно посмотрим на конструктор.
1
2
3
4
5
6
7
|
public function __construct()
{
$this->CI =& get_instance();
$this->CI->config->load('mediarenderer');
$this->valid_drivers = $this->CI->config->item('media_services');
$this->_adapter = $this->CI->config->item('media_default');
}
|
Вспомните файл конфигурации mediarenderer, который мы определили ранее, и он точно загружен в конструктор. Требуется, чтобы вы установили список адаптеров, поддерживаемых драйвером, в свойство valid_drivers
, поэтому мы просто сделали это. И, наконец, мы установили значение драйвера по умолчанию для свойства _adapter
для нашего удобства.
Двигаясь дальше, давайте добавим код метода __get
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public function __get($child)
{
if (in_array($child, $this->valid_drivers))
{
$object = $this->load_driver($child);
if ($object instanceof MediaRendererInterface)
{
return $object;
}
else
{
show_error("MediaRenderer: Adapter '".$child."' doesn't implement MediaRendererInterface. Aborting.");
return;
}
}
else
{
show_error('Unable to load the requested adapter: '.$child);
return;
}
}
|
Я бы сказал, что вам не нужно переопределять этот метод, и наш драйвер будет работать без него. Причиной реализации этого метода в нашем случае является обеспечение реализации интерфейса MediaRendererInterface
, и, таким образом, он будет гарантировать, что каждый драйвер должен реализовывать метод отображения.
Далее, давайте посмотрим на метод setAdapter
.
1
2
3
4
5
|
public function setAdapter($adapter)
{
$this->_adapter = $adapter;
return $this;
}
|
Как видите, он просто используется для переопределения настроек адаптера по умолчанию, если вы хотите использовать другой адаптер в настоящее время.
Наконец, есть метод display
который вызывает метод отображения соответствующего адаптера.
1
2
3
4
|
public function display($id)
{
return $this->{$this->_adapter}->display($id);
}
|
Опять же, я бы сказал, что вы можете пропустить реализацию метода display, так как вы всегда можете вызвать метод display адаптера напрямую, как мы увидим позже в этой статье. Тем не менее, я хотел бы получить доступ к адаптерам через метод MediaRenderer
класса MediaRenderer
как это место, где вы могли бы реорганизовать общий код, который может реализовать адаптер.
Так что это был класс MediaRenderer
в вашем распоряжении.
Создать адаптеры
Некоторое время мы обсуждали адаптеры драйверов, и теперь пришло время их реализовать.
Начнем с файла адаптера YouTube в application/libraries/MediaRenderer/drivers/MediaRenderer_youtube.php
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* MediaRenderer_youtube Class
*/
class MediaRenderer_youtube extends CI_Driver implements MediaRendererInterface {
/**
* @param string $id Media ID
* @see MediaRendererInterface::display()
*/
public function display($id)
{
if ($id)
{
return '<iframe width="420" height="315" src="//www.youtube.com/embed/'.$id.'" frameborder="0"
allowfullscreen></iframe>';
}
}
}
|
Важно отметить, что имя адаптера имеет префикс MediaRenderer_
, а также расширяет класс CI_Driver
. Кроме того, он реализует интерфейс MediaRendererInterface
чтобы убедиться, что мы придерживаемся стандартов, которые мы обсуждали ранее.
Причина, по которой наш класс адаптера расширяет класс CI_Driver
заключается в использовании всех родительских методов и свойств. Вы правильно MediaRenderer
, вы можете получить доступ к методам и свойствам класса MediaRenderer
из класса MediaRenderer_youtube
даже если он не расширяет класс MediaRenderer
напрямую.
Кроме того, довольно легко понять реализацию метода display
, который возвращает код для встраивания при условии, что идентификатор носителя передается в качестве аргумента метода.
Класс адаптера Vimeo очень похож на класс YouTube. Создайте его в application/libraries/MediaRenderer/drivers/MediaRenderer_vimeo.php
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* MediaRenderer_vimeo Class
*/
class MediaRenderer_vimeo extends CI_Driver implements MediaRendererInterface {
/**
* @param string $id Media ID
* @see MediaRendererInterface::display()
*/
public function display($id)
{
if ($id)
{
return '<iframe width="420" height="247" src="//player.vimeo.com/video/'.$id.'"></iframe>';
}
}
}
|
На этом обсуждение адаптеров заканчивается.
Собираем все вместе
В последних двух разделах мы обсудили классы драйверов и адаптеров. В этом разделе, который является последним в этой статье, мы расширим наш путь, чтобы пройти через демонстрацию базового использования драйвера.
Начнем с создания файла контроллера application/controllers/Media.php
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Media Controller Class
*/
class Media extends CI_Controller {
public function index()
{
// this will use default adapter as per the config file
$this->load->driver('mediaRenderer');
// IMP: it must be a lowercase drivername when you use it
echo $this->mediarenderer->display("0GfCP5CWHO0");
// override adapter settings by setting it explicitly
echo $this->mediarenderer->setAdapter('vimeo')->display("225434434");
// access the adapter directly
echo $this->mediarenderer->vimeo->display("225434434");
echo $this->mediarenderer->youtube->display("0GfCP5CWHO0");
}
}
|
Первое, что нам нужно сделать, это загрузить наш собственный драйвер mediaRenderer
, и это то, что делает следующий фрагмент.
1
|
$this->load->driver('mediaRenderer');
|
Для доступа к пользовательскому драйверу, который мы только что загрузили, вы должны использовать синтаксис $this->mediarenderer
. Важно отметить, что имя драйвера в нижнем регистре, независимо от фактического имени драйвера.
Далее давайте рассмотрим, что делает следующий код.
1
|
echo $this->mediarenderer->display("0GfCP5CWHO0");
|
В первую очередь он вызывает метод MediaRenderer
класса MediaRenderer
, в котором он делегирует элемент управления методу display
соответствующего адаптера, который установлен в качестве адаптера по умолчанию в файле конфигурации mediarenderer. В конце концов он вызывает метод display
адаптера YouTube, так как это адаптер по умолчанию в нашем случае.
С другой стороны, если вы хотите вызвать метод отображения любого конкретного адаптера, вы всегда можете сделать это явно, как показано в следующем фрагменте.
1
|
echo $this->mediarenderer->setAdapter('vimeo')->display("225434434");
|
Как я упоминал ранее, вы также можете вызывать метод display любого конкретного адаптера напрямую, не проходя через метод MediaRenderer
класса MediaRenderer
.
1
2
|
echo $this->mediarenderer->vimeo->display("225434434");
echo $this->mediarenderer->youtube->display("0GfCP5CWHO0");
|
Так вот как вы должны вызывать драйвер и его адаптеры вместе - благодаря структуре драйвера, которая позволяет вам подключать новые адаптеры на лету по мере необходимости.
И это в значительной степени так. Я надеюсь, что вам понравилась статья, и вы всегда можете посетить раздел комментариев, чтобы высказать свои мысли и опасения.
Вывод
Путешествие по драйверам в среде CodeIgniter было рецептом сегодняшней статьи.
Как всегда, статья началась с базового введения в концепцию драйверов в среде CodeIgniter. Как я и обещал, мы продолжили создавать собственный драйвер на основе реального варианта использования, и я считаю, что это лучший способ понять новую концепцию.
Я хотел бы услышать, не могли бы вы придумать что-нибудь об этой захватывающей концепции!