shivrajsa

Multisites with same templates and different databases

Recommended Posts

Hello,

I am new to PW and learning this great tool for web development.

I have already created a site for portfolio showcase using PW

Same site templates will be used for different portfolio showcase with different sites / domain and different database.

For all the sites front end design/display will be same.

So, in future if I wan to modify display of sites, I have to edit template file [ i.e. /site/template/file.php ] for each domain, which is not a good solution.

I want a solution where I will modify at single place and that will be reflected in every domain / site.

Is there any way to achieve this ? Please guide

Share this post


Link to post
Share on other sites

You should be able to point to different databases in your config.php depending on hostname. Something like this _should_ work, but I haven't tried it:

<?php
// config.php
if($_SERVER['HTTP_HOST'] == 'firstsite.com') {
    $config->dbHost = 'localhost';
    $config->dbName = 'db_for_first_site';
    $config->dbUser = 'user';
    $config->dbPass = 'password';
  
} else if ($_SERVER['HTTP_HOST'] == 'secondsite.com') {
    $config->dbHost = 'localhost';
    $config->dbName = 'db_for_second_site';
    $config->dbUser = 'anotheruser';
    $config->dbPass = 'password';
}

 

  • Like 1

Share this post


Link to post
Share on other sites

Welcome @shivrajsa,

The simplest way would be for the template files in each /site/templates/ directory to consist only of include() statements, which draw from a central templates directory at /templates/. Ryan suggests something like this here:

Or, as also mentioned in that thread, you could consider using symlinks.

  • Like 1

Share this post


Link to post
Share on other sites

Thank you @abdusand @Robin S .

For @abdus answer, how can we use different domains on same site folder ? because all template files and config file will be in one folder. I am curious to understand this solution.

For @Robin S , I explored little about symlinks and I discovered, it has to be allowed by hosting provider before going live.

 

Share this post


Link to post
Share on other sites
4 hours ago, shivrajsa said:

Thank you @abdusand @Robin S .

For @abdus answer, how can we use different domains on same site folder ? because all template files and config file will be in one folder. I am curious to understand this solution.

For @Robin S , I explored little about symlinks and I discovered, it has to be allowed by hosting provider before going live.

 

I tried it, it works just fine. Here's how you do it

  • Create a new database for the other site(s). Add new database user and set correct permissions & privileges.
    I duplicated mine by dumping into .sql file, changing its name then reimporting in Adminer panel
  • Go to config.php, update $config->httpHosts to include other domains, then add new database info like so:
    $config->dbHost = 'localhost';
    $config->dbPort = '3306';
    
    $config->httpHosts = array('pw.dev', 'pw2.dev');
    
    if($_SERVER['HTTP_HOST'] == 'pw.dev') {
        $config->dbName = 'pw';
        $config->dbUser = 'pw';
        $config->dbPass = 'password';
    
    } else if ($_SERVER['HTTP_HOST'] == 'pw2.dev') {
        $config->dbName = 'pw_dev';
        $config->dbUser = 'pw_dev';
        $config->dbPass = 'password';
    }

     

  • Update your HTTP server configuration. 
    I use Caddy Server, which makes these changes trivial.
     

    # old 
    pw.dev:80 {
            root /www/pw/
            # other configs
    }
    
    # add new host
    pw.dev:80, pw2.dev:80 {
            root /www/pw/
            # other configs
    }
    
    # both hosts share the same root!

     

  • Reload HTTP server (Apache, nginx, Caddy etc) and enjoy!

Here it is in action:

2017-04-07_11-56-11.mp4 (1MB video, 00:24 sec)

  • Like 1

Share this post


Link to post
Share on other sites

Thank you again @abdusIt seems amazing.

This topic is little advance for me considering my knowledge, so I have few more questions.

I am wondering if such type of server configuration is allowed by hosting provider and where can I edit this server configuration in CPanel.

I got this doc, but it talks about different directory for each domain

https://blog.cpanel.com/managing-multiple-domains-from-a-single-cpanel-account/

Also, just a quick query, can I use candy server on my shared hosting account ?

 

 

 

