You can run multiple independent sites from one play-cms installation. Each site has its own frontend and shares the common backend with all sites (however, each site also can have site-specific backend entries).
Required version: play-cms:2.5+
Sites are configured in application.conf: key cms.sites[{site1}{site2}{..}]
name |
The display name of a site. |
key | The key used in the database - don't change after a site was initialized. |
hosts |
A comma-separated lists of hosts that are assigned to this site. They're matched against the request's "Host:" header. To allow all hosts, use the wildcard "*". Note: The port is part of the host header if it's not 80 - meaning you can run multiple sites on different ports of the same host. |
langs | The language config to support multilanguage feature. |
langs | Path to site specific logo(usually it appears in /uploads directory) |
The default site config looks like this:
cms.sites = [
{
name: default
key:""
hosts: ["*"]
}
]
In this example, two sites are configured, with no default:
cms.sites = [
{
name: site1.ch
key: site1
hosts: [site1.ch, www.site1.ch]
langs: [...]
logoPath: ""
}
{
name: site2.ch
key: site2
hosts: [site2.ch, www.site2.ch]
langs: [...]
logoPath: ""
}
]
From code, access the site configuration like this:
// Get the sites configuration
CMS.getSites();
// Get the current site
CMS.getSites().current();
// Get all configured sites
CMS.getSites().all();
// Resolve the site for a given host
CMS.getSites().forHost("site1.ch");
// Get the TypeSafe config object for the current site
// (This will let you use arbitrary site-specific config values)
CMS.getSites().current().config;
(Note: These are all immutable config values)
First, add the configuration entry for your new site. After that, access the backend of your new site (newsite.com/admin).
In the "Navigation" screen, you should see a red note which asks for initializing the new site. Click on it. This will add the required structural nodes and some demo content to your new site.
The AbstractBlock
(table cms_blocks
) has a new attribute site
which contains the site key the block belongs to. Blocks that belong to all sites, such as the backend, have site set to the wildcard (*).
The site is inherited from the parent block, except for the site root nodes (those nodes that connect directly to the single root parent) - these site roots define the site starting point.
When retrieving blocks, the cms tries first to find a specialized block (matching the current site), then a default (wildcard) block.
If assigning a key, then a block's site+key must be unique.
The cms requires always a valid site. To write tests or other code running from localhost, you should ensure the Host header is set to localhot and have a configuration that can handle localhost. In any case, CMS.getSites().current()
needs to be set correctly when interacting with cms content!
[TODO: Allow to set / mock the current site from code]
With a multi-site configuration there are often cases, where different logic has to be implemented for the different sites. The cms provides the SiteSpecific
utility class to make this easier and with less boilerplate code.
Rendering different layouts per site:
return SiteSpecific.forSite(CMS.getSites().current(), views.html.notFound.render())
.onSiteKey(MySites.SITE_A.key, () -> views.html.showSiteA.render())
.onSiteKey(MySites.SITE_B.key, () -> views.html.showSiteB.render())
.get();
The above code returns the template notFound
by default and returns showSiteA
if the current site is SITE_A
and showSiteB
if the current site is SITE_B
SiteSpecific
uses generics to determine the result type of the suppliers. This way you can either return a Result, a rendered Template or something entirely different.
Configuration configuration = ...
return SiteSpecific.forSite(CMS.getSites().current(), Results::notFound)
.onSiteKey(MySites.SITE_A.key, () -> {
boolean useSomeFeature = configuration.getBoolean("config.someFeature.siteA.enabled");
return ok(views.html.showPage.render(useSomeFeature));
})
.onSiteKey(MySites.SITE_B.key, () -> {
boolean useSomeFeature = configuration.getBoolean("config.someFeature.siteB.enabled");
return ok(views.html.showPage.render(useSomeFeature));
})
.get();
This code renders the same template for SITE_A
and SITE_B
but first reads the configuration about whether a certain feature is enabled or not. By default, it returns the Play Framework's notFound
result.
1. Add the default site configuration to application.conf (see above)
2. Update the existing db:
CREATE UNIQUE INDEX cms_blocks_KEY_SITE_uindex ON `play-cms-demo`.cms_blocks (`KEY`, SITE);
UPDATE cms_blocks SET SITE=''
UPDATE cms_blocks SET SITE='*' WHERE `KEY`='_root'
UPDATE cms_blocks SET SITE='*' WHERE `KEY`='_backend'