Forums / Setup & design / How do you organize your multisite content?

How do you organize your multisite content?

Author Message

Ciprian Popovici

Thursday 23 March 2006 6:14:25 am

I've set up several sites on the same ezPublish 3.7.2 installation. I've decided that I would create a folder for each site under the main content folder (the one called "eZ publish"), ie. mysite.com, mysite2.com and so on. Under each folder I add content specific to that site. By editing each siteaccess and specifying a certain default node I've solder the issue of showing a certain different homepage for each siteaccess.

Now, the problem I'm facing is the URL's. My URL's only work in this form: /index.php/mysite_com/about/. It's fair, because my content structure has a folder called "mysite.com", and the "About" article under it. Also, if I use {"/about/"|ezurl} I get "/index.php/about/", which is not valid.

How did you guys solve this issue if you have multisite setups? Do you have another way of organizing the content structure? I'd rather not put content from different sites all together at the same level if possible. But at the same time I'd like to have nicer URL's (such as "/index.php/about/") without the extra folder in the middle.

Ciprian Popovici

Thursday 23 March 2006 7:43:02 am

I managed to solve the issue using mod_rewrite tricks.

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?myhost\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/index\.php/myhost_com [NC]
RewriteCond %{REQUEST_URI} !^/design/ [NC]
RewriteCond %{REQUEST_URI} !^/var/ [NC]
RewriteRule ^(.*)$ /index\.php/myhost_com/$1 [L]

Repeat this set for each virtual host in your multisite setup, changing myhost\.com and myhost_com to whatever is needed.

