Need help fixing redundant variable in three MVC classes...

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
kilbad
Forum Commoner
Posts: 28
Joined: Wed Apr 02, 2008 3:51 pm

Need help fixing redundant variable in three MVC classes...

Post by kilbad »

I am having a hard time fixing a redundancy of the setPageDir() function, which is found within all three of my MVC classes (ActionController, FrontController, and View). How can I best/most appropriately provide the value of the $pageDir variable to all these classes without being redundant? I feel like there must be a better way to do this than putting that function in each class and passing the variable through it?

Thank you all in advance!

Here are my MVC classes:

Code: Select all

 
<?php
 
class FrontController {
 
    //Declaring variable
    private static $instance;
    private static $pageDir;
 
    private function __construct(){}
    
    //Setting page directory and starting new instance of this class with a Singleton pattern
    public static function getInstance(){
        if(!self::$instance){
            self::$instance = new self();
        }
        return self::$instance;
    }
 
    //Setting the page directory, which is passed from the FrontController
    public static function setPageDir($pageDir){
        self::$pageDir = $pageDir;
    }
 
    public function dispatch($throwExceptions = false) {
 
        /*  
            Checking for the GET variables $module and $action, and, if present, will strip them down
            with a regular expression function with a white list of allowed characters, removing anything 
            that is not a letter, number, underscore or hyphen.
        */
 
        $regex = '/[^-_A-z0-9]++/';
        $module= isset($_GET["module"]) ? preg_replace($regex, '', $_GET['module']) : "home";
        $action = isset($_GET["action"]) ? preg_replace($regex, '', $_GET['action']) : "frontpage";
 
        //Generating class name (example: HomeActions)
        $class = ucfirst($module) . "Actions";
 
        //Generating path to Actions class (example: home/HomeActions.php5)
        $file = self::$pageDir . "/" . $module . "/" . $class . ".php5";
        if (!is_file($file)) {
            throw new FrontControllerException("Page not found!");
        }
 
        //Requiring the Actions class (example: home/HomeActions.php5)
        require_once $file;
 
        /*  
            Creating a new instance of the Actions class (example: $controller = new HomeActions();)
            and passing page directory variable to the ActionController class
        */
            
        $controller = new $class();
        $controller->setPageDir(self::$pageDir);
 
        try {
            //Using the setName function in the ActionController class
            $controller->setName($module);
 
            //Checks if the method exists, then runs the displayView function in the ActionController class
            $controller->dispatchAction($action);
        }
        catch(Exception $e){
            //An exception has occurred, and an error message will be displayed if $throwExceptions is set to TRUE
            if($throwExceptions){
                echo $e;
            } else {
                echo $e->errorMessage();
            }
        }
    }
}
 
abstract class ActionController {
 
    //Declaring variable(s)
    private static $pageDir;
    protected $name;
    protected $viewData = array();
 
    //Setting the page directory, which is passed from the FrontController
    public static function setPageDir($pageDir){
        self::$pageDir = $pageDir;
    }
 
    public function setName($name) {
        $this->name = $name;
    }
 
    public function getName() {
        return $this->name;
    }
 
    //Placing a value in the $viewData array at the key position
    public function setVar($key, $value) {
        $this->viewData[$key] = $value;
    }
 
    //Returns a value from the $viewData array located at the key position
    public function getVar($key) {
        if (array_key_exists($key, $this->viewData)) {
            return $this->viewData[$key];
        }
    }
    
    /*
        Checking for actionMethod in the Actions class (example: doFrontpage() within home/HomeActions.php5)
        with the method_exists function and, if present, the actionMethod and displayView functions are
        executed.
    */
    
    public function dispatchAction($action) {
        $actionMethod = "do" . ucfirst($action);
        if (!method_exists($this, $actionMethod)) {
            throw new FrontControllerException("Page not found!");
        }
        $this->$actionMethod();
        $this->displayView($action);
    }
 
    public function displayView($action) {
        if (!is_file(self::$pageDir . "/" . $this->getName() . "/" . $action . "View.php5")) {
            throw new FrontControllerException("Page not found!");
        }
 
        //Setting content variable to the path of the action View file
        $this->actionView = self::$pageDir . "/" . $this->getName() . "/" . $action . "View.php5";
 
        //Creating a new instance of the View class and passing the $pageDir, $viewData, and actionView variables
        $view = new View();
        $view->setPageDir(self::$pageDir);
        $view->setViewData($this->viewData);
        $view->setVar("actionView","$this->actionView");
        $view->render();
    }
}
 
class View extends ActionController {
 
    //Declaring variable(s)
    private static $pageDir;
 
    //Setting the page directory, which is passed from the FrontController
    public static function setPageDir($pageDir){
        self::$pageDir = $pageDir;
    }
 
    public function setViewData($viewData){
        $this->viewData = $viewData;
    }
 
    public function render() {
 
        //Default variables, (To be placed in an outside/included file!!)
        $title = "Example.com";
 
        //This foreach function goes over all of the elements in $this->viewData array, creates
        //a variable for every value, and the name of the value (the variable name) is the key's value.
        foreach ($this->viewData as $key => $value) {
            $$key = $value;
        }
 
        //Including a template file within which the action View file is included
        require_once self::$pageDir . "/default.tpl";
    }
}
 
class FrontControllerException extends Exception {
    public function errorMessage(){
        //Error message
        return $this->getMessage();
    }
}
 
/*
    Notes:
        Abstract Class:
            An abstract class is a class that cannot (or should not) be instantiated.
 
        PHP 5 allows you to declare properties and methods as public, private or protected.
        These are defined as:
            Public: anyone either inside the class or outside can access them
            Private: only the specified class can access them. Even subclasses will be denied access.
            Protected: only the specified class and subclasses can access them
        
        The PHP Static Statement:
            The PHP static statement is that it allows a function to "remember" the value of a local
            variable for the next time the function is called.
 
    Reference(s):
        "A lightweight and flexible front controller for PHP 5" by Chris Corbyn
        http://www.w3style.co.uk/a-lightweight- ... -for-php-5
 
*/
 
?>
 
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Need help fixing redundant variable in three MVC classes...

Post by Christopher »

This is a tough decision to make. Most frameworks do what you do and put it everywhere. In Skeleton we separate out the path finding from the Front Controller into a Mapper class (it maps requests to paths). The Skeleton Front Controller adds it to the Registry so it is available if the Action, View, etc. want to get path information. Otherwise it unobtrusive.

Another goal is to reduce the need to get paths in your code. We do that with loading functionality where you ask for things my location/scope (e.g. global, module, controller, action) rather than path.
(#10850)
Post Reply