Slim(PHP)RESTful API的Apache重写规则

Slim(PHP)RESTful API的Apache重写规则,apache,.htaccess,rest,mod-rewrite,slim,Apache,.htaccess,Rest,Mod Rewrite,Slim,我在配置restfulapi(使用slimphp和雄辩的ORM)以正确重写URL时遇到了一些问题 我的项目目录结构如下所示: wwwroot/ myproject/ api/ (maintained in its own Git repo) app/ data/ lib/ models/ routes/

我在配置restfulapi(使用slimphp和雄辩的ORM)以正确重写URL时遇到了一些问题

我的项目目录结构如下所示:

wwwroot/
    myproject/
        api/ (maintained in its own Git repo)
            app/
                data/
                lib/
                models/
                routes/
                app.php (where Slim is instantiated and used)
                config.php (holds database settings, etc.)
            public/
                .htaccess (#1)
                index.php (includes ../app/app.php)
            vendor/
            .htaccess (#2, this be empty yo)
        ngapp/ (future Angular.js app)
        webapp/ (future standard web app)
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
.htaccess
(#1)包含以下标准规则:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
这使得API可以通过
http://localhost/myproject/api/public/
。但是,我希望通过如下URL访问API:
http://localhost/myproject/api/
。我该怎么做

(也可以随意评论我的总体项目结构。我正在尝试学习如何用一种我现在很少使用的语言开发RESTful API,因为我是一名.NET/JS开发人员,使用两个我以前从未涉足过的框架(API)适用于网络和移动设备上的多个客户端。只要有时间,学习就很有趣。)

更新 我遵循了smcjones的建议,并在我的
httpd vhosts.conf
中添加了以下内容:

<VirtualHost *:80>
    Alias "/lampjavel/api" "C:/Users/Viktor/Dev/htdocs/lampjavel-api/public"
    <Directory "C:/Users/Viktor/Dev/htdocs/lampjavel-api">
        Options Indexes FollowSymLinks MultiViews
        AllowOverride all
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>
然而,纤细路线的第一部分被扔掉了。当我在浏览器中访问
../api
时,我得到了正确的
/
路径。但是当我请求
../api/images
时,我仍然得到
/
路径。如果我深入研究
../api/images/images
我会得到我想要的路线,
/images

在我的
app.php
中:

$app->get('/', function () use ($app) {
    echo '/';
});

$app->get('/images', function () use ($app) {
    echo '/images';
});

知道为什么路由的第一部分被忽略了吗?

听起来你的应用程序的
DocumentRoot
实际上是
wwwroot/myproject/api
,你希望它是
wwwroot/myproject/api/public
。您可以只设置
DocumentRoot
指令,或者只执行以下操作:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /public/index.php [QSA,L]

在.htaccess#2(在api/中)中使用此选项:


您希望以声明的形式完成的任务将是笨拙和不安全的

笨拙,因为您试图从父文件夹调用子文件夹。这可能导致一些无法预料的问题。例如:

  • 您需要禁止使用
    mod\u rewrite
    调用项目结构中的文件夹。否则,您的服务器将尝试为您提供一条超薄路线,而不是,比如,
    app
    。而您可以添加
    RewriteCond%{REQUEST\u FILENAME}-d
    ,这将错过要点,因为这样你的
    应用程序
    路线就无法在Slim上运行
  • 因此,您也将永远无法拥有名为
    app
    的细长路线。虽然您很可能不打算使用名为
    app
    的瘦路由,但最好让您的应用程序具有灵活性
  • 类似地,如果您决定需要另一个文件夹(比如,
    docs
    ,或者用于单元测试的
    test
    ),您可能需要将其埋在另一个文件夹下,比如
    app
    public
    (至少在我看来,它们似乎不合适),或者您需要更改您的
    mod\u rewrite
    。您还需要再次注意命名冲突。从这个意义上说,除非你100%确定你不会改变你的结构,否则你会给自己带来更多的痛苦
不安全,因为您的web路径当前设置为显示大部分目录结构。虽然在我看来,这就像是一个开发服务器,但这可能并不重要,但我认为最好先在开发服务器上整理好路径

当前,如果导航到
http://localhost/myproject/api/app/data
,它会抛出404吗?有人能猜出你的结构吗?是否有您不希望有人在您的根目录之外找到的页面?虽然PHP不会显示这些文件中的任何一个,但有人很容易通过调用文件来过载您的系统。另外,如果一个文件在单独调用时抛出错误,您可能会放弃有关路径的更多信息

我再次意识到,您可能只是在测试它,但如果它在某个时候进入了一个活动环境,这些都是您需要处理的问题。在我开始尝试让我的开发服务器尽可能多地模仿我的实时服务器之后,我给自己的痛苦减轻了很多

我提出的解决方案

.htaccess
确实不是执行此类操作的理想场所。相反,您应该查看Apache的配置文件。正如@guillermoandrae所说,听起来您真正想要做的是使用不同的
DocumentRoot

如果可以访问Apache的配置,则可以创建一个直接指向
public
目录的

例如:

<VirtualHost *:80>
    Alias "/api" /wwwroot/myproject/api/public
    <Directory "/api">
        Options Indexes FollowSymLinks MultiViews
        AllowOverride all
        Order allow,deny
        Allow from all
        <IfModule mod_rewrite.c>
            RewriteEngine on
            #Rewrite Rules from .htaccess here
        </IfModule>
    </Directory>
</VirtualHost>
编辑#2 您的htaccess代码当前正在将主目录中不是目录或文件的所有内容推送到Slim。因此,很有可能错误出现在您的Slim路由中,而不是您的Apache访问中。你有这样的路线吗

$app->get('/images/:route', function ($route) {

    //execute code
};

如果您没有,那么请尝试找出正在实施的路线。如果很难定位,您可能可以使用Slim的一些内置日志功能。

但这两种功能似乎都不能正常工作。使用
RewriteRule
时,第一个Slim参数总是被忽略,因此我必须编写
http://localhost/myproject/api//
?您可以从
.htaccess
设置
DocumentRoot
?我已经试了一整天了,我不能让它正常工作。您确定您的配置正确吗?如果我阅读了您的规则,您会将所有传入请求重写到
public/index.php
,然后由我的初始
.htaccess
文件拾取?旗帜是干什么的?我们是否应该使用
RewriteBase
。关于这个问题的文档非常稀少和不清楚……我想把这一点从我的答案中分离出来,但我仍然想把它扔出去:如果您正在创建一个RESTful API,它可以是任何语言(Java、.NET、PHP等),只要
RewriteCond %{REQUEST_FILENAME} !-d
$app->get('/images/:route', function ($route) {

    //execute code
};