处理同一URL中的多个版本

时间:2011-08-10 11:43:19

标签: php apache ria multiple-versions

我要做的是处理同一个网络应用程序的多个版本,有点像谷歌与他们的一些产品,你会得到“尝试新版本”链接。

目标是同时拥有webapp的“稳定”版本和“beta”版本,并让用户试用新功能,而不必强迫它们(以及它们的错误)。

现在,一个非常简单的方法是将每个版本放在自己的子文件夹中,例如www.mywebapp.com/v1和www.mywebapp.com/v2。

但是,我希望这对用户和webapp URL保持透明以保持不变(例如:www.mywebapp.com /)。

必须加载哪个版本在用户登录后确定服务器端(例如:给定用户的活动版本存储在数据库中),并且可能在用户点击“尝试新版本”时更改/“回到旧版本”链接。

在服务器端,我必须使用MySQL,PHP和Apache。

我已经设法让这个工作将每个版本放入其自己的子文件夹中,然后将版本信息存储在cookie中(在每次登录或页面刷新时由服务器更新)并使用RewriteRule来“代理”来自基本/无版本URL到正确的子文件夹。如果未设置cookie,则由后备RewriteRule选择默认文件夹。

这个kludge工作但感觉非常脆弱,它给Apache守护进程带来了额外的负担,所以我在这里询问是否有人知道更好的方法。

谢谢!

7 个答案:

答案 0 :(得分:6)

htaccess allows for rewrites based on the contents of cookies。由于Apache在重定向方面非常棒且PHP足够,我会这样处理它。

此示例测试是否存在vers cookie。如果有的话,它会在请求中添加'vers ='+ vers cookie中的任何内容。

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} vers=([^;]+) [NC]
RewriteRule ^(.*)$ /$1?vers=%1 [NC,L,QSA]

(该例子可以找到here

答案 1 :(得分:2)

我认为在PHP中更好的方法是简单地查询数据库,获取所需的版本,然后从子文件夹中include()。这样,它对用户来说是透明的。

例如,假设用户选择了新的测试版,则将其条目保存在数据库中,

UPDATE `versions_table` SET (`version`) VALUES ('1.02b') WHERE `userid` = 5

然后当他访问该页面时,你会发生这样的事情:

//PDO Connection here, skipped for example purposes
$stmt = $pdo->query('SELECT `version` from `versions_table` WHERE `userid` = 5 LIMIT 1'); 
//Of course 5 is only an example, in actual code that would be a variable
//representing the actual user ID.
$row = $stmt->fetch(); //Should be only one row.
include_once($row['version'].'/myApp'.'.php'); //Include 1.02b/myApp.php

答案 2 :(得分:2)

使用单个RewriteRule将所有请求重新路由到您网站根文件夹中的单个route.php文件。

route.php文件应如下所示:

$user = authenticateUser();
$version = $user->getPreferredVersion();

$filePath = $_SERVER['DOCUMENT_ROOT'].'v'.$version.$_SERVER['REQUEST_URI'];

if( !file_exists( $filePath ) ) {
    header("Status: 404 Not Found", true, 404 );
    die();
}

$pathDetails = pathinfo( $filePath );

if( $pathDetails['extension'] == 'php' ) {
    require( $filePath );
} else {
    if( $pathDetails['extension'] == 'jpg' ) {
        header( 'Content-Type: image/jpeg' );
    } elseif( $pathDetails['extension'] == 'gif' ) {
        ...
    } elseif (...) {
        ...
    } else {
        // unsupported file type
        header("Status: 404 Not Found", true, 404 );
        die();
    }
    echo file_get_contents( $filePath );
}

这是您应该在route.php中做什么的概述,您应该在该文件中处理一些其他安全和技术问题。

答案 3 :(得分:0)

虽然可以使用路由机制和会话信息来制定规则,但我宁愿保留您当前的解决方案。你在PHP中实现它所做的就是将apache2(已经有一个非常快速的Rewrite-Engine)的负载推送到php-binary。此外,由于数据,cookie和其他基于会话的变量不兼容,您的应用程序将面临干扰版本的风险。

另一方面,您可以获得库,域模型,数据映射器等共享对象的可重用性。但在我看来,这种优势并不会降低性能和干扰风险。

所以在一个短语中,我相信你目前的解决方案是最好的。

答案 4 :(得分:0)

在IFRAME中加载版本化页面/ wepages,IFRAME src可能是“webapp.com/v2”..

因此,无论用户选择地址栏的哪个版本都会读取webapp.com ..但您的IFRAME网址会根据版本不断变化..

无需编写重写规则..

答案 5 :(得分:0)

这可能会有所帮助:我现在使用的一个月是

  1. 保持数据库中的所有文件(路径,代码,版本=十进制(3,1),标记:stable = 3 / lab = 2 / beta = 1 / alpha = 0 )

  2. 将.htaccess 重定向所有非现有文件(不要将图像,css,js或其他静态非版本文件重定向)内部加载到loader.pm(为您加载。 ph_)不要使用与其他文件相同的扩展名进行区分

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^   loader.pm [L,QSA]
    
  3. 如果不存在稳定版本,
  4. 加载程序会从数据库或测试版加载最新的稳定版

    SELECT code, version, flag FROM table WHERE path = ? AND flag > 0 ORDER BY flag DESC, version DESC LIMIT 1不要显示正在开发中的Alpha页面

    如果没有结果,

    输出404错误,

    当指定版本时?v=2.0加载程序文件使用不同的查询

    SELECT code, version, flag FROM table WHERE path = ? AND version <= ? ORDER BY flag DESC LIMIT 1

  5. 假设:

    1. 用户想要稳定或最新;所以你实际上每个路径不需要超过2个文件;除非你想保留陈旧的旧版本。如果用户想要最新,请使用.. ORDER BY version DESC, flag DESC, ..
    2. 用户不在乎知道它是哪个版本,因此我们不是一次为整个网站设置相同版本,而是单独设置每个文件的版本;因此跟踪开发很容易。
    3. 问题:

      • 没有索引/主键
        • 您需要确保没有重复的条目,但它不会破坏您的网站,但它看起来不会很好;)
        • 如果相同的beta&amp;文件存在稳定版本,用户选择了最新版(测试版);然后你可能会意外地发送他的beta文件而不是稳定文件。
      • 查询字符串变量?v=保留用于选择版本,但这很好;您可以选择?var=

答案 6 :(得分:0)

有一个云平台可以在部署时自动执行此操作。 www.cycligent.com
只需在部署两个版本后设置cookie即可。比显示的其他一些答案少得多的工作 完全披露:我为Cycligent工作。