滚动
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 的工作原理:
- 启动会话,以便在整个框架中读写数据。
- 定义框架的根目录常量,便于在任何地方引用路径。
- 设置自动加载机制,以便在调用控制器时自动引入对应文件。
- 引入并初始化注册器类。
- 输出框架名称以确认系统正常运行。