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

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

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

Звучит здорово до сих пор?

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

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

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

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

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

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

и в файле локальных хостов я имею:

 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 для кода или конфигурации, специфичной для клиента.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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