滚动
1.4. 开始编写 MVC 框架
我们已经详细规划了框架应具备的结构,现在是时候开始实现我们的 MVC 框架了。首先,你需要一个 Web 服务器。你可以使用 Denwer,不过可能需要更新 PHP 版本。
你可以在此页面下载带有 PHP 5.5.20 的 Denwer:
https://drupalbook.org/ru/drupal/denwer-obnovlenie-php
或者从 GitHub 下载:
https://github.com/levmyshkin/denwer-php-5.5.20
我们的框架将从 index.php 文件开始运行,该文件会从注册器中获取实例,调用所需的控制器并将注册器结果传递给它。控制器反过来可以调用所需的模型。
模式实现
实现我们讨论过的设计模式有多种方式。我们将选择其中一种实现方法,以后你可以根据需要更改某些模式的实现方式。
首先,在之前的章节中我们已经讨论了框架的目录结构,因此现在你需要根据该结构创建相应的文件夹。
接下来创建文件 Registry/registry.class.php。在其中我们将编写注册器类:
<?php /** * 注册器对象 * 实现注册器(Registry)和单例(Singleton)模式 */ class Registry { /** 存储对象的数组 */ private static $objects = array(); /** 存储设置的数组 */ private static $settings = array(); /** 框架名称 */ private static $frameworkName = 'Framework version 0.1'; /** 注册器实例 */ private static $instance; /** 构造函数(私有) */ private function __construct() { } /** 单例访问方法 */ public static function singleton() { if( !isset( self::$instance ) ) { $obj = __CLASS__; self::$instance = new $obj; } return self::$instance; } /** 防止克隆对象 */ public function __clone() { trigger_error( '禁止克隆注册器对象', E_USER_ERROR ); } /** 将对象存入注册器 */ public function storeObject( $object, $key ) { require_once('objects/' . $object . '.class.php'); self::$objects[ $key ] = new $object( self::$instance ); } /** 从注册器中获取对象 */ public function getObject( $key ) { if( is_object ( self::$objects[ $key ] ) ) { return self::$objects[ $key ]; } } /** 存储注册器设置 */ public function storeSetting( $data, $key ) { self::$settings[ $key ] = $data; } /** 获取注册器设置 */ public function getSetting( $key ) { return self::$settings[ $key ]; } /** 获取框架名称 */ public function getFrameworkName() { return self::$frameworkName; } } ?>
那么注册器是如何工作的?它如何存储对象?
- 所有对象都保存在一个数组中。
- 当一个新对象被添加到注册器时,其对应的类文件会被引入,并创建该对象的实例,随后存入数组。
- 通过向
getObject
方法传递键名即可返回该对象。
如何防止创建注册器类的其他副本?
- 构造函数被声明为
private
,防止从外部直接实例化。 - 克隆对象会触发错误。
- 如果你需要在框架中访问注册器实例,可以通过静态方法
Registry::singleton()
获取它。
现在我们已经创建了注册器类,接下来编写 index.php 文件,它将作为框架的入口点并与注册器交互。
Index.php
index.php 是框架的启动文件。
稍后我们将通过 .htaccess 文件实现友好 URL(ЧПУ),但现在先来看看 index.php 的基本代码:
<?php /** * Framework * 框架加载器 - 框架的单一入口点 */ // 启动会话 session_start(); // 定义常量 define( "APP_PATH", dirname( __FILE__ ) ."/" ); define( "FW", true ); /** * 自动加载函数 * 当调用控制器时自动引入所需类 */ function __autoload( $class_name ) { require_once('Controllers/' . $class_name . '/' . $class_name . '.php' ); } // 引入注册器 require_once('Registry/registry.class.php'); $registry = Registry::singleton(); // 输出框架名称(用于测试) print $registry->getFrameworkName(); exit(); ?>
如果一切正常,页面上将显示以下信息:
Framework version 0.1
让我们来分析当前 index.php 的工作原理:
- 启动会话,以便在整个框架中读写数据。
- 定义框架的根目录常量,便于在任何地方引用路径。
- 设置自动加载机制,以便在调用控制器时自动引入对应文件。
- 引入并初始化注册器类。
- 输出框架名称以确认系统正常运行。