Статьи

Как создать пользовательские драйверы в CodeIgniter

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

Я хотел бы услышать, не могли бы вы придумать что-нибудь об этой захватывающей концепции!