PHP 的引导程序和正则表达式帮助

发布于 2024-10-10 18:46:01 字数 1232 浏览 4 评论 0原文

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

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

在这个例子中,虽然在我的 module/account/ 文件夹中,如果我有一个名为 home.php 的文件,那么我应该能够使用 www.domain.com/account/home 而不是 访问它。 >www.domain.com/module/account/home.phpwww.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

I am working on a new PHP framework for personal use in future projects, and
below is my planned file structure so far. I just need some help with some regex for my .htaccess file and some help for how I can load the files I want.

Basically, any "folder" after the domain should load from my "module" folder.
I would like to have it load www.domain.com/account/ from www.domain.com/module/account/. I also want it in that format for any other folder I have under modules. All folders/files under "module" should load as if it were in the top level.

In this example though in my module/account/ folder, if I have a file called home.php then I should be able to access it with www.domain.com/account/home instead of www.domain.com/module/account/home.php, and www.domain.com/module/user/register.php would actually be accessed by www.domain.com/user/register

I hope this makes sense and appreciate any help and any advice. I mainly need help with the .htaccess file to make this folder structure work. I have not decided if all files should be accessed though a single index file or if I should just include a bootstrap type file into every page. The bootstrap file would set up all variables, config options, as well as auto load all class files and create objects needed.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

别闹i 2024-10-17 18:46:01

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]

The answer from jasonbar is actually almost there. All it lacks is dealing with the .php extension as you described:

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

That being said, I'd strongly encourage you to consider a front controller paradigm (as you eluded to in your problem description) as doing so allows for much greater control, encourages an MVC approach, etc. =o)

EDIT:

I corrected a few neglected points and added proper processing of the PHP extension. Note that the [L] argument at the end causes further processing to cease, making these code blocks useful as logical structures within your .htaccess file (i.e. by preventing any processing that follows); remove that argument if such functionality is not desired.

I've also added a line to specifically check that the php file being requested actually exists.

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]

EDIT:

To also allow files that end in ".php" to be served from the module directory, add the following to your .htaccess file:

# 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]
一袭水袖舞倾城 2024-10-17 18:46:01

如果由我决定的话,我会尝试用 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( );

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

<?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';
}

就是这样。功能齐全,一应俱全。不过,您可以从使用一个为您解决所有问题的库中受益。

I'd try to solve this in PHP itself, if it were up to me. Just create a .htaccess file that maps every possible request to a single file (probably index.php), and determine what to do from there. That gives you an opportunity to do all kinds of bootstrapping and logging before delegating the request to whatever piece of code should handle that request. You could even include and use a micro framework such as Limonade to accomplish what you want. Here's an example:

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. 

Then, in index.php, you can do a wide variety of things to make sure you get the correct response. The simplest way to use a "controller like structure", would be to include a framework such as Limonade, and use it. An example:

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

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

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

run( );

Obviously, that is just a suggestion. Alternatively, you could just make use of an even simpler system, although I guess you'd have to write that yourself. That way you can say, if the file exists in the modules directory, just include this file, and that's that.

<?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';
}

That's it. Fully functional and all. You could benefit from using a library that sorts this all out for you though.

从来不烧饼 2024-10-17 18:46:01

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

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 条件。

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

After reading your requirements, I have come up with the following solution:

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

I have verified this works with the following URL patterns using Apache 2.2:

Redirects to module folder:

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

Doesn't redirect as these URI's are excluded:

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

Note that the RewriteCondition is essentially an AND consisting of NOT conditions, so any folder or file that you want to exclude from the rewrite rule must be added as a NOT condition.

The module rule is inclusive, meaning that any new folders you place in the module folder will automatically be subject to your rewrite requirements.

新雨望断虹 2024-10-17 18:46:01

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

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

If I understand you, this should work. The conditions will cause it to redirect only when the requested resource isn't a real file / directory and when it isn't already requested from the module directory.

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/module
RewriteRule (.*) /module/$1
鹤舞 2024-10-17 18:46:01

我正在和一位同事一起开发一个 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 施加相当严格的规则/过滤器。

I'm developing a PHP framework with a collegue so this really caught my attention.

Our .htaccess makes a minimal amount of assumptions. It looks like this:

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 in turn, looks like this:

<?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 is the bootstrapper which sets up the environment. Indium is the name of our framework. IndiumFactory is autogenerated from a set of config files.

Maybe I should clarify that Indium has a mechanism for loading and calling the correct controller class with the rest of REQUEST_URI as the arguments. Our forms rely on POST:ed data, so we can impose rather strict rules/filters on the URI.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文