views:

812

answers:

5

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?

A: 

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!

MC
What would happen if I used a subdomain (client1.myapp.com) and masked it with another domain (client1.com)? I don't know anything about domain masking, but would this solution prevent me from doing that?
Andrew
It wouldn't stop you from putting client1.example.com into a frame as client1.com, but it is far better to check the $_SERVER['HTTP_HOST'] for client1.com (or sub-domains) and act according to that.
Alister Bulman
+3  A: 

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&lt;/base_url&gt;
       <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&lt;/base_url&gt;
       <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.

lo_fye
This won't work if you want both sites to use the same code but with a single parameter changed!
Grouchal
I don't see why it couldn't. One of the values you could set in the $config is $site_id. The code can behave however it wants based on rules associated with each $site_id.
lo_fye
+2  A: 

i think http://www.nabble.com/routes-like-username.domain.com-to21943784.html#a21981209 may hold the answer

i think u will use the Zend_Controller_Router_Route_Hostname

iceangel89
thanks for the links, they helped me find http://www.noginn.com/2008/09/03/using-subdomains-as-account-keys/ which is a really good tutorial on what I am trying to achieve...however, I don't know if this works out-of-the-box without doing anything with Apache...do you know?
Andrew
hmm thats a good question, i also dont know, i havent tried that
iceangel89
+1  A: 

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.

Grouchal
I don't want to "redirect", I want to mask http://username.myapp.com with a new domain. The location in the browser shouldn't change. How would this implimentation differ from that which you described?
Andrew
OK - just use exactly the same solution - but take out the redirect - once someone has your server in their DNS records - it is up to you to do the rest. So where I mentioned http://grouchal.com - then redirect - just skip this stage and look up grouchal.com in your DB and load properties based on this site.
Grouchal
A: 

I would use this: http://framework.zend.com/manual/en/zend.controller.router.html

wenbert