Как запустить несколько веб-сайтов на одном сервере с одной и той же базой кода на PHP?


Я создал пользовательскую специализированную CMS с несколькими клиентами на ней, у каждого из которых есть собственное доменное имя, веб-сайт, область администрирования и база данных, но все они находятся на одном сервере.

Всякий раз, когда я получаю нового клиента, я просто копирую весь код, меняю 3 строки в файле конфигурации, а затем все их стили/данные удаляются из базы данных или из загрузок, которые они отправляют на сервер из своей собственной области администрирования.

Пока звучит здорово, верно?

Хорошо, когда я недавно решил обновить все сайты клиентов, это стало серьезной проблемой. Очевидно, мне приходилось менять код при каждой установке. Для крупного обновления это нормально, но для частых настроек или тому подобного дублирование усилий по загрузке становится очень раздражающим....Я надеюсь, что когда-нибудь у меня будут десятки или сотни клиентов, поэтому код в конечном итоге придется централизовать, чтобы его изменение в одном месте обновляло его повсюду... как это сделать?

 10
Author: Phil, 2010-09-27

9 answers

Простым решением было бы поместить исходный код в подкаталог, за исключением файлов, которые должны быть изменены для каждого клиента (например, файл конфигурации).

Затем вы можете поместить этот каталог исходного кода куда-нибудь и просто создать символические ссылки на него.

Например, ваша структура каталогов может выглядеть следующим образом:

/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").

 17
Author: ChrisM, 2010-09-27 16:16:42

Лично у меня есть таблица клиентов в базе данных, в которой содержится номер текущей версии кода, который они запускают. Когда пользователь входит в систему, он устанавливает файл cookie под названием CodeVersion, указывающий версию кода для этого клиента (например, "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 [email protected]
    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 для специфичного для клиента кода или конфигурации.

 4
Author: Mark Baker, 2010-09-27 16:24:47

Просто чтобы вы знали, что у меня уже была эта проблема раньше. Легко попасться на какие-то нарушения phantom.htaccess или открыть эксплойты для других клиентов, если вы решите выполнить настройку с помощью этого.

Я рекомендую разделять все между клиентами.

Поэтому предоставьте им их собственный FTP, базу данных и кодовую базу. Не складывайте все это в одну папку и не думайте, что конфигурация поможет. Кажется сексуальным делать это таким образом, но когда у тебя есть один маленький проблема тогда у вас одна и та же проблема на всех клиентских сайтах, но если у вас есть одна проблема с клиентом, и все хранится отдельно, то другие клиенты не обязательно это чувствуют.

Вы можете запустить свою основную базу кода на отдельном тестовом сервере для выполнения обновлений, а затем просто исправить файлы FTP клиента и SQL базы данных.

Но держите это простым и отдельным!

 3
Author: Geekster, 2010-09-27 16:25:13

Я бы разделил на 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) создайте symlinks между веб-папками каждого сайта и источником library или (2) разделите свой код на основные функциональные возможности и код визуализации.

Символическая ссылка создает системную связь между двумя точками на диске (это похоже указатель). Правильно созданная ссылка позволяет вам получить доступ к папке с другим именем, чтобы вы могли создать /home/user1/library, /home/user2/library /home/user3/library, и все они указывают и содержат содержимое /home/library (они не являются копиями данных).

Я был бы включен в список № 2, хотя для этого потребуется больше работы. Ваш library выполняет эту работу, но рендеринг сайта выполняется вторым фрагментом кода, который предоставляется на основе каждого сайта (вероятно, включая вышеупомянутый config), это позволяет больше гибкость в зависимости от сайта (даже если вы еще не предвидите, что вам это понадобится). В качестве побочного эффекта вы находитесь на пути к многоуровневому приложению.

 2
Author: Rudu, 2010-09-27 16:25:38

Альтернативный подход заключается в использовании заглушек. Просто переместите общий код, например библиотеку, в общий каталог. Затем для каждого отдельного сайта создайте скрипты hollow.php, которые просто включают общий код:

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

Вам придется повторить это для каждой точки входа в приложение. Таким образом, у вас почти пустые сценарии на каждом сайте, и все изменения в общей кодовой базе автоматически применяются ко всем настройкам. Просто позвольте config.php различаются между установками.

Для статических файлов (изображения, css и т.д.) Я бы также использовал подход с символическими ссылками или перезаписью.

 1
Author: mario, 2010-09-27 16:28:57

Когда я делаю что-то подобное, у меня есть папка каждого клиента на веб-сервере, которая является рабочей копией SVN (очевидно, я использую SVN в качестве своей системы управления версиями). Затем, когда я внес некоторые обновления, протестировал и пометил выпуск, я просто переключаю папку клиента на новый выпуск. SVN автоматически отменяет все изменения для меня. Есть одно предостережение: убедитесь, что вы настроили свой веб-сервер так, чтобы он не позволял отображать содержимое папок .svn в каждом каталоге (или эквивалент для ваш VCS по выбору, если таковой имеется). Я полагаю, что впервые прочитал об этой технике в официальных документах SVN, поэтому я думаю, что она санкционирована их разработчиками, но я не могу найти ссылку на нее в документах прямо сейчас.

 1
Author: rmeador, 2010-09-27 17:56:22

Если вы разместите свой код в системе управления версиями, то каждый клиентский веб-сайт может быть отдельной проверкой. Вы можете проверить свои изменения и внедрить их в каждый клиент (или тестовый сайт), выполнив обновление системы управления версиями (или используя экспорт) в корневом каталоге. Затем вы можете обновить и протестировать каждого клиента по одному, чтобы убедиться, что исправление применено правильно.

 1
Author: SorcyCat, 2010-09-27 18:09:46

Во-первых, вам нужно быть осторожным с подводными камнями совместного использования кода между сайтами. Обновление многих сайтов одновременно увеличивает опасность того, что ваши обновления вызовут проблему - если в общем коде есть ошибка, лучше узнать об этом на одном сайте, чем на сотне сразу!

Решение для управления развертыванием может быть лучше, чем прямое совместное использование кода. (например, если вы используете Drupal, вы можете использовать Aegir для управления всеми развертываниями и обновлениями вашего сайта)

Тем не менее, он может в некоторых случаях было бы полезно поделиться кодом. Я делал что-то подобное на предыдущей работе, где они хотели, чтобы несколько сайтов использовали единую общую базу кода. Что мы сделали, так это поместили общие библиотеки в папку на сервере, и затем каждому сайту была предоставлена символическая ссылка на эту папку, поэтому он рассматривал ее как локальную папку. Довольно легко сделать и довольно легко управлять.

 0
Author: Spudley, 2010-09-27 16:34:49

Как насчет чего-то, что использует один и тот же код, но у каждого есть свой mysql.
Например, http://mycms.com/myuser / добавляет префикс myuser_ в таблицы, таким образом, позволяя 1 структуру src и несколько сайтов. Вам понадобится.htaccess, хотя

 0
Author: InsanityNet, 2010-09-27 17:59:12