CodeIgniter 是一个广泛使用的 PHP 框架,旨在帮助开发人员编写更好的结构化代码并从工作流程中删除样板任务。
在本文中,我将解释一些在使用 CodeIgniter 开发应用程序时使用的非常有用的技术。
为我们的应用程序创建库(或任何需要配置值的内容)时,我们经常需要使用配置参数,以便它能够执行其任务。这样做时,我们可以使用下面显示的代码片段来获取配置值。
$value = $this->config->item( 'some_item' );
如果我们只有几个配置参数,这很好,但是当我们需要提取十几个配置参数时,这种方式加载值可能会非常烦人。加载每个参数(例如我们在配置文件中使用的数组)不是很好吗?为了做到这一点,您需要按以下方式加载它。
$this->load->config( 'config_file', true ); $options = $this->config->item( 'config_file' ); // $options['some_item'];
通过这一行,我们的整个配置文件将被放置在 $options
数组中。为了进一步增加交易的难度,使用这种技术还可以确保避免配置文件中的名称冲突问题。这样,您的参数可以命名为您想要的任何名称,而不必担心其他配置文件。
在我们之前的观点的基础上,想象一个场景,我们希望在加载库时将参数从配置文件或选项数组传递到我们的库。也许我们在应用程序的不同部分使用相同的库,并且每个用例的配置选项不能相同。
为了能够做到这一点,请在您的库中放置一个私有 _options
成员并使用如下所示的构造函数。
private $_options = array(); public function __construct( $options = array() ) { if ( is_empty( $options ) ) { $this->load->config( 'config_file', true ); $options = $this->config->item( 'config_file' ); } $this->_options = $options; }
此后,您可以通过库中的私有 _options
数组访问您的参数,并且就像前面的示例一样,您已经避免了配置文件中的键的名称冲突问题。
通过您的应用发送 HTML 电子邮件的需求无处不在,无论是新闻通讯还是一些自动欢迎消息。通常,您可以通过在电子邮件对象的 message
参数中手动编码相应的 HTML 来完成此操作(已经完成了)。
嗯,众所周知,上面的方法非常丑陋。下面的技巧并不完全是一个技巧,而只是一种在有意义的情况下利用 CodeIgniter 某些功能的方法。
就我个人而言,我更喜欢这种方法,因为我管理一些需要发送新闻通讯和其他几封 HTML 电子邮件的网站,并且使用模板将显着简化该过程。
在应用程序的 views
文件夹中,创建一个名为 emails
的文件夹,并将您要发送的任何 HTML 电子邮件放入其中,并由电子邮件客户端呈现相应的结构。现在,在发送电子邮件的方法中,您可以使用以下代码:
public function send_mail() { $this->load->library( 'email' ); $this->email->from( 'jdoe@gmail.com', 'John Doe' ); $this->email->to( 'jane_doe@gmail.com' ); $this->email->subject( 'Some subject' ); $this->email->message( $this->load->view( 'emails/message', $data, true ) ); $this->email->send(); }
使用此技术时需要记住的一些重要事项:
data
对象应包含视图中使用的选项让我们面对现实:几乎每个最近的 PHP 应用程序都是后端服务或 API。如果您使用过 Google Maps API,您可能已经注意到 Google 允许我们传递一个版本参数,以便我们告诉它我们将使用哪个版本。
如果我们可以在 CodeIgniter 应用程序中执行此操作,不是很好吗?这样,我们就可以创建软件的新版本,同时支持旧版本以确保向后兼容性。
通过这种技术,我们将能够使用单个 CodeIgniter 安装来使用相同的索引文件处理应用程序的多个版本。我们可以通过在请求中传递 v
参数来选择版本。
要使其发挥作用,需要做一些事情。首先,我将重命名我的 application
文件夹。由于这是我的 API 的第一个版本,我将其简单命名为 1.0.0.
之后,我将重命名我的 index.php
文件,将其命名为 1.0.0.
并更改其中的 application_folder
行。将第 75 行替换为:
$application_folder = '1.0.0';
酷,现在我们的应用程序版本是 1.0.0。我们要调用 1.0.0.php
文件而不是索引吗?绝对不!让我们创建一个新的 index.php
文件并向其中添加以下代码。
define( 'API_VER', 'v' ); array_key_exists( API_VER, $_REQUEST ) ? $v = $_REQUEST[ API_VER ] : $v = '1.0.0'; if ( file_exists( "{$v}.php" ) ) { if ( is_dir( dirname( __FILE__ ) . "/{$v}" ) ) { require dirname( __FILE__ ) . "/{$v}.php"; } else { $error = new stdClass(); $error->error = true; $error->description = 'INVALID_API_VERSION'; echo json_encode( $error ); exit; } } else { $error = new stdClass(); $error->error = true; $error->description = 'INVALID_API_VERSION'; echo json_encode( $error ); exit; }
在这里,我们定义用于选择版本的参数。如果没有版本通过,我们使用1.0.0版本。如果某个版本通过了,我们会确保该版本有相应的文件和文件夹。否则,我们会抛出错误。
要添加更多版本,我们只需复制 1.0.0
文件夹和 1.0.0.php
文件,根据我们要创建的版本重命名它们,更改 文件中的 application_folder
变量并开始处理我们的 API 的下一版本。当我们觉得足够舒服时,我们可以通过修改 index.php
文件使其成为版本。
点符号?不,我不是在谈论 Objective-C 消息。如果您使用过 Twitter API 或类似的东西,您会记得在方法调用结束时,您可以指定您想要的响应格式。由于我非常喜欢使用 CodeIgniter 创建 RESTful 服务,因此我喜欢添加即使我一直使用 JSON,也可以为他们提供此功能。
为了做到这一点,我们需要利用 CodeIgniter 挂钩来预处理我们的 URI。我们将在此过程中使用两个钩子,并设置一个配置项来相应地设置响应格式。
首先,什么是钩子?根据 CodeIgniter 用户指南,
CodeIgniter Hooks 功能提供了一种在不破坏核心文件的情况下利用和修改框架内部工作方式的方法
简单来说,它们是改变应用程序正常执行流程的一种方法。尽管我们不想在这里精确地执行此操作,但我们确实希望在 CodeIgniter Router 类有机会检查 URI 之前对其进行预处理。考虑到这一点,我们将使用“pre_system”挂钩。
为了使用钩子,我们必须启用它们。为此,请打开 config
下的 config.php
文件,并将 enable_hooks
项设置为 true。
$config['enable_hooks'] = TRUE;
我们现在需要添加负责预路由过程的钩子。在应用程序文件夹中的 config
文件夹中,打开 hooks.php
文件并添加以下代码:
$hook['pre_system'] = array( 'class' => 'Router', 'function' => 'route', 'filename' => 'router.php', 'filepath' => 'hooks' );
这段代码的作用是告诉我们的应用程序运行 hooks
文件夹中 Router
类的 route
方法。这里快速说明一下: filepath
参数是包含您要调用的方法的文件的路径,并且它必须相对于您的应用程序文件夹没有尾部斜杠。
现在我们需要创建该钩子将要调用的类和方法。在 application
文件夹内的 hooks
文件夹(如果不存在,请创建它)中,创建一个新文件,将其命名为 router.php
并将以下代码放入其中。
if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); class Router { private static $_format = ''; public function route() { $request = strstr( $_SERVER['REQUEST_URI'], '?', true ); if ( !$request ) { $request = $_SERVER['REQUEST_URI']; } $parts = explode( '.', $request ); self::$_format = $parts[ sizeof($parts) - 1 ]; if ( self::$_format == 'json' || self::$_format == 'xml' || self::$_format == 'rss' || self::$_format == 'atom' ) { $_SERVER['REQUEST_URI'] = substr( $request, 0, ( strlen( $request ) - strlen( self::$_format ) - 1 ) ); } else { self::$_format = ''; } } }
CodeIgniter Hooks 功能提供了一种在不破坏核心文件的情况下利用和修改框架内部工作方式的方法
这里有几点需要注意。首先,您会注意到我使用静态类成员来存储请求的类型。这是因为我们正确地获取了响应格式,但我们无法将其告知应用程序的其余部分。在应用程序执行的早期阶段,配置类尚未加载,因此我们需要使用另一个钩子。考虑到这一点,我们需要将其设为静态,这样当我们调用下一个钩子时它就不会被覆盖。
一开始,我会检查 ?
符号,因此此处的重新路由不会与通过 URL 传递的任何参数发生冲突。 strstr
方法将返回字符串 BEFORE 该字符作为第三个参数设置为 true。请记住,此行为是在 PHP 5.3.0 中添加的,因此如果您使用的是以前的版本,则需要另一种方法来获取 ?
符号之前的字符串部分。
由于我们从 URI 检索请求的响应格式,然后为 CodeIgniter 路由器手动设置 REQUEST_URI
键,因此我们需要检查请求的输出是否有效。如果没有,我们让应用程序处理请求而不进行干扰。
现在我们已经识别了请求的响应格式,但我们的控制器不知道它。我认为通知这一点的一种干净方法是使用 config
参数。为了设置它,我们需要使用另一个钩子。前两个钩子是 pre_system
和 pre_controller
。
但是,此时我们无法使用 get_instance
方法,这意味着我们无法设置配置项,因此我们将使用 post_controller_constructor
挂钩。只要您不打算在控制器构造函数中使用响应格式配置项,此技术就可以工作。
在hooks.php
文件中的pre_system
钩子后添加以下代码。
$hook['post_controller_constructor'] = array( 'class' => 'Router', 'function' => 'config', 'filename' => 'router.php', 'filepath' => 'hooks' );
正如您所知,这个钩子正在调用同一类中的另一个方法,我们用它来检索请求的响应格式。在 Router
类中 route
方法之后(或之前),添加以下代码。
public function config() { $CI =& get_instance(); $CI->config->set_item( 'response_format', self::$_format ); }
在此方法中,我们设置一个名为 response_format
的配置选项,其格式在 route
方法中检索到。
最后,要在控制器(或应用程序中的任何位置)中使用此响应格式,请使用以下代码。
$format = $this->config->item( 'response_format' );
这样,您就可以检索请求的格式并相应地解析结果。至于解析响应,我将其作为练习留给读者。
我希望您发现其中一些技巧很有用。您可能已经注意到,我一直专注于 RESTful 服务,因为在我看来,它们是我们作为 PHP 开发人员应该关注的内容。
我期待您的评论,非常感谢您的阅读。