用 PHP5 打造简易的 MVC 架构

起始工作

启始档案用来做一般的启动工作,像定义常数、设定错误回报等级等等,我们起始档案的第一部份像这样:

<?phperror_reporting (E_ALL);

if (version_compare(phpversion(), ‘5.1.0’, ‘<‘) == true) { die (‘PHP5.1 Only’); }

// Constants:

define (‘DIRSEP’, DIRECTORY_SEPARATOR);

// Get site path

$site_path = realpath(dirname(__FILE__) . DIRSEP . ‘..’ . DIRSEP) . DIRSEP;

define (‘site_path’, $site_path);

在上面的例子中我们定义了一些常数,取得网站路径,还有确认PHP的版本是否比5.1还新。

接下来我们必须做的是设定Registry物件来保有我们所有的全域资料,registry物件会在我们的MVC系统里在所有的个别物件间传来传去,它是用来传送全域资料这样我们在系统中就不须用到’global’关键字或是$GLOBALS,你可以阅读这一篇“Using globals in PHP”来了解registry物件的资讯。

新增下面的程式码到startup.php档中,下面的程式码是从前一个例子来的:

$registry = new Registry;

假如你现在试着要执行系统,你会得到下面的错误:

Fatal error: Class ‘Registry’ not found in g:\Projects\PHPit\content\simple mvc php5\demo\includes\startup.php on line 12

不要太惊讶,因为我们尚未建构Registry类别,我们也没有将有Registry类别的档案含括进来,我们可以简单地使用include函式来含括但是让我们来使用PHP5的新功能:__autoload()。

这个__autoload()神奇函式用来动态载入类别,当PHP碰到不存在的类别时,它会优先呼叫__autoload()函式,只是当时会宣布错误,这个可以快速用来载入类别。

将下面的程式码放在前面的范例程式码

// For loading classesfunction __autoload($class_name) {

$filename = strtolower($class_name) . ‘.php’;
$file = site_path . ‘classes’ . DIRSEP . $filename;

if (file_exists($file) == false) {

return false;

}

include ($file);

}

我们的 __autoload()函式会取得类别名称,传递引数,并且确认是否有相同的档案名称在类别的目录中,假如档案没有存在,函式会传回false,而且致命的fatal错误仍会产生,但是假如档案存在,它就会被含括进来,也就是说这个类别会突然地在那,而且没有错误会产生。

我们尚未建构Registry类别,所以我们还是会得到一个错误,所以让我们做一些事来处理。

Creating the Registry class

Registry类别用在个别的物件之间传递全域的资料,而且只是一个小小的类别,通常不会有超过3个以上的小方法。

首先建立一个叫做’classes’的目录,然后新增一个’registry.php’档案,将下面的程式码放进registry.php:

<?phpClass Registry {

private $vars = array();

}

?>

我们现在已有一个Registry类别的架构,而我们所要做的就是新增方法,所有的Registry类别需要一个set()方法来设定资料,以及一个get()方法来取得资料,另外我们也可选择要不要新增一个remove()方法来移除资料,下面的程式码会新增这三个方法:

function set($key, $var) {if (isset($this->vars[$key]) == true) {
throw new Exception(‘Unable to set var `’ . $key . ‘`. Already set.’);

}

$this->vars[$key] = $var;

return true;

}

function get($key) {

if (isset($this->vars[$key]) == false) {

return null;

}

return $this->vars[$key];

}

function remove($var) {

unset($this->vars[$key]);

}

正如同你所看到的,这三个方法实在简单,他们所作的就是从$vars属性中设定、取得及删除事项,在set()方法中我们也确认特殊的key是否不存在,假如存在我们会丢出一个例外,这是为避免偶然地复写资料。

我们现在有一个完整的Registry类别,但是我们还没有要停止,我们要使用SPL的其中一个功能:ArrayAccess,SPL是Standard PHP Library的缩写,它是一个集合用来解决标准问题的介面及类别,SPL其中的一个介面ArrayAccess可以让阵列存取物件,看看下一段的程式码:

<?php$registry = new Registry;

// Set some data

$registry->set (‘name’, ‘Dennis Pallett’);

// Get data, using get()

echo $registry->get (‘name’);

// Get data, using array access

echo $registry[‘name’]

?>

阵列存取使得$registry看起来像是阵列即使它是物件,虽然ArrayAccess没有真正的用处,它可以让我们少key一些字这样子就不用一直使用->get(),要使用ArrayAccess首先你必须改变(“Class Registry”)的第一行,变成这样:

Class Registry Implements ArrayAccess {

Implements关键字用来实作介面,而那就是ArrayAccess的功能。

藉着实作ArrayAccess介面,这个类别也需要新增四个方法:

function offsetExists($offset) {return isset($this->vars[$offset]);
}

function offsetGet($offset) {

return $this->get($offset);

}

function offsetSet($offset, $value) {

$this->set($offset, $value);

}

function offsetUnset($offset) {

unset($this->vars[$offset]);

}

这些方法应该相当明显,更多的资讯可以在SPL documentation找到。

现在我们已经实作ArrayAccess,我们可以使用物件就像使用阵列一样,就像你在前面例子看到一样,也可以在下面例子看到:

<?php$registry = new Registry;

// Set some data

$registry->[‘name’] = ‘Dennis Pallett’;

// Get data, using get()

echo $registry->get (‘name’);

// Get data, using array access

echo $registry[‘name’]

?>

我们的Registry现在已经完成,而且假如你试着执行系统每件事应该都可以运作(虽然没有任何东西显示),我们的起始档案完成,我们可以移到我们MVC系统下一步:设定资料库功能,也叫做”Model”。

頁次: 1 2 3 4 5