作为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
文件,如下所示。
<?php
$config['media_services'] = array('youtube', 'vimeo');
$config['media_default'] = 'youtube';
它表明我们将实现两个适配器-YouTube和Vimeo。 默认适配器设置为YouTube。
继续并使用以下内容创建文件application/libraries/MediaRenderer/MediaRendererInterface.php
。
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MediaRendererInterface
*/
interface MediaRendererInterface
{
public function display($id);
}
如您所见,这是一个非常基本的接口,可确保实现此接口的适配器必须实现display方法。
接下来,让我们看一下MediaRenderer
驱动程序文件。 继续并使用以下内容创建文件application/libraries/MediaRenderer/MediaRenderer.php
。
<?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
接口。
由于每笨司机的标准,我们班MediaRenderer
扩展CI_Driver_Library
该类可确保我们可以使用
CI_Driver_Library
类中定义的load_driver
方法轻松访问驱动程序适配器。
接下来,让我们仔细看一下构造函数。
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
方法的代码。
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
接口的实现,因此可以确保每个驱动程序都必须实现display方法。
接下来,让我们看一下setAdapter
方法。
public function setAdapter($adapter)
{
$this->_adapter = $adapter;
return $this;
}
如您所见,如果您暂时想使用其他适配器,它仅用于覆盖默认适配器设置。
最后,有一个display
方法可以调用相应适配器的显示方法。
public function display($id)
{
return $this->{$this->_adapter}->display($id);
}
再说一遍,我想说您可以跳过display方法的实现,因为您总是可以直接调用适配器的display方法,正如我们将在本文后面看到的那样。 但是,我想通过MediaRenderer
类的display方法访问适配器,因为在这里您可以重构适配器可能实现的通用代码。
这就是您可以使用的MediaRenderer
类。
创建适配器
我们讨论驱动程序适配器已有一段时间了,现在是时候实际实现它们了。
让我们从application/libraries/MediaRenderer/drivers/MediaRenderer_youtube.php
的YouTube适配器文件开始。
<?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_youtube
类,即使它不扩展MediaRenderer
直接类。
除此之外,很容易理解display
方法的实现,只要将媒体ID作为方法的参数传递,它就会返回嵌入代码。
Vimeo适配器类与YouTube完全相同。 继续在application/libraries/MediaRenderer/drivers/MediaRenderer_vimeo.php
创建一个。
<?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
。
<?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
,这就是以下代码片段的作用。
$this->load->driver('mediaRenderer');
要访问我们刚刚加载的自定义驱动程序,应使用$this->mediarenderer
语法。 重要的是要注意,驱动程序的名称必须小写,与实际的驱动程序名称无关。
接下来,让我们检查以下代码的作用。
echo $this->mediarenderer->display("0GfCP5CWHO0");
它首先调用MediaRenderer
类的display
方法,因为它将控件委托给相应适配器的display
方法,该适配器在mediarenderer配置文件中设置为默认适配器。 最终,它最终调用了YouTube适配器的display
方法,因为在我们这里是默认适配器。
另一方面,如果要调用任何特定适配器的显示方法,则始终可以显式地执行该操作,如以下代码片段所示。
echo $this->mediarenderer->setAdapter('vimeo')->display("225434434");
如前所述,您也可以直接调用任何特定适配器的display
方法,而无需通过MediaRenderer
类的display
方法。
echo $this->mediarenderer->vimeo->display("225434434");
echo $this->mediarenderer->youtube->display("0GfCP5CWHO0");
因此,这就是您应该同时调用驱动程序及其适配器的原因,这要归功于驱动程序结构,该结构允许您根据需要即时插入新适配器。
就是这样。 我希望您喜欢这篇文章,并且可以随时单击“评论”部分来表达您的想法和疑虑。
结论
今天,本文将介绍在CodeIgniter框架中遍历驱动程序的过程。
与往常一样,本文从基本介绍CodeIgniter框架中的驱动程序概念开始。 如我所言,我们继续基于实际用例创建自定义驱动程序,我相信这是理解新概念的最佳方法。
我很想听听您是否可以就这个令人兴奋的概念提出一些建议!
翻译自: https://code.tutsplus.com/tutorials/how-to-create-custom-drivers-in-codeigniter--cms-29339