如何在PHP中使用相同的代码库在同一台服务器上运行多个网站?

时间:2010-09-27 16:12:22

标签: php admin

我创建了一个自定义的专用CMS,其上有许多客户端,每个客户端都有自己的域名,网站,管理区域和数据库,但都位于同一台服务器上。

每当我得到一个新客户端时,我只需复制所有代码,在配置文件中更改3行,然后将所有样式/数据从数据库中取出或从上传到服务器的上传他们自己的管理区域。

到目前为止听起来很棒吗?

当我最近决定更新所有客户网站时,这成了一个主要的痛苦。显然我必须在每次安装时更改代码。对于重大更新,这很好,但是对于频繁的调整等,重复上传的工作变得非常烦人....我希望有一天会有几十个或几百个客户端,所以代码最终必须集中化,以便在一个地方更改它在任何地方更新它...如何做到这一点?

9 个答案:

答案 0 :(得分:17)

一个简单的解决方案是将源代码放在一个子目录中,除了文件之外,应该为每个客户端更改这些文件(例如,配置文件)。

然后,您可以将此源代码目录放在某处,只需为其创建符号链接。

例如,您的目录结构可能如下所示:

/var/www/src/index.php
/var/www/src/more_source.php
/var/www/clients/client_a/settings.php
/var/www/clients/client_a/src -> ../../src/
/var/www/clients/client_b/settings.php
/var/www/clients/client_b/src -> ../../src/

如果您选择此结构,则唯一需要更改的内容是settings.php的包含(例如从require "settings.php"require "../settings.php")。

答案 1 :(得分:4)

就个人而言,我在数据库上有一个客户端表,其中包含他们正在运行的代码的当前版本号。当用户登录时,它会设置一个名为CodeVersion的cookie,指示该客户端的代码版本(例如“v5-09-00”)。在Apache .htaccess中,我有:

RewriteEngine on

RewriteCond %{HTTP_COOKIE} CodeVersion=([^;]+) [NC]
RewriteRule ^(.*)$ http://v%1.%{HTTP_HOST}/${escape:$1} [R=302,P,L]

在本地hosts文件中,我有:

127.0.0.1    myservername       myservername.myserverdomain.com

127.0.0.1    v5-08-00.myservername  v5-08-00.myservername.myserverdomain.com
127.0.0.1    v5-09-00.myservername  v5-09-00.myservername.myserverdomain.com
127.0.0.1    v5-10-00.myservername  v5-10-00.myservername.myserverdomain.com

处理Apache中的本地重定向到vhosts中的条目

vhosts文件为每个版本的代码设置环境:

<VirtualHost *:80>
    ServerAdmin mark.baker@myserverdomain.com
    DocumentRoot /usr/local/apache/htdocs_5-09-00
    ServerName v5-09-00.myservername.myserverdomain.com
    ServerAlias v5-09-00.myservername
    ErrorLog logs/myservername-error_log_5-09-00
    CustomLog logs/myservername-access_log_5-09-00 common
    php_value include_path ".:/php/includes:/usr/local/include/5-09-00/API:/usr/local/include/5-09-00/library:/usr/local/include/5-09-00/businesslogic:/usr/local/include/5-09-00/configuration:/usr/local/include/5-09-00/library/PHPExcel/Classes"
</VirtualHost>

<Directory "/usr/local/apache/htdocs_5-09-00">
    Options Indexes FollowSymLinks ExecCGI
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

在每组目录中,我可以使用指向公共代码的符号链接,以及用于客户端特定代码或配置的实际php / ini文件。

答案 2 :(得分:3)

只是为了让你知道我以前遇到过这个问题。如果您决定通过此配置,很容易被一些幻像.htaccess违规或开放漏洞攻击到其他客户端。

我建议将客户端之间的所有内容分开。

因此,给他们自己的FTP,数据库和代码库。不要把它全部堆放在一个文件夹中,并认为配置会有所帮助。这样做似乎很性感,但是当你遇到一个小问题时,你在所有客户端网站上遇到同样的问题,但是如果你对客户有一个问题并且一切都是分开的,那么其他客户就不会感觉到它必然。

