Quite often in my role as a Solutions Architect at Acquia, I'll see customers looking to bring sites under the multisite banner in order to enact a more controlled code governance model. Amalgamating codebases allows for a more controlled site development experience where 50 different sites can be thought of as one cohesive unit rather than disparate and isolated nuggets of technical debt. This blog extends one I wrote a while ago about the opposite operation of extracting sites from within a multisite.
A while ago, I wrote an article about migrating a site out of a multisite situation into being its own standalone Drupal installation. A site might be separated out of a multisite if its functionality was expanding in scope further than what the platform should reliably be dealing with. Ideally, any shared platform would ensure the majority of functionality included in the codebase was utilised by all sites to minimise the possibility of code bloat.
What is code bloat?
Within the Drupal community, many pieces of code exist to connect Drupal sites with external services and increase the overall level of functionality of the site. Due to the architecture of Drupal, code providing functionality and content/configuration in the database, many sites can use the same codebase to run entirely different sites. It’s often a preferable idea to map functionally similar sites to the same codebase to allow one bug fix or patch update to be applied to multiple running websites simultaneously; lowering the development burden and reducing the maintenance time and spend. This should be contrasted with entirely different sites e.g. intranet vs eCommerce. Typically the functional requirements of the two sites would be completely different, leading to less code share and a reduced effectiveness in a shared codebase. In these instances, I typically recommend using separate codebases to contain the functionality and remove the amount of unused code per site.
How can I make development more efficient?
If two similar Drupal sites exist in different codebases, it can be a preferable option to allow them to run from a shared codebase. The process of migrating an existing site into a multisite arrangement is reasonably trivial provided the following steps are adhered to.
- Create a directory within the sites directory to house the site specific modules, files and database connection information e.g. sites/mysitename
- Copy across everything from within the old site code tree from sites/default to sites/mysitename.
- Ensure that all modules existing on the old site within sites/all/modules are present on the multisite codebase in some way. N.B. if these modules would benefit other sites on the multisite they should be added to sites/all, if they are custom or bespoke to the site being transferred in they should be moved to sites/mysitename
- If on another server, migrate the database from the old site to the database present on the server where the multisite resides
- Connect to the database by typing mysql -uUSERNAME -pPASSWORD -DDATABASENAME or navigate to the new site directory (sites/mysitename) and type drush sqlc.
- Run the following queries substituting in the correct name for your site directory and only changing path for the custom modules that have been placed in the sites/mysitename/modules directory
- It's important to run the SQL statements in this order as the second query relies on a JOIN operation that won't work after the third query.
- Clear your cache with drush cc all (At this point you may also need to manually truncate cache and cache_menu and menu_router tables beforehand.)
- Finally change your filesystem path(s) variable in the Drupal settings from sites/default/files to sites/mysitename/files.
UPDATE system SET filename = REPLACE(filename, 'sites/all/modules', 'sites/mysitename/modules') WHERE name IN ('custom_module', 'mysite_feature', 'migration_module'); UPDATE registry_file rf JOIN registry r ON rf.filename = r.filename SET rf.filename = REPLACE(rf.filename, 'sites/all/modules', 'sites/mysitename/modules') WHERE r.module IN ('custom_module', 'mysite_feature', 'migration_module'); UPDATE registry SET filename = REPLACE(filename, 'sites/all/modules', 'sites/mysitename/modules') WHERE module IN ('custom_module', 'mysite_feature', 'migration_module');