I am having a hard time fixing a redundancy of the setPageDir() function, which is found in two of my three of my MVC classes (ActionController and FrontController). 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!
<?php
class FrontController extends ActionController{
//Declaring variable
private static $instance;
protected static $pageDir;
protected $controller;
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; //Full exception echoed
} else {
echo $e->errorMessage(); //Simple error messaged echoed
}
}
}
}
abstract class ActionController {
//Declaring variable(s)
protected 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->setVar("actionView","$this->actionView");
$view->render();
}
}
class View extends ActionController {
public function render() {
//The following TWO blocks of code can go in a registry + the pageDir
//Default variables, (To be placed in an outside/included file!!)
$title = "Example";
//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.
The Singleton Pattern
The Singleton is one of the simplest Patterns to understand. It's common usage is to ensure
that only one instance of a class is ever instantiated. The reason for wanting such behaviour
varies but typically it is because only one object instantiated from the source class is
required and you want the resulting object to be available throughout an application, i.e.
globally available.
Reference(s):
"A lightweight and flexible front controller for PHP 5" by Chris Corbyn
http://www.w3style.co.uk/a-lightweight-and-flexible-front-controller-for-php-5
*/
?>