帮助PHP的bootstrap和regex

时间:2011-01-09 15:39:48

标签: php regex .htaccess bootstrapping

我正在开发一个新的PHP框架,供个人在未来的项目中使用,以及  下面是我计划的文件结构到目前为止。我只需要一些关于我的.htaccess文件的正则表达式的帮助,以及如何加载我想要的文件的一些帮助。

基本上,域之后的任何“文件夹”都应从我的“module”文件夹加载。  我想从 www.domain.com/module/account / 加载 www.domain.com/account / 。我也希望它以该格式存在于模块下的任何其他文件夹中。 “module”下的所有文件夹/文件都应该加载,就好像它位于顶层一样。

在这个示例中,虽然在我的module / account /文件夹中,如果我有一个名为home.php的文件,那么我应该能够通过 www.domain.com/account/home 来访问它 www.domain.com/module/account/home.php www.domain.com/module/user/register.php 实际上可以通过 www.domain.com/user/register

我希望这是有道理的,并感谢任何帮助和任何建议。我主要需要帮助.htaccess文件来使这个文件夹结构工作。我还没有决定是否应该通过单个索引文件访问所有文件,或者我是否应该在每个页面中包含一个引导程序类型文件。引导程序文件将设置所有变量,配置选项,以及自动加载所有类文件并创建所需的对象。

myFramework/
--/assets/
--------/css/
--------/images/
--------/javascript/
--/includes/
---------/classes/
---------/config/
---------/language/
---------/header.php
---------/footer.php
--/module/
--------/account/
----------------/create.php
----------------/login.php
----------------/logout.php
----------------/settings.php
----------------/editprofile.php
--------/admin/
--------/blog/
--------/forums/
--------/messages/
--------/users/
--index.php

5 个答案:

答案 0 :(得分:3)

jasonbar的答案实际上几乎就在那里。它所缺乏的只是处理你所描述的.php扩展名:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/module
RewriteCond %{REQUEST_URI} [.]php$
RewriteRule (.*)[.]php$ /module/$1

话虽这么说,我强烈建议您考虑前端控制器范例(正如您在问题描述中所述),因为这样做可以实现更大的控制,鼓励MVC方法等等。= o)

修改

我纠正了一些忽略的点,并添加了PHP扩展的正确处理。注意,最后的[L]参数导致进一步处理停止,使得这些代码块可用作.htaccess文件中的逻辑结构(即通过阻止随后的任何处理);如果不需要这样的功能,请删除该参数。

我还添加了一行来专门检查所请求的php文件是否确实存在。

RewriteEngine On

# if the uri matches a directory in the module dir, redirect to that. Disable 
# this block if you don't wish to have either directory browsing or to have the 
# default apache file load.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/module%{REQUEST_URI} -d
RewriteCond %{REQUEST_URI} !^/includes
RewriteCond %{REQUEST_URI} !^/assets
RewriteCond %{REQUEST_URI} !^/module
RewriteRule (.*) /module/$1 [L]

# if the uri matches a file sans the .php extension in the module directory, 
# then redirect to that.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/module%{REQUEST_URI}.php -f
RewriteCond %{REQUEST_URI} !^/includes
RewriteCond %{REQUEST_URI} !^/assets
RewriteCond %{REQUEST_URI} !^/module
RewriteRule (.*) /module/$1.php [L]

修改

要同时允许从模块目录提供以“.php”结尾的文件,请将以下内容添加到.htaccess文件中:

# if the uri matches a file with the .php extension in the module directory, 
# then redirect to that.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/module%{REQUEST_URI} -f
RewriteCond %{REQUEST_URI} !^/includes
RewriteCond %{REQUEST_URI} !^/assets
RewriteCond %{REQUEST_URI} !^/module
# note that the following line restricts access to php files only. comment out 
# the following line to allow any existing file under module director to be 
# accessed (or modify the following to allow other file extensions to be read)
RewriteCond %{REQUEST_URI} [.]php$  
RewriteRule (.*) /module/$1 [L]

答案 1 :(得分:3)

如果由我自己决定,我会尝试在PHP中解决这个问题。只需创建一个.htaccess文件,将每个可能的请求映射到单个文件(可能是index.php),并确定从那里做什么。这使您有机会在将请求委托给处理该请求的任何代码段之前进行各种引导和日志记录。您甚至可以包含并使用诸如Limonade之类的微框架来完成您想要的任务。这是一个例子:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d # if the requested directory does not exist,
RewriteCond %{REQUEST_FILENAME} !-f # and the requested file does not exist,
RewriteRule ^ index.php             # map everything to index.php. 

