Advertisement
  1. Code
  2. CodeIgniter

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

Scroll to top
Read Time: 8 min

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Работая в качестве разработчика 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
<?php
2
$config['media_services'] = array('youtube', 'vimeo');
3
$config['media_default'] = 'youtube';

Это означает, что мы собираемся реализовать два адаптера - YouTube и Vimeo. Адаптер по умолчанию установлен на YouTube.

Далее создайте application/libraries/MediaRenderer/MediaRendererInterface.php со следующим содержимым.

1
<?php
2
defined('BASEPATH') OR exit('No direct script access allowed');
3
4
/**

5
 * MediaRendererInterface

6
 */
7
interface MediaRendererInterface
8
{
9
    public function display($id);
10
}

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

Затем давайте посмотрим на файл драйвера MediaRenderer. Далее создайте application/libraries/MediaRenderer/MediaRenderer.php со следующим содержимым.

1
<?php
2
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
3
interface_exists('MediaRendererInterface', FALSE) OR require_once(APPPATH.'/libraries/MediaRenderer/MediaRendererInterface.php');
4
5
/**

6
 * MediaRenderer Class

7
 */
8
class MediaRenderer extends CI_Driver_Library {
9
    
10
  public $valid_drivers;
11
  public $CI;
12
  protected $_adapter = 'youtube';
13
14
  /**

15
   * Class constructor

16
   */
17
  public function __construct()
18
  {
19
    $this->CI =& get_instance();
20
    $this->CI->config->load('mediarenderer');
21
    $this->valid_drivers = $this->CI->config->item('media_services');
22
    $this->_adapter = $this->CI->config->item('media_default');
23
  }
24
25
  /**

26
   * Overrided __get method to check if the adapter implements MediaRendererInterface interface

27
   * @see CI_Driver_Library::__get()

28
   */
29
  public function __get($child)
30
  {
31
      if (in_array($child, $this->valid_drivers))
32
      {
33
          $object = $this->load_driver($child);
34
          
35
          if ($object instanceof MediaRendererInterface)
36
          {
37
              return $object;
38
          }
39
          else
40
          {
41
              show_error("MediaRenderer: Adapter '".$child."' doesn't implement MediaRendererInterface. Aborting.");
42
              return;
43
          }
44
      }
45
      else
46
      {
47
                show_error('Unable to load the requested adapter: '.$child);
48
                return;
49
      }
50
  }
51
52
  /**

53
   * @param string $adapter Adapter name

54
   * @return MediaRenderer

55
   */
56
  public function setAdapter($adapter)
57
  {
58
      $this->_adapter = $adapter;
59
      return $this;
60
  }
61
62
  /**

63
   * @param string $id Media ID

64
   */
65
  public function display($id)
66
  {
67
      return $this->{$this->_adapter}->display($id);
68
  }
69
70
}

В начале файла мы добавляем интерфейс MediaRendererInterface, который мы уже определили ранее в этом разделе.

В соответствии со стандартами драйвера CodeIgniter наш класс MediaRenderer расширяет класс CI_Driver_Library, который позволяет легко получить доступ к адаптерам драйверов, используя метод load_driver, определенный в классе CI_Driver_Library.

Затем давайте посмотрим на конструктор.

1
public function __construct()
2
{
3
  $this->CI =& get_instance();
4
  $this->CI->config->load('mediarenderer');
5
  $this->valid_drivers = $this->CI->config->item('media_services');
6
  $this->_adapter = $this->CI->config->item('media_default');
7
}

Вспомните файл конфигурации mediarenderer, который мы определили ранее, и это точно загружено в конструкторе в первую очередь. Необходимо, чтобы вы установили список адаптеров, которые поддерживаются драйвером, в свойство valid_drivers, поэтому мы просто это и сделали. И, наконец, для удобства мы установили значение драйвера по умолчанию для свойства _adapter.

Двигаясь дальше, давайте рассмотрим код метода __get.

1
public function __get($child)
2
{
3
    if (in_array($child, $this->valid_drivers))
4
    {
5
        $object = $this->load_driver($child);
6
        
7
        if ($object instanceof MediaRendererInterface)
8
        {
9
            return $object;
10
        }
11
        else
12
        {
13
            show_error("MediaRenderer: Adapter '".$child."' doesn't implement MediaRendererInterface. Aborting.");
14
            return;
15
        }
16
    }
17
    else
18
    {
19
            show_error('Unable to load the requested adapter: '.$child);
20
            return;
21
    }
22
}

Я бы сказал, что вы не обязаны переопределять этот метод, и наш драйвер будет работать отлично, и без него. Причиной внедрения этого метода в нашем случае является обеспечение реализации интерфейса MediaRendererInterface, и поэтому он будет следить за тем, чтобы каждый драйвер должен реализовать метод display.

Затем давайте посмотрим на метод setAdapter.

1
public function setAdapter($adapter)
2
{
3
    $this->_adapter = $adapter;
4
    return $this;
5
}

Как вы можете видеть, он просто используется для переопределения настроек адаптера по умолчанию, если вы хотите использовать другой адаптер в настоящее время.

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

1
public function display($id)
2
{
3
    return $this->{$this->_adapter}->display($id);
4
}