Explanation:
1. If the host being used is [www.]myhost.com
2. And if the URL being requested does NOT already start with /index.php/myhost_com (otherwise you'd get an endless loop).
3. And if the URL being requested does NOT start with /design/ (so you can still access your stylesheets and design images normally) nor /var/ (so you can access files and images served through ezPublish).
4. Then translate the URL "quietly" (the user won't see it in the browser address bar) by taking whatever is after the site name and adding /index.php/myhost_com/ in front of it.

So, if I access this: http://www.mysite.com/company/
it gets quietly transformed into this: http://www.mysite.com/index.php/mysite_com/company/

<b>One more important thing:</b> in my templates, I generate URL's like this:

<a href={"/company/"|ezroot}>COMPANY</a>

Note that I'm using <b>ezroot</b>, which strips "index.php" from the generated URL.

Thoughts for improvement: one may choose to further tweak the mod_rewrite rules. For example, you may use regular expressions to make sure that the URL being reformatted is actually of the form /something/ and nothing more. It should be something allowing only two slashes, and in between only a-zA-Z0-9_ or such.

Ciprian Popovici

Thursday 23 March 2006 7:49:15 am

Oh, one more thing. Since /mysite_com/ is actually a content folder called "mysite.com", accessing /index.php/mysite_com/ or simply / will (with the rewrite rules above activated) actually list the contents of the eZ folder. Which may not be what you want (I know it's not what I want).

I chose to deal with this via the URL translator in the admin interface (Setup/URL Translator). There are two ways you can tackle this: either redirect "mysite_com" to "mysite_com/company", or to "view/content/full/<b>ID</b>" (where ID is the same ID you used as DefaultNode in the respective siteaccess).

Or you can accomplish the same with more mod_rewrite rules, whichever you prefer.

Roy Bøhmer

Friday 24 March 2006 2:57:47 am

You should take a look at the site.ini setting PathPrefix. It's unfortunately not documented yet, but the tread http://ez.no/community/forum/setup_design/pathprefix_and_media_and_users_folder_problem discuss some of the issues.
I myself have not experience in usint it, but I have a site with the same issues as you describe, and I'm planning to take a closer look at PathPrefix.

It would be nice if you posted your experience.

Roy

Ciprian Popovici

Friday 24 March 2006 7:21:23 am

Not bad, Roy, that PathPrefix is a sweet thing. What I did was go to my site.ini override and make sure to add this:

[SiteAccessSettings]
PathPrefix=mysite_com

What this does is transform all URL's so that <b>/index.php/mysite_com/page/</b> is no longer valid, but instead <b>/index.php/page</b> is.

Even better, all URL's generate by <link> or <a> tags inside XML blocks are by default affected by this and are generated directly in the form <b>/index.php/page</b>, which is very nice.

Still, you have "index.php" in both the XML block generated links and in the URL's.

To get rid of the "index.php" in the URL one can use the mod_rewrite rules above, but slightly changed:

RewriteCond %{HTTP_HOST} ^(www\.)?mysite\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/index\.php/ [NC]
RewriteCond %{REQUEST_URI} !^/design/ [NC]
RewriteCond %{REQUEST_URI} !^/var/ [NC]
RewriteRule ^(.*)$ /index\.php/$1 [L]

However, messing with the way XML object generates internal links is a bit more tricky. What you do is go in the admin interface to Design/Templates, browse until you come across <b>/content/datatype/view/ezxmltags/link.tpl</b> and you create a new override, let's call it link_stripped.tpl. Use a copy of the original, not an empty file. (And take care to create the override for the siteaccess you have business with!)

Next, you go edit the file (found under design/mysite_com/override/templates/link_stripped.tpl. You edit it and replace the <b>{$href|ezurl}</b> part with <b>{$href|ezroot}</b> and that's it, now generated links only contain the /page part!

Ciprian Popovici

Friday 24 March 2006 7:23:28 am

BTW, here's a more advanced replacement for link.tpl, for people who don't want to use PathPrefix, or who just want to get ideas. So, you replace <b>{$href|ezurl}</b> with this:

"{concat($href|explode('/')|remove(0,1)|implode('/')|ezroot(no),'/')}"

What this does:
1. Take the full generated URL.
2. Split it into pieces at the / marks and obtain an array.
3. Remove the first element of the array (which would be "mysite_com").
4. Stick together the pieces again, using / for the glue.
5. Pass the thing through ezroot (not ezurl, so we don't get index.php in front.
6. Use ezroot(no) so we don't get it enclosed in quote marks.
7. Concatenate what we got with an extra /, and only now place the whole thing inside double quotes.

Before this (and without PathPrefix) generated URL's would look like this: <b>/index.php/mysite_com/page</b>. But after this trick we get this: <b>/page/</b>.

Ciprian Popovici

Friday 24 March 2006 7:27:54 am

<b>Warning:</b> apparently, ezroot does not play nice with pure anchor links (such as <a href="#section">). If you have such links you'll be forced to use ezurl, but in that case you'll still get /index.php. :( Here's an updated links.tpl replacement that takes care of this (this is the PathPrefix variant):

{if eq($href|extract_left(1),'#')}{$href|ezurl}{else}"{$href|ezroot(no)}/"{/if}

So, only use ezroot if link is not a local anchor.

Roy Bøhmer

Thursday 30 March 2006 5:17:57 am

Thanks for your updates!
I will soon dive into it myself, and will read you experience carefully.

Roy

Ciprian Popovici

Thursday 01 June 2006 1:41:39 am

Some updates. First, my latest and revised mod_rewrite rules. Please note that they are only useful in the context described above.

# mod_rewrite rules
RewriteEngine On

##################################################
# exempt admin site from any rewriting
##################################################

RewriteCond %{HTTP_HOST} ^admin\.my_site\.com$ [NC]
RewriteRule .* - [L]

##################################################
# rewrite rules common to all ez sites
##################################################

# restrict /node/ or /content/ access 
# ...allow interactive content (forms) and downloads
RewriteCond %{REQUEST_URI} !^/(index\.php/)?content/(action|collectedinfo|download) [NC]
# ...disallow for anything else
RewriteCond %{REQUEST_URI} ^/(index\.php/)?(content|node) [NC]
RewriteRule .* - [F,L]

# SEO friendly URL's
RewriteCond %{REQUEST_URI} !^/var/ [NC]
RewriteCond %{REQUEST_URI} !^/index\.php/ [NC]
RewriteCond %{REQUEST_URI} !^/design/ [NC]
RewriteRule ^(.*)$ /index\.php/$1 [L]

##################################################
# my_site.com
##################################################

# under construction, don't allow access from anybody but dev team
RewriteCond %{HTTP_HOST} ^(www\.)?my_site\.com$ [NC]
RewriteCond %{REMOTE_ADDR} !^(666\.666\.666\.666|69\.69\.69\.69)$
RewriteRule .* - [F,L]

##################################################
# my_other_site.com
##################################################

# currently up, no special rules

Explanations:
* We turn the mod_rewrite engine on.
* We exempt the admin site from any mod_rewrite tricks, by acknowledging it and stopping short with an empty [L]ast rule.
* The rules common to all hosted sites first block all dynamic /node/ and /content/ access except the strictly necessary stuff. This, by the way, will also conceal givaway URL's that can tell others you're using ez Publish for your sites.
* The 2nd part of the common rules is for nice URL rewriting and they're mostly the same as above.
* Next, you can add special rules for individual sites. One of them is working and needs no such rule, but another one is under construction so I block anybody not comping from one of 2 IP's with a [F]orbidden rule.

---------------------------------

Next, an updated link_stripped.tpl override, which in addition to making nice internal links also properly handles anchor links (#), the root link (/) and external links (http://):

<a href={if eq($href,'/')}"/"{else}{if eq($href|extract_left(1),'#')}{$href|ezurl}{elseif eq($href|extract_left
(7),'http://')}"{$href}"{elseif eq($href|extract_left(5),'https')}"{$href}"{else}"{$href|ezroot(no)}/"{/if}{/if
}{section show=$id} id="{$id}"{/section}{section show=$title} title="{$title}"{/section}{section show=$target}
target="{$target}"{/section}{section show=ne($classification|trim,'')} class="{$classification|wash}"{/section}
>{$content}</a>