2010-09-27 16 views
10

He creado un CMS especializado y personalizado con una cantidad de clientes, cada uno con su propio nombre de dominio, sitio web, área de administración y base de datos, pero todos residen en el mismo servidor.¿Cómo ejecuto varios sitios web en el mismo servidor con la misma base de código en PHP?

Cada vez que obtengo un nuevo cliente, simplemente copio todo el código, cambio 3 líneas en un archivo de configuración, y luego todos sus estilos/datos se sacan de la base de datos o de las cargas que publican en el servidor desde su propia área de administración.

Suena genial hasta ahora ¿verdad?

Bueno, cuando recientemente decidí actualizar todos los sitios de los clientes, esto se convirtió en un gran dolor. Obviamente tuve que cambiar el código en cada instalación. Para una actualización importante, está bien, pero para ajustes frecuentes o cosas similares, duplicar el esfuerzo de cargar es muy molesto ... Espero que algún día tenga docenas o cientos de clientes, por lo que el código eventualmente tendrá que ser centralizado para que cambiarlo en un lugar lo actualiza en todas partes ... ¿cómo se hace eso?

Respuesta

16

Una solución fácil sería poner el código fuente en un subdirectorio, excepto los archivos, que se deben modificar para cada cliente (por ejemplo, el archivo de configuración).

Puede colocar este directorio de código fuente en algún lugar y simplemente crear enlaces simbólicos a él.

Por ejemplo, la estructura de directorios podría ser:

/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/ 

Si elige esta estructura, lo único que tendría que cambiar, sería la de incluir settings.php (por ejemplo, de require "settings.php" a require "../settings.php")

+0

esto suena como una solución prometedora y simple ... si tan solo supiera qué son los enlaces simbólicos :) para aclarar ... lo investigaré. No soy un programador capacitado y SÓLO conozco idiomas web: php, js, mysql, html, flash. no hay cosas de administrador de sistemas en absoluto. – Phil

+3