然后,在index.php中,您可以执行各种操作以确保获得正确的响应。使用“类似控制器的结构”的最简单方法是包含一个像Limonade这样的框架,然后使用它。一个例子:

<?php
require_once 'vendor/limonade.php';

dispatch( 'account/home', 'accountHome' );

function accountHome( ) {
    require_once 'modules/account/home.php';
}

run( );

显然,这只是一个建议。或者,您可以使用更简单的系统,虽然我猜您必须自己编写。这样你就可以说,如果文件存在于modules目录中,只需包含这个文件就可以了。就这样。

<?php
$path = isset( $_SERVER['PATH_INFO'] ) ? trim( $_SERVER['PATH_INFO'], '/' ) : null;
if( $path !== null ) {
    $filename = 'module/' . $path . '.php'; /** $path could be account/home */
    if( file_exists( $filename ) ) {
        require_once $filename;
    }
    else {
        require_once 'error.php';
    }
}
else {
    require_once 'home.php';
}

就是这样。功能齐全,全部。您可以使用一个可以为您排序的库来获益。

答案 2 :(得分:2)

在阅读完您的要求后,我提出了以下解决方案:

RewriteCond %{REQUEST_URI} !^/includes
RewriteCond %{REQUEST_URI} !^/assets
RewriteCond %{REQUEST_URI} !^/module
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteRule (.*)(\.php)?$ /module/$1

我已经使用Apache 2.2验证了这可以使用以下URL模式:

重定向到模块文件夹

http://local.sandbox.com/account/home.php?t=t
http://local.sandbox.com/account/home.php
http://local.sandbox.com/account/home.php/?t=t
http://local.sandbox.com/account/home?t=t
http://local.sandbox.com/account/home/?t=t
http://local.sandbox.com/account/home/
http://local.sandbox.com/account/home
http://local.sandbox.com/user/register
http://local.sandbox.com/user/register.php
http://local.sandbox.com/user/register?t=t
http://local.sandbox.com/user/register.php?t=t

不会重定向,因为这些URI被排除

http://local.sandbox.com/includes/header.php
http://local.sandbox.com/includes/header.php?t=t
http://local.sandbox.com/index.php?t=t
http://local.sandbox.com/?t=t

请注意,RewriteCondition本质上是一个由NOT条件组成的AND,因此您要从重写规则中排除的任何文件夹或文件都必须添加为NOT条件。

模块规则是包含在内的,这意味着您放置在模块文件夹中的任何新文件夹都将自动满足您的重写要求。

答案 3 :(得分:0)

如果我理解你,这应该有效。只有当请求的资源不是真实的文件/目录并且尚未从模块目录中请求时,这些条件才会导致它重定向。

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/module
RewriteRule (.*) /module/$1

答案 4 :(得分:0)

我正在开发一个带有同事的PHP框架,所以这真的引起了我的注意。

我们的.htaccess做出了极少量的假设。它看起来像这样:

DirectoryIndex index.php
RewriteEngine on
RewriteBase /

RewriteCond %{REQUEST_URI} \.png$
RewriteRule ^(.*)$ $1  [QSA,L]

RewriteCond %{REQUEST_URI} \.gif$
RewriteRule ^(.*)$ $1  [QSA,L]

RewriteCond %{REQUEST_URI} \.jpg$
RewriteRule ^(.*)$ $1  [QSA,L]

RewriteCond %{REQUEST_URI} \.js$
RewriteRule ^(.*)$ $1  [QSA,L]

RewriteCond %{REQUEST_URI} \.pdf$
RewriteRule ^(.*)$ $1  [QSA,L]

RewriteCond %{REQUEST_URI} \.css$
RewriteRule ^(.*)$ $1  [QSA,L]

RewriteCond %{REQUEST_URI} ^/favicon*
RewriteRule ^(.*)$ favicon.ico [QSA,L]

#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php?$1 [QSA,L]

index.php反过来,看起来像这样:

<?php

namespace System;

try
{
        ob_start();

        $Indium = include 'src/bootstrap/IndiumFactory.php';
        $Indium->run();
}
catch (\Exception $e) // catch errors and display/log
{
        Error::indium_exception_handler($e);
        Error::render_error_page();
}

IndiumFactory是设置环境的引导程序。 Indium是我们框架的名称。 IndiumFactory是从一组配置文件中自动生成的。

也许我应该澄清一下,Indium有一种机制,用于加载和调用正确的控制器类,其余的REQUEST_URI作为参数。我们的表单依赖于POST:ed数据,因此我们可以对URI施加相当严格的规则/过滤器。