您可以在单独的测试服务器上运行主代码库以进行更新,然后只需修补客户FTP文件和数据库SQL。

但请保持简单和分离!

答案 3 :(得分:2)

我分为library(您的工作代码)和config(每个用户的三行,可能是数据库连接等)。

library拆分为通用位置,例如/home/library(在* nix中),并允许读取属性到其他用户帐户。

现在,对于每个站点,都有一个config文件,其中首先包含library,第二个文件设置特定于站点的配置。更新library会更新所有版本。但需要注意的是 - 您需要进行一些单元测试,以便更新library不会破坏任何单个站点。

例如config :(每个网站一个)

<?php
require_once('/home/library/include.php');
//Line 1 config
//Line 2 config
//Line 3 config
?>

如果您的代码库也用于呈现内容(index.php等),那么您有两个选择:(1)在每个站点的Web文件夹和symlinks源之间创建library,或(2)将您的代码分为核心功能和呈现代码。

符号链接在驱动器上的两个点之间创建一个系统链接(就像一个指针)。正确创建的链接允许您使用其他名称访问文件夹,以便创建/home/user1/library/home/user2/library /home/user3/library,并且它们都指向并包含/home/library的内容(它们不是数据的副本。)

虽然预先需要做更多的工作,但我会被包括在内。您的library可以完成工作,但网站渲染是由每个网站提供的第二段代码执行的(可能包括前面提到的config),这样可以提高工作效率逐个站点(即使你没有预见到自己需要这个)。作为副作用,您正在前往多层应用程序。

答案 4 :(得分:1)

另一种方法是使用存根。只需将共享代码(如库)移动到共享目录中即可。然后,对于每个单独的站点,创建空心的.php脚本,其中只包含共享代码:

  // file: index.php
  include(".../shared/index.php");

您必须为每个应用程序入口点重复此操作。因此,每个站点中的脚本几乎都是空的,共享代码库中的所有更改都会自动应用于所有设置。只需让config.php在安装之间有所不同。

对于静态文件(图像,CSS等),我还使用符号链接方法或RewriteRule。

答案 5 :(得分:1)

当我做这样的事情时,我在Web服务器上的每个客户端文件夹都是一个SVN工作副本(显然我使用SVN作为我的版本控制系统)。然后,当我做了一些更新,测试和标记版本时,我只是将客户端文件夹切换到新版本。 SVN会自动为我提取所有更改。有一点需要注意:确保将Web服务器设置为不允许在每个目录中提供.svn文件夹的内容(或者选择VCS的等效文件,如果有的话)。我相信我在官方的SVN文档中首先阅读了这种技术,所以我认为它是由开发人员批准的,但我现在无法在文档中找到它的引用。

答案 6 :(得分:1)

如果您将代码置于版本控制中,则每个客户端网站都可以单独签出。您可以检查更改,并通过在根目录下执行版本控制更新(或使用导出)将它们滚动到每个客户端(或测试站点)。然后,您可以一次更新和测试每个客户端,以确保正确应用补丁。

答案 7 :(得分:0)

首先,您需要注意在站点之间共享代码的缺​​陷。一次更新多个站点会增加更新导致问题的危险 - 如果共享代码有错误,最好在一个站点上找到,而不是一次找到一百个站点!

部署管理解决方案可能比直接共享代码更好。 (例如,如果您使用Drupal,则可以使用Aegir管理所有站点部署和更新)

也就是说,在某些情况下共享代码会很有帮助。我在之前的工作中做了类似的事情,他们想要使用单个共享代码库的几个站点。我们所做的是将共享库放入服务器上的文件夹中,然后为每个站点提供指向该文件夹的符号链接,因此将其视为本地文件夹。很容易做到,而且很容易管理。

答案 8 :(得分:0)

使用相同代码的东西怎么样,但每个代码都有自己的mysql 就像,http://mycms.com/myuser/ 将前缀myuser_带到表中,因此允许1个src结构和多个站点。你需要.htaccess