Share this post


Link to post
Share on other sites
2 hours ago, shivrajsa said:

Thank you again @abdusIt seems amazing.

This topic is little advance for me considering my knowledge, so I have few more questions.

I am wondering if such type of server configuration is allowed by hosting provider and where can I edit this server configuration in CPanel.

I got this doc, but it talks about different directory for each domain

https://blog.cpanel.com/managing-multiple-domains-from-a-single-cpanel-account/

Also, just a quick query, can I use candy server on my shared hosting account ?

You're probably not allowed to make changes in server, or install new packages if you're on a shared hosting (judging by the use of CPanel). But I am guessing it's possible, because reading the guide on the link you posted, there's this screenshot. This probably allows pointing to same directory  However, you will probably need to upgrade your hosting account for multiple domains.

Also if you use this setup, databases will be unique but since both setups point to same /site directory, assets folders will eventually clash since both sites are unaware of the other's page ids. To solve this you may need to change site path as well. I'll look into how when I am back on PC.

Edit: solved it below

Share this post


Link to post
Share on other sites

Note that "there are times" when $_SERVER['HTTP_HOST'] and similar are undefined, eg. when running PW from CLI (bootstrapping), because of this, I normally use something like this:

if(strstr(getcwd(),'/full/path/to/dev')) {
	// DEV settings
} else if(strstr(getcwd(),'/full/path/to/stage')) {
	// STAGE settings
} else {
	// PRODUCTION settings
}
[credit]
  • Like 1

Share this post


Link to post
Share on other sites
2 hours ago, abdus said:

You're probably not allowed to make changes in server, or install new packages if you're on a shared hosting (judging by the use of CPanel). 

Also if you use this setup, databases will be unique but since both setups point to same /site directory, assets folders will eventually clash since both sites are unaware of the other's page ids. To solve this you may need to change site path as well. I'll look into how when I am back on PC.

By overriding $config->paths and $config->urls, I got it to work. Both sites use different directories for uploads unaware of each other. I couldn't override $config->site->assets, which would have been a much better option, anyone know how?

<?php
$config->dbHost = 'localhost';
$config->dbPort = '3306';

$config->httpHosts = array('pw.dev', 'pw2.dev');

if($_SERVER['HTTP_HOST'] == 'pw.dev') {
    $config->dbName = 'pw';
    $config->dbUser = 'pw';
    $config->dbPass = 'password';
    $config->paths->files = $config->paths->site . '/assets/files-first/';
    $config->urls->files = $config->urls->site . '/assets/files-first/';
} else /*if ($_SERVER['HTTP_HOST'] == 'pw2.dev')*/ {
  	// remember to default to some site if HTTP_HOST is not set!
    $config->dbName = 'pw_dev';
    $config->dbUser = 'pw_dev';
    $config->dbPass = 'password';
    $config->paths->files = $config->paths->site . '/assets/files-second/';
    $config->urls->files = $config->urls->site . '/assets/files-second/';
}
1 hour ago, szabesz said:

Note that "there are times" when $_SERVER['HTTP_HOST'] and similar are undefined

Checking path is quite good, I'll probably implement some setup like this to set up a staging environment. Right now I'm just using reverse SSH tunnel to redirect localhost to web. 

One thing however, since both sites use the same templates, paths wouldn't be different, but you can create a symlink to solve that. 

  • Like 3

Share this post


Link to post
Share on other sites
1 hour ago, abdus said:

One thing however, since both sites use the same templates, paths wouldn't be different, but you can create a symlink to solve that.

Yeah, valid point ;) I just did not follow the thread properly and only spotted the usage of the variable which I also used to use to tell apart my local machine from the server but recently switched to checking the path instead.

  • Like 1

Share this post


Link to post
Share on other sites

It seems very simple solution, i.e.  pointing multiple domain to same directory where all sites will have same templates and managing their database settings in config file.

I think keeping assets folder different is a good idea if we ever want to export assets related to specific site. I will give it a try soon.

Thank you @abdus and all for help and guidance.

  • Like 1

Share this post


Link to post
Share on other sites

