1

I'd like to be able to reroute or redirect all requests to my site to a specific page, if a conditional passes. I'm assuming this would have to be done somewhere in the bootstrap or with the dispatcher, but I'm not sure exactly what the best/cleanest way to go about it would be.

No .htaccess redirects since a condition needs to be tested for in PHP

Here's what I'd like:

if( $condition ) {
    // Redirect ALL Pages/Requests
}

// else, continue dispatch as normal...

The idea here is that we can setup the entire website and send everything to a splash page until a specified date/time, at which point it would 'auto launch' itself essentially.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Ryan
  • 17,511
  • 23
  • 63
  • 88

4 Answers4

5

Why bother with routing? Just a simple redirect.

maybe something like this in Bootstrap.php:

public function initSplash(){
    if($splashtime && $requestIsNotForComingSoonAlready){
        header('Location: /coming-soon',true,302);
        die();
    }
}

or you could just stick the if statement at the top of your index.php, and avoid loading the framework completely

timdev
  • 61,857
  • 6
  • 82
  • 92
  • +1 for a simple solution, but I went with the plugin due to some more complexity that I needed to handle – Ryan May 13 '11 at 14:10
  • No, it's about 1/16th-assed. OP wants a splash page until date X (or the stroke of midnight, or whatever). The date condition doesn't depend on anything in the app, so using any more ass than is strictly necessary reeks of overengineering. – timdev May 13 '11 at 19:11
  • if you really want to get technical, you should just have a landing page and have ur framework on another machine with a different domain/subdomain – Ascherer May 15 '11 at 11:00
  • @Ascherer - That's a perfectly fine solution, but I wouldn't agree that one "should" do that, any more than my suggestion, or a cron job that swaps httpd.conf and restarts apache (or whatever). Many ways to skin a cat, etc. – timdev May 15 '11 at 23:12
  • i didnt say it doesnt work, i just implied that it isnt the way it "should" be done – Ascherer May 16 '11 at 00:06
  • Not to be argumentative, but considering the OP's stated problem (show splash page until time T, then proceed normally, and do it in PHP code), my solution is exactly the way you "should" do it. The solution you (and others) offered (a frontcontroller plugin), smells like overengineering in the extreme. After all, once time T comes and goes, this code may as well just be removed entirely. That's why I'd solve with a quick cronjob, but if I had to do a PHP solution, I'd stick it at the top of index.php, and remove it at T+N. – timdev May 16 '11 at 00:25
2

Indeed, I'd go for a plugin.

In library/My/Plugin/ConditionallyRedirect.php:

class My_Plugin_ConditionallyRedirect extends Zend_Controller_Plugin_Abstract
{
    public function routeStartup(Zend_Http_Request_Abstract $request)
    {
        // perform your conditional check
        if ($this->_someCondition()){
             $front = Zend_Controller_Front::getInstance();
             $response = $front->getResponse();
             $response->setRedirect('/where/to/go');
        }
    }

    protected function _someCondition()
    {
        // return the result of your check
        return false; // for example
    }

}

Then register your plugin in application/configs/application.ini with:

autoloaderNamespaces[]                        = "My_"
resources.frontController.plugins.conditional = "My_Plugin_ConditionallyRedirect"

Of course, other preferences/requirements for classname prefixing and for file location would entail slightly different steps for autoloading and invocation.

David Weinraub
  • 14,144
  • 4
  • 42
  • 64
  • 2
    preDispatch is far too late. You can use routeStartup() – Tomáš Fejfar May 12 '11 at 13:12
  • +1 @Tomáš Fejfar That's a very good point. Unless the condition actually depends upon the routing being completed. But you're right: my inference from the original question is that `routeStartup()` is better. Changing the answer. Thanks! ;-) – David Weinraub May 12 '11 at 13:45
  • Thanks @David Weinraub, I went with a solution based off yours. I had to check what the initial request was for to ensure I didn't infinitely redirect, and I could only seem to do that in preDispatch(), not routeStartup(). See my solution and let me know what you think. – Ryan May 12 '11 at 18:30
1

If you want to do it the right way, you'd have to do it in a class after the request is created so you can modify it before the response is sent. Normally not quite in the bootstrap. Id say put it somewhere with a plugin that has access to the front controller (similar to how an ACL would work)

Ascherer
  • 8,223
  • 3
  • 42
  • 60
1

Thanks @David Weinraub, I went with the plugin similar to yours. I had to change a couple things around though, here's my final result (with some of my application specific stuff simplified for the example here)

<?php

/**
 * Lanch project within valid dates, otherwise show the splash page
 */

class App_Launcher extends Zend_Controller_Plugin_Abstract
{
// The splash page
private $_splashPage = array(
    'module' => 'default',
    'controller' => 'coming-soon',
    'action' => 'index'
);

// These pages are still accessible
private $_whiteList = array(
    'rules' => array(
        'module' => 'default',
        'controller' => 'sweepstakes',
        'action' => 'rules'
    )
);


/**
 * Check the request and determine if we need to redirect it to the splash page
 * 
 * @param Zend_Controller_Request_Http $request
 * @return void
 */
public function preDispatch(Zend_Controller_Request_Http $request)
{
    // Redirect to Splash Page if needed
    if ( !$this->isSplashPage($request) && !$this->isWhiteListPage($request) && !$this->isSiteActive() ) {

        // Create URL for Redirect
        $urlHelper = new Zend_View_Helper_Url();
        $url = $urlHelper->url( $this->_splashPage );

        // Set Redirect
        $front = Zend_Controller_Front::getInstance();
        $response = $front->getResponse();
        $response->setRedirect( $url );

    }
}


/**
 * Determine if this request is for the splash page
 * 
 * @param Zend_Controller_Request_Http $request
 * @return bool
 */
public function isSplashPage($request) {

    if( $this->isPageMatch($request, $this->_splashPage) )
        return true;

    return false;

}


/**
 * Check for certain pages that are OK to be shown while not 
 * in active mode
 * 
 * @param Zend_Controller_Request_Http $request
 * @return bool
 */
public function isWhiteListPage($request) {

    foreach( $this->_whiteList as $page )
        if( $this->isPageMatch($request, $page) )
            return true;            

    return false;

}


/**
 * Determine if page parameters match the request 
 * 
 * @param Zend_Controller_Request_Http $request
 * @param array $page (with indexes module, controller, index)
 * @return bool
 */
public function isPageMatch($request, $page) {

    if(  $request->getModuleName() == $page['module']
      && $request->getControllerName() == $page['controller']
      && $request->getActionName() == $page['action'] )
        return true;

    return false;
}


/**
 * Check valid dates to determine if the site is active
 * 
 * @return bool
 */
protected function isSiteActive() {

    // We're always active outside of production
    if( !App_Info::isProduction() )
        return true;

    // Test for your conditions here...
    return false; 
            // ... or return true;

}

}

There's room for a some improvements but this will fit my needs for now. A side note, I had to change the function back to preDispatch because the $request didn't have the module, controller, and action names available in routeStartup, which were necessary to ensure we aren't redirecting requests to the splash page again (causing infinite redirect loop)

(Also just added a 'whitelist' for other pages that should still be accessible)

Ryan
  • 17,511
  • 23
  • 63
  • 88