我对自动加载功能有问题,这是一个场景:
注意:MVC框架不是我自己的。我只是用它来学习更多关于OOP和MVC的知识。
第一,相关档案。
.htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /phoenix/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?%{QUERY_STRING} [NE,L]
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>
index.php:
<?php require_once('./application/LOADER.php'); ?>
application/LOADER.hp:
<?php
chdir(dirname(__FILE__));
require_once('./config/func_main.php');
require_once('./conf_system.php');
session_start();
ob_start('ob_gzhandler', 6);
$load = new Boot();
$load->LOAD();
?>
conf_system.php:
<?php
$C = new stdClass;
$C->INCPATH = dirname(__FILE__) . '/';
if( ! file_exists($C->INCPATH.'conf_main.php') ) {
exit;
}
require_once($C->INCPATH.'conf_main.php');
chdir( $C->INCPATH );
?>
conf_main.hp:
<?php
// Site Address Here:
$S->DOMAIN = 'site.com';
$S->SITE_URL = 'http://site.com/myMVC/';
?>
在config/func_main.php中:
function __autoload($class_name) {
global $C;
require_once( $C->INCPATH.'libs/lib_'.$class_name.'.php' );
}
libs/libs_Boot.php:
class Boot {
public function __construct() {
$this->controller = $GLOBALS['C']->INCPATH . 'controllers/';
$this->request = array();
}
public function LOAD() {
$this->_parse_input();
$this->_load_controller();
$this->load_template();
}
private function _parse_input() {
/* Here is the logic to get the controller name. */
$request = explode('/', ...);
$this->request = $request[2];
}
private function _load_controller() {
require_once( $this->controller.$this->request.'.php' );
$controller = new $this->request;
}
public function load_template($name) {
global $C, $D;
require 'view/header.php';
require 'view/' . $name . '.php';
require 'view/footer.php';
}
}
controllers/index.php:
<?php $this->load_template('index');?>
在视图文件夹中,只有HTML文件。
我知道应该有一个index
类,但我想使用Boot类中的函数。例如:
public function redirect($loc, $abs=FALSE) {
global $C;
if( ! $abs && preg_match('/^http(s)?':'/'//', $loc) ) {
$abs = TRUE;
}
if( ! $abs ) {
if( $loc{0} != '/' ) {
$loc = $C->SITE_URL.$loc;
}
}
if( ! headers_sent() ) {
header('Location: '.$loc);
}
echo '<meta http-equiv="refresh" content="0;url='.$loc.'" />';
echo '<script type="text/javascript"> self.location = "'.$loc.'"; </script>';
exit;
}
因此,在controller/index.php中,我可以写:
<?php
if (/* the user is not logged in */) {
$this->redirect('signin');
}
$this->load_template('index');
?>
一切都在一定程度上起作用。我看到了视图,但有一个错误:
**警告:require_sonce(/home/novacl/public_html/myMMVC/application/libs/lib_index.php)[function.requestonce]:无法打开流:在第6行/home/novicl/public_html/myMMVC/config/func_main.php中没有这样的文件或目录**
第6行在__autoload
函数中。
那么为什么会发生这种情况呢?如果索引控制器(controller/index.php)更改为:
class index {
function __construct(){
$this->load_template('index');
}
}
我不能使用它,因为load_template
不是index
的方法,它是Boot
类的方法。。
发生了什么?
__autoload
。错误消息指示代码正试图在某个地方创建名为"index"的类。如果它存在于示例代码中,那么它可能是$controller = new $this->request;
。您需要在此行之前包含一个定义类"index"的文件。前面的行require_once( $this->controller.$this->request.'.php' );
就是这样做的一个地方,正如您所确定的那样。
至于这使得index.php中的调用$this->load_template('index')
不起作用,在任何情况下都不应该这样做。首先,类的实现应该包含在一个文件中;否则,您的代码就不是很有凝聚力。另一方面,$this
是文件中的一个自由变量,在代码清晰度方面,它几乎和全局变量一样糟糕。相反,应该有一个Boot
调度器将调用的标准控制器方法;CCD_ 12的主体是实现的良好候选者。
如果你不能更改控制器基类(你可能无法控制框架代码,但你可以创建自己的fork,这取决于许可),你可以创建一个丑陋的破解,定义一个索引类,并调用类之外的任何其他代码:
<?php
class index {
}
$this->load_template('index');
然而,从设计的角度来看,这是非常可怕的。除了前面的原因(分散的实现、自由变量)之外,它在一个明显的全局范围内执行代码,而这个范围实际上是函数范围。库代码应该只定义事物,而不是直接执行代码,因为这可能会导致范围混乱。
您应该做的一件事是在__autoload
中添加对file_exists
的调用,以防止试图包含不存在的文件。但是,除非您也应用上述修复程序,否则这可能会导致"未找到类索引"的致命错误。即使这样也比目前的情况更可取,因为它会给你一个更相关的错误。
请注意,建议使用spl_autoload_register
而不是定义__autoload
函数,因为前者允许多个自动加载函数。文档中指出__autoload
将来可能会被删除。
class index {
function - construct(){
$this->load_template('index');
}
不是有效的PHP代码。你能更改触发错误的代码,然后粘贴完整的代码吗。