You might need to override paths for other site specific directories, such as cache, logs, sessions to get a better separation. If it were possible override assets directory altogether, that would be much better, but for now, this should suffice.

If anyone knows how to override /site/assets/ path, I'd love to be enlightened.

  • Like 1

Share this post


Link to post
Share on other sites

Thank you @abdus

I am also thinking on another strategy .i.e "Multiple sites with same database" but problem I see is, there will be same database of users who will have edit rights for all the sites.

I want to assign edit rights to separate user for each site. And other users will not have access to that particular site.

I will open another thread for this discussion so that it is easy to track. 

Based on the simplicity and maintainability of solution, I will select my strategy. 

Share this post


Link to post
Share on other sites

@gebeer, unfortunately PW ignores it.

<?php 
$config->paths->assets = config()->paths->root . 'test/';
$config->urls->assets = config()->urls->root . 'test/';
// doesn't work :(

 

Share this post


Link to post
Share on other sites

@abdus

your code throws an error for me: `Uncaught Error: Call to undefined function ProcessWire\config()`

And this code works ( note the $config instead of config() ):

$config->paths->assets = $config->paths->root . 'test/';
$config->urls->assets = $config->urls->root . 'test/';

 

Share this post


Link to post
Share on other sites
34 minutes ago, gebeer said:

@abdus

your code throws an error for me: `Uncaught Error: Call to undefined function ProcessWire\config()`

And this code works ( note the $config instead of config() ):


$config->paths->assets = $config->paths->root . 'test/';
$config->urls->assets = $config->urls->root . 'test/';

 

I'm using PW from dev branch with Functions API enabled. In your config.php add

$config->useFunctionsAPI = true 

https://processwire.com/blog/posts/processwire-3.0.39-core-updates/

 

Were you able to override assets directory altogether? 

Share this post


Link to post
Share on other sites

@abdus ok, I see.

When I echo $config->paths->assets in a template file I get '/DATA/htdocs/test. So it seems to be working and picking up the changed path from config.php.

Share this post


Link to post
Share on other sites

Paths echo whatever you set them to, but try uploading a file, do you get /site/test/files directories? In my case I didnt get new directories even though paths seem to change, it kept uploading to /site/assets/files

Share this post


Link to post
Share on other sites

@abdus As the $config variable inherits all methods and properties from WireData, you can try and use the set method

$config->paths->set('assets', $config->paths->root . 'test/');

I don't have the time to try this right now. So give it a try yourself and let me know.

Share this post


Link to post
Share on other sites

Nope, no change

<?php
// doesnt work
$config->paths->set('assets', $config->paths->site . '/assets-second/');
$config->urls->set('assets', $config->urls->site . '/assets-second/');

 

Share this post


Link to post
Share on other sites

I really like what you guys came up with here, I think I'm going to implement this on a bunch of websites. 

One thing to note is that when you are using multi-instance like I do, and you connect from a PW site that is not part of your 'multisite' setup, the $_SERVER['HTTP_HOST'] condition in config.php won't trigger and you will not get the data you are after. One way to get around this is to create the instance like this:

$site = new ProcessWire('/srv/users/me/apps/website/public/', 'http://website.dev/');

Adding the domain as the second parameter will set a variable called $httpHost (to 'website.dev' in my example) in wire\core\ProcessWire.php which is available to config.php. Therefore, if you alter the condition in config.php to this, multi-instance should work:

if ($_SERVER['HTTP_HOST'] == 'website.dev' || $httpHost == 'website.dev') {
    $config->dbName = 'name';
    $config->dbUser = 'user';
    $config->dbPass = 'pass';
    //etc
}

I have not tested this extensively but it seems to work fine.

Share this post


Link to post
Share on other sites

Has anyone managed to overwrite the cache path and URL? It does not seem to work so all sites will be sharing the same cache, which might be problematic.

