Как мне запустить несколько сайтов на одном сервере с одной и той же кодовой базой в PHP? - PullRequest
10 голосов
/ 27 сентября 2010

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

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

Звучит отлично, правда?

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

Ответы [ 9 ]

17 голосов
/ 27 сентября 2010

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

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

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

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

4 голосов
/ 27 сентября 2010

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

3 голосов
/ 27 сентября 2010

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

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

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

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

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

2 голосов
/ 27 сентября 2010

Я бы разделил на 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), это обеспечивает большую гибкость на сайте за сайтом основа (даже если вы еще не предвидите, что нуждаетесь в этом). В качестве побочного эффекта вы на пути к многоуровневому приложению.

1 голос
/ 27 сентября 2010

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

1 голос
/ 27 сентября 2010

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

1 голос
/ 27 сентября 2010

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

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

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

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

0 голосов
/ 27 сентября 2010

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

0 голосов
/ 27 сентября 2010

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

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

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

...