Опять же, я бы сказал, что вы можете пропустить реализацию этого метода, поскольку вы всегда можете вызвать метод отображения адаптера напрямую, как мы увидим далее в этой статье. Тем не менее, я хотел бы получить доступ к адаптерам с помощью метода отображения класса MediaRenderer, поскольку это место, где вы могли бы реорганизовать общий код, который может реализовать адаптер.

Таким образом, в вашем распоряжении был класс MediaRenderer.

Создаем адаптеры

Некоторое время мы обсуждали адаптеры драйверов, и теперь пришло время их реализовать.

Начнем с файла адаптера YouTube в приложении application/libraries/MediaRenderer/drivers/MediaRenderer_youtube.php.

1
<?php
2
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
3
4
/**

5
 * MediaRenderer_youtube Class

6
 */
7
class MediaRenderer_youtube extends CI_Driver implements MediaRendererInterface {
8
9
  /**

10
   * @param string $id Media ID

11
   * @see MediaRendererInterface::display()

12
   */
13
  public function display($id)
14
  {
15
    if ($id)
16
    {
17
      return '<iframe width="420" height="315" src="//www.youtube.com/embed/'.$id.'" frameborder="0"

18
allowfullscreen></iframe>';
19
    }
20
  }
21
22
}

Важно отметить, что имя адаптера имеет префикс MediaRenderer_, а также расширяет класс CI_Driver. Кроме того, он реализует интерфейс MediaRendererInterface, чтобы убедиться, что мы придерживаемся стандартов, которые мы обсуждали ранее.

Причина, по которой наш класс адаптера расширяет класс CI_Driver, заключается в использовании всех родительских методов и свойств. Вы правильно расслышали, вы можете получить доступ к методам и свойствам класса MediaRenderer из класса MediaRenderer_youtube, даже если он не распространяется непосредственно на класс MediaRenderer.

Кроме того, довольно легко понять реализацию метода display, который возвращает код вставки при условии, что медиа-идентификатор передается в качестве аргумента метода.

Класс адаптера Vimeo довольно похож на класс YouTube. Идем дальше и создаем его в application/libraries/MediaRenderer/drivers/MediaRenderer_vimeo.php.

1
<?php
2
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
3
4
/**

5
 * MediaRenderer_vimeo Class

6
 */
7
class MediaRenderer_vimeo extends CI_Driver implements MediaRendererInterface {
8
    
9
    /**

10
     * @param string $id Media ID

11
     * @see MediaRendererInterface::display()

12
     */
13
  public function display($id)
14
  {
15
      if ($id)
16
      {
17
      return '<iframe width="420" height="247" src="//player.vimeo.com/video/'.$id.'"></iframe>';
18
      }
19
  }
20
21
}

И на этом заканчиваем обсуждение адаптеров.

Все вместе

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

Начнем с создания файла контроллера application/controllers/Media.php.

1
<?php
2
defined('BASEPATH') OR exit('No direct script access allowed');
3
4
/**

5
 * Media Controller Class

6
 */
7
class Media extends CI_Controller {
8
  public function index()
9
  {
10
    // this will use default adapter as per the config file

11
    $this->load->driver('mediaRenderer');
12
    
13
    // IMP: it must be a lowercase drivername when you use it

14
    echo $this->mediarenderer->display("0GfCP5CWHO0");
15
    
16
    // override adapter settings by setting it explicitly

17
    echo $this->mediarenderer->setAdapter('vimeo')->display("225434434");
18
    
19
    // access the adapter directly

20
    echo $this->mediarenderer->vimeo->display("225434434");
21
    echo $this->mediarenderer->youtube->display("0GfCP5CWHO0");
22
  }
23
}

Первое, что нам нужно сделать, это загрузить наш собственный драйвер mediaRenderer, и это то, что делает следующий фрагмент.

1
$this->load->driver('mediaRenderer');

Чтобы получить доступ к только что загруженному пользовательскому драйверу, вы должны использовать синтаксис $this->mediarenderer. Важно отметить, что имя драйвера указано в нижнем регистре, независимо от фактического имени драйвера.

Затем давайте рассмотрим, что делает следующий код.

1
echo $this->mediarenderer->display("0GfCP5CWHO0");

Он вызывает метод display класса MediaRenderer в первую очередь, поскольку он делегирует элемент управления методу display соответствующего адаптера, установленного в качестве адаптера по умолчанию в файле конфигурации медиаредактора. В конце концов, он делает вызов метода display адаптера YouTube, поскольку в нашем случае это адаптер по умолчанию.

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

1
echo $this->mediarenderer->setAdapter('vimeo')->display("225434434");

Как я уже упоминал ранее, вы также можете напрямую вызвать метод display любого конкретного адаптера, не пройдя метод отображения класса MediaRenderer.

1
echo $this->mediarenderer->vimeo->display("225434434");
2
echo $this->mediarenderer->youtube->display("0GfCP5CWHO0");

Таким образом, вы должны вызвать драйвер и его адаптеры рядом - благодаря структуре драйвера, которая позволяет вам подключать новые адаптеры «на лету» по мере необходимости.

И на этом все. Я надеюсь, что вам понравилась статья, и вы всегда можете попасть в раздел комментариев, чтобы выразить свои мысли и проблемы.

Заключение

Путешествие по драйверам фреймворка CodeIgniter было темой сегодняшней статьи.

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

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

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.