Edit: looks like template cache does use the custom cache path/URL and other forms of cache use the default cache folder.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By ethanbeyer
      I have a question about Multiple Site implementation, and how to possible "share" modules between them.
      First, required reading: https://processwire.com/api/modules/multi-site-support/  I'm dealing with Option #1.
      The way this works is that in the root directory of a site, there is an index.config.php file that denotes what domain is mapped to which site-*/ directory.
      The project I am working on has three site-*/ directories, each with their own site-*/modules/ directory.
      What has happened is that a lot of the modules from site to site are the same.
      I was wondering if there was any way to "share" modules between sites in the Multiple Site setup, via symlink or alias, or potentially if there was some roadmapped feature that @ryan has planned to solve this issue.
      Either way, any help/pointers would be appreciated!
    • By gornycreative
      Hi!
      I've been working over a number of sites into processwire, but I have come across a strange bug I cannot wrap my head around.
      I'm using method #1. Single wire directory, multiple site- directories with index.config.php and config.php set up properly.
      I've had no problem setting domains in the configs up until this point. www and root domains are loading perfectly. However I tried to add a subdomain value 'new.domain.com' and I have put the bits in all the right spots. I get a 500 Internal Server Error.
      If I change the subdomain to something else, same deal. Only domain.tdl and www.domain.tdl entries are working.
      Any thoughts? I'm using the latest stable 3.X branch.
    • By iNoize
      Hello, 
      i need help i dont know what happen but i get this error
      Its an multipage installation with one core and many languages. 
      EN Version is ok but the DE version always error 500 also if i try to login to the backend.
      Exception: You do not have permission to execute this module - ProcessPageView (in /homepages/17/pathtosite/wire/core/Modules.php line 1225
      Errorlog: 
      2016-11-26 11:13:37    guest   http://de.mypage.com/?/  Error:     Exception: You do not have permission to execute this module - ProcessPageView (in /homepages/17/pathtosite/wire/core/Modules.php line 1225)
      2016-11-26 11:13:57    guest   http://de.mypage.com/?/  Error:     Exception: You do not have permission to execute this module - ProcessPageView (in /homepages/17/pathtosite/wire/core/Modules.php line 1225)  #0 /homepages/17/pathtosite/wire/core/Modules.php(1130): ProcessWire\Modules->getModule('ProcessPageView') #1 /homepages/17/pathtosite/index.php(53): ProcessWire\Modules->get('ProcessPageView') #2 {main}
      2016-11-26 11:14:34    guest   http://de.mypage.com/?/  Error:     Exception: You do not have permission to execute this module - ProcessPageView (in /homepages/17/pathtosite/wire/core/Modules.php line 1225)  #0 /homepages/17/pathtosite/wire/core/Modules.php(1130): ProcessWire\Modules->getModule('ProcessPageView') #1 /homepages/17/pathtosite/index.php(53): ProcessWire\Modules->get('ProcessPageView') #2 {main}
      2016-11-26 11:14:51    guest   http://de.mypage.com/?/  Error:     Exception: You do not have permission to execute this module - ProcessPageView (in /homepages/17/pathtosite/wire/core/Modules.php line 1225)
       
       
       
    • By ridgedale
      I'm wondering if anyone else has attempted this before.
      I've setup a basic test multisite installation that effectively includes the master site and 3 others subsites using either the basic or intermediate template. I can't remember which and there might even be a mix of both among them, but I don't think that should cause an issue.
      What I want to achieve is a Home tab in the navigation menu on each of the subsites that links directly to the Home page of the master site. Is it possible to do that within the processwire admin or is it something that is going to have to be hardcoded into the template file. If the latter, do I go about that as I cannot see anything that appears to relate to the navigation in each of the site directories.
      i.e. Is it possible to add a menu item to the left of the subsite "Home" page now named About that is simply a link named "Home" that redirects to the Home page of the master website?
      Any thoughts would be greatly appreciated.
    • By makari
      Hello,
      I need to redirect the old paths after migration to a multisite PW installation.
      There are 3 domains and small differences between paths
      i.e.


      old path: domain-2/?text
      new path: domain-2/text or domain-2/new_text

      I try it via .htaccess (in the root direction) with an 301 redirect:


      redirect 301 domain/old_path domain/new_path

      -> generates an 500 server error
      What is wrong? How to do that?