Un enlace simbólico es un enlace simbólico (http://en.wikipedia.org/wiki/Symbolic_link), que simplemente le dice al servidor que debe buscar la información en otro lugar. Si está utilizando Linux/UNIX en el servidor, puede establecer el enlace simbólico con ln -s [fuente] [destino]. – ChrisM

2

Me dividiría en el library (su código de trabajo) y el config (las tres líneas para cada usuario, probablemente las conexiones a la base de datos y similares).

Divida library en una ubicación universal, por ejemplo /home/library (en * nix) y permita el atributo de lectura en las otras cuentas de usuario.

Ahora para cada sitio hay un archivo config que primero incluye el library y el segundo establece la configuración específica del sitio. Actualizando el library actualiza todas las versiones. Sin embargo, una palabra de precaución: querrá tener algunas pruebas unitarias implementadas de modo que una actualización del library no rompa ninguno de los sitios únicos.

por ejemplo config: (uno por cada sitio)

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

Si la biblioteca de código también se utiliza para representar el contenido (index.php etc), entonces usted tiene dos opciones: (1) crear symlinks entre las carpetas web de cada sitio y la fuente library, o (2) separe su código en la funcionalidad principal y el código de representación.

Un enlace simbólico crea un enlace de sistema entre dos puntos en el disco (es como un puntero). Un enlace creado correctamente le permite acceder a una carpeta con un nombre diferente para que pueda crear /home/user1/library, /home/user2/library/home/user3/library, y todos apuntan y contienen el contenido de /home/library (no son copias de los datos).

Me incluirían para ir con el n. ° 2 aunque tomará más trabajo por adelantado.Su library hace el trabajo, pero el renderizado del sitio se realiza mediante la segunda parte del código que se suministra en bases por sitio (probablemente incluyendo el anteriormente mencionado config), esto permite más flexibilidad sitio por sitio (incluso si no te imaginas que necesites esto todavía). Como efecto secundario, estás en el camino hacia una aplicación de varios niveles.

4

Personalmente, tengo una tabla de clientes en la base de datos que contiene el número de versión actual del código que están ejecutando. Cuando un usuario inicia sesión, establece una cookie llamada CodeVersion que indica la versión del código para ese cliente (por ejemplo, "v5-09-00"). En el .htaccess de Apache, tengo:

RewriteEngine on 

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

y dentro del archivo de hosts locales, que tengo:

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 

que se ocupa de redirección local dentro de Apache a una entrada en vhosts

Los VHosts archivo establece el entorno para cada versión del código:

<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> 

Dentro de cada conjunto de direct ories, puedo tener enlaces simbólicos que apuntan a código común, y archivos php/ini reales para código o configuración específicos del cliente.

+0

+1 Me gusta este kung-fu, gran idea. – Rudu

+0

¿no crea esto problemas si el usuario falsifica la cookie? Supongo que hay algún tipo de problema de seguridad aquí, a menos que sea extremadamente cuidadoso. – rmeador

+0

Hay controles adicionales dentro del código, por lo que una cookie falsa eliminará esa cookie y desconectará al usuario. –

3

Solo para hacerle saber que he tenido este problema antes. Es fácil quedar atrapado por algunas irregularidades de acceso phantom o open exploits hasta otros clientes si decide configurarlo a través de esto.

Recomiendo mantener todo separado entre los clientes.

Por lo tanto, proporcióneles su propio FTP, base de datos y base de código. No lo apile todo en una carpeta y piense que la configuración ayudará. Parece atractivo hacerlo de esa manera, pero cuando tienes un pequeño problema, entonces tienes el mismo problema en todos los sitios de los clientes, pero si tienes un problema con un cliente y todo se mantiene separado, los demás clientes no se sienten es necesariamente

Puede ejecutar su base de código principal en un servidor de prueba separado para realizar actualizaciones y luego simplemente parchear los archivos FTP de sus clientes y la base de datos SQL.

¡Pero mantenlo simple y separado!

+0

punto de vista interesante ... ¿Qué sucede si los clientes no tienen acceso a FTP o a la base de datos? acceden al servidor únicamente a través de su propia área de administración en su propio directorio. – Phil

+0

@Phil - Estoy de acuerdo. También he desviado el camino de los archivos de configuración sexy y cuando llega el momento en que un cliente quiere algo que requiera más que unas pocas configuraciones (y llegará) puede ser muy complicado. Lo que me di cuenta de que estaba buscando fue en realidad un método para implementar una base de código actualizada en varios sitios con pruebas unitarias incorporadas. Mira mi pregunta similar aquí http://stackoverflow.com/questions/3386529/deploy-to-multiple-instances – Macros

+0

Disculpa, significa @Geekster Estoy de acuerdo. Intentar mantener una base de código central con una sola mano puede ser muy complicado – Macros

1

Un enfoque alternativo es usar stubs. Simplemente mueva el código compartido, como una biblioteca a un directorio compartido. Luego, para cada sitio individual, crear scripts .php huecos que acaba de incluir el código compartido:

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

podrás tuvo que repetir que para cada punto de entrada de la aplicación. Por lo tanto, tiene scripts casi vacíos en cada sitio, y todos los cambios en la base de código compartido se aplican automáticamente a todas las configuraciones. Simplemente deja que el config.php difiera entre las instalaciones.

Para archivos estáticos (imágenes, css, etc.) También utilizaría un enfoque de enlace simbólico o una RewriteRule.

0

En primer lugar, debe tener cuidado con las trampas de compartir el código entre sitios. La actualización de muchos sitios a la vez multiplica el peligro de que sus actualizaciones causen un problema: si el código compartido tiene un error, ¡es mejor descubrir en un sitio que en un centenar a la vez!

Una solución de administración de implementación puede ser mejor que compartir directamente el código.(Si está usando Drupal, por ejemplo, podría utilizar Aegir para gestionar todos sus despliegues y actualizaciones del sitio)

Dicho esto, puede ser útil para compartir código en algunos casos. Hice algo como esto en un trabajo anterior, donde querían varios sitios usando una única base de código compartido. Lo que hicimos fue poner las bibliotecas compartidas en una carpeta en el servidor, y cada sitio recibió un enlace simbólico a esa carpeta, por lo que lo trató como una carpeta local. Muy fácil de hacer, y bastante fácil de administrar.

+0

gracias por ese punto de vista. Estoy usando PHP simple y MySQL construidos desde cero. ¿Puedes sugerir una solución de administración de implementación para eso? – Phil

+1

Es posible que desee migrar a un sistema de implementación y control de versiones. Esto hace factibles las actualizaciones semiautomáticas. Sin embargo, puede verificar por sistema, si algo sale mal. – mario

+0

De acuerdo con @mario: un sistema de control de versiones (SVN, Git, etc.) facilitará las cosas ya que puede obtener cualquier versión del repositorio en cualquier momento, por lo que es fácil deshacer un cambio si algo va incorrecto. Estoy tan acostumbrado a usar el control de versiones que me olvidé de mencionarlo; Consideraría que es una herramienta vital para cualquier desarrollador de software, pero particularmente una en la que necesita administrar múltiples instalaciones. – Spudley

1

Cuando hago algo como esto, tengo la carpeta de cada cliente en el servidor web como una copia de trabajo SVN (uso SVN como mi sistema de control de versiones, obviamente). Luego, cuando realicé algunas actualizaciones, probé y etiqueté la versión, simplemente cambié la carpeta del cliente a la nueva versión. SVN automáticamente baja todos los cambios por mí. Hay una advertencia: asegúrese de configurar su servidor web para que no permita la publicación de los contenidos de las carpetas .svn en cada directorio (o el equivalente para su VCS de elección, si lo hay). Creo que primero leí esta técnica en los documentos oficiales de SVN, así que creo que es aprobada por sus desarrolladores, pero no puedo encontrar una referencia en los documentos en este momento.

0

¿Qué tal algo que utiliza el mismo código, pero cada uno tiene su propio mysql.
Me gusta, http://mycms.com/myuser/ trae el prefijo myuser_ a las tablas, permitiendo así 1 estructura de src y sitio múltiple. Necesitará .htaccess a través de

1

Si coloca su código en el control de la versión, cada sitio web del cliente puede ser un proceso de pago por separado. Puede verificar sus cambios y distribuirlos en cada cliente (o sitio de prueba) haciendo una actualización de control de versión (o usando exportación) en la raíz. Luego puede actualizar y probar cada cliente de uno en uno para asegurarse de que el parche se aplique correctamente.

Cuestiones relacionadas