Learning Laravel: dynamic domain control

EDIT: Fun fact.  Literally about 3 hours after I posted this, I learned this is called Multi-tenancy, which is what I’m describing below and how I achieved it my way as a Laravel newbie.  Now I’m seeing there is a better way and will post again with what I’ve learned.  Feel free to read this anyway, maybe I’m closer to doing it right than I think.

I’ve been toying with Laravel a bit, I purchased Laravel Up & Running after having seen many good reviews about it, and I even subscribed to Laracasts almost a year ago, wanting to learn, but not having a project to use it on.  That opportunity finally came, and I built a small user role management system for work. Its only 3 controllers, 1 model and two views. It was actually fun to use and I learned a lot by actually putting the things I had seen in the videos to practice.  I wanted to tackle something a bit larger.

I’ve written a Conference Management System (CMS – yea I know the ‘C’ usually stands for content) called ConferenSpy in “classic PHP” that allows conference admins to manage all aspects of a conference, workshop or event from venue setup to final evaluations, all with an accompanying mobile app for attendees to use during the conference.  I have two clients who hold large annual conferences (about 700 and 2000 attendees respectively) and smaller workshops and tech days throughout the year.

The event registration system was a small enough piece of this app (yea right) that I figured I’d tackle that with Laravel. The important thing to note is that the entire codebase (every .php page) reacts to the url that is given in this way –

http://{clientname}.conferenspy.com.  My php code then uses the url to get the client ID to pull content, configuration, etc.

If someone visited say http://pepsi.conferenspy.com – that would display the login page for the CMS for the Pepsi client.

The event url that contains the event information and registration links is pretty ugly right now and looks like this –

https://pepsi.conferenspy.com/event/event_details.php?Challenge2017

This allowed me to know the client was Pepsi, and I could grab the query-string to know which conference it is (Challenge2017).  I know some rewrite rules could have cleaned that up but whatever, they usually post a link on their site, or email it out.

Enter Laravel

I needed to achieve this with Laravel and found Route groups to be helpful.  I was able to put together a nice clean group to deal with this.  As I was planning this rewrite, I decided that I wanted the url to be useful for the CMS login as well as allow for an easy registration/event url, one you could remember like http://laracon.us (which I’m going to!)

I wanted something like this:

http://pepsi.conferenspy.com – just like above

http://challenge2017.conferenspy.com – would be the new easy url for the event page and registration links

This is a different approach than I had with my classic PHP app, but its much friendlier and easy to remember than the old event url format.  My route configuration has to get a portion of the url and determine whether it is a client or an event and serve up the appropriate view

Route::group(array('domain' => '{eventname}.{domain}.{ext}'), function()
{
    Route::get('/', function($eventname)
    {
      /**
      * This method determines if there is a conference configured for the URL specified
      * if there is, display the main event page for the event based on the URL
      * and if not it will redirect to the client /hub login if there is a configured
      * client for the URL specified.
      * ie.  http://codestorm.conferenspy.com -> redirect to /hub
      *      http://storm2017.conferenspy.com -> load event page for this event
      *      http://foobarnow.conferenspy.com -> load a "404" page
      **/

      $event_tag = str_replace(" ", "", $eventname);
      $is_event = App\Conference::where('conference_url', strtolower($event_tag))->first();

      if ($is_event == NULL) {
         // check for client configuration
         $is_client = App\Client::where('client_name', strtolower($event_tag))->first();

         if ($is_client == NULL) {
            // display url not configured page
            return view('site-not-found');
         } else {
            // display login
            return view('client-login');
         }

       } else {
         // This is an event url, run controller and method
         $app = app();
         $controller = $app->make('App\Http\Controllers\EventController');
         return $controller->callAction('displayEventDetails', $parameters = ['conference_id' => $is_event->conference_id]);
        }
    });

});

First – I know you’re thinking – why the heck are you doing {eventname}.{domain}.{ext} ?  Well because I have a different domain configuration on my local machine so I had to make both domain and ext variable and this worked, I don’t do anything with those however. If there’s an easier way to achieve the url parsing, let me know, I’m all about learning this.

Along those lines, since I’m new to this, I’m hoping that’s the proper way to call the EventController, it seems to work, but its a bit ugly.  If not, please feel free to comment and let me know if there’s a better, cleaner way.

I’ve also noticed as I build this out that I’m repeatedly passing objects around through the registration process.  I’ve read a bit about Composite Views, but not sure if that’s what I want, or how to implement them and not sure if that helps me not having to pass around objects or call methods to get data for the views (see still learning).

People joke about spaghetti PHP code and how a framework like Laravel can solve that. At times the Laravel code I’m writing looks elegant, and at other times, I’m not so sure.  It’s probably the learning curve and this being my first big app, I’m betting I’m creating spaghetti Laravel.  Sounds like a good title for a future blog post.

If you have suggestions or pointers feel free to comment, but remember, even though I have a copy of Laravel Up & Running, I may not (yet) understand what you’re saying 🙂

 

This entry was posted in Laravel. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *