Работая в качестве разработчика 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. Как я и обещал, мы продолжили создавать собственный драйвер на основе реального варианта использования, и я считаю, что это лучший способ понять новую концепцию.
Я хотел бы услышать, не могли бы вы придумать что-нибудь об этой захватывающей концепции!