Question

Part 1

I want to build a PHP Zend Framework application that users can sign up to use. When they register, I would like the application to create a sub-domain that points to their public page, that serves up content specific to that client.

For example: http://mywebapp.com/username or http://username.mywebapp.com

Update: "Using sub-domains as account keys" is a good tutorial that pretty much answered my question on this one. This involves using Zend_Controller_Router_Route_Hostname.

However, I am still wondering...

Question #1: the tutorial doesn't mention setting up a wildcard sub-domain. Is this necessary in order to achieve this? Is there any way around using a wildcard subdomain?


Part 2

I will also need to offer users the ability to register domain names and point them to their page. So if you were to go to http://clientdomain.com, you would be seeing http://clientname.mywebapp.com, but you would never be able to tell because the url in the address bar shows http://client1.com. Does that make sense? I think the process is called domain masking. I basically want to offer my users free domain masking.

Update: I've just discovered the world of domain reseller APIs. OpenSRS looks nice. Do you have one to recommend?

Question #2: How does domain masking work? Can it work with a domain reseller API?

Was it helpful?

Solution

For Part 1 of your question you can implement any of the solutions here - but I am not sure you need a router - you will not offer a different functions for each site - you just want to load up different content based on the URL. We handle this in quite a simple way:

  1. In your bootstrap.php you need to grab the server URL
  2. Take the URL and strip out the portion after http:// and before .mywebapp.com
  3. Lookup this prefix in a database table and load any information you need to about the user or other information to do with this prefix
  4. Put an object into Zend_Config that you can then access from any page with the site details (we call this siteinfo).
  5. Modify your controllers or views to respond differently based on siteinfo - ie. change what data they retrieve etc

You will need to modify apache to handle this - and the easiest way is to make sure your default domain (the pages that come up when a URL is not recognised) is set to your application.

Handling the DNS changes is not that easy - you need to have a DNS server that can handle wildcard replies.

Part 2: I think you are saying that if I enter the URL http://grouchal.com that this would redirect to http://grouchal.yourwebapp.com. This would require me to update the existing DNS server entries for grouchal.com so that your server is found.

If you want to see a good example of this working in practice you should set-up a google apps for your domain account. I have urls like mail.grouchal.com that once typed in become mail.google.com/a/grouchal.com. This required me to set up the grouchal.com DNS server to point at a google server. The google server then puts a redirect in place to change the url to the one they need.

Going back to the solution I proposed above you would modify it so that in addition to checking the prefix for when your domain name is there (ie stripping out grouchal from http://grouchal.mywebapp.com) it would also look up alternate domains. So if there is no mywebapp.com in the address then it would look up in the database grouchal.com and then set the siteinfo using that data.

Hope this makes sense - the problems you will have will not be in PHP but in setting up your wildcat DNS server and getting your customers to configure their DNS servers correctly. Good luck with the project though.

OTHER TIPS

First, you are right. You don't want multiple instances/installs of your app. Setup multiple Apache virtual hosts to point at the Doc Root.

ServerName  www.serverOne.com
DocumentRoot "/htdocs/myapp/public"
SetEnv CONFIG_ENV "serverOne"   

ServerName www.serverTwo.com
DocumentRoot "/htdocs/myapp/public"    
SetEnv CONFIG_ENV "serverTwo"   

Put all your base urls, paths, etc in different sections of a Zend_Config_Xml file.

<?xml version="1.0" standalone="yes"?>
<config>
<siteOne>
   <base_url>http://www.siteOne.com</base_url>
       <image_path>/images/siteOne/</image_path>
       <database>
          <host>34.23.34.457</host>
          <name>siteOne_DB</name>
          <user>siteOne</user>
          <pass>**********</pass>
       </database>
    </siteOne>
    <siteTwo>
   <base_url>http://www.siteTwo.com</base_url>
       <image_path>/images/siteTwo/</image_path>
       <database>
          <host>34.23.34.456</host>
          <name>siteTwo_DB</name>
          <user>siteTwo</user>
          <pass>**********</pass>
       </database>
    </siteTwo>
</config>

Then in your /public/index.php

<?php
require '../common/config/Bootstrap.php';
$bootstrap = new Bootstrap($_SERVER['CONFIG_ENV']);
$bootstrap->runApp();
?>

And in Bootstrap.php's runApp() method:

function runApp($env)
{
   $root   = realpath(dirname(__FILE__) . '/..');
   $config = new Zend_Config_Xml($root . '/config.xml', $env);

This will work perfectly with relative links, and it doesn't require any pattern matching :)

If you don't have a Bootstrap.php file, you can learn how to create & use on in Manning Press's "Zend Framework In Action" book, available instantly as a PDF download. It helped me through some tough times.

As Zend Framework uses the MVC pattern, you can have single models and controllers and then different views for each domain.

After having customized views, you can detect the typed domain and show the correct views. For example, in your bootstrap you can detect the domain this way:

// Bootstrap or controller
$domain = array_reverse(split('[.]', $_SERVER['SERVER_NAME']));
$domain = $domain[1] . '.' . $domain[0];

// Store domain in registry
Zend_Registry::set('domain', $domain);


// Calling the view from the controller
$domain = Zend_Registry::get('domain');
$this->render($domain . 'home');

It's just and idea!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top