Making a variable global is not a good idea when you using an MVC patterns in a project. There are other solutions that will make use of your MVC more wisely.
If you should have a single use of a resource, use a singleton pattern. Something like
class My_View {
private $_instance;
static public function getInstance() {
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
private function __construct() { }
public function __clone() {
trigger_error("Cannot make copy of this object", E_USER_ERROR);
}
// add public methods and/or properties here...
}
and get that view object anywhere with
$view = My_View::getInstance();
This way, you don't have global variables and you are using best OO practices.
However, as others have pointed out, having a singleton view is not necessarily a good idea... A probably better approach would be to make your dispatcher code create a new view and set it to the controller being called, so the controller would have a view available and access it directly.
The view (not being a singleton) could also be a public property, or accessible though a public method of an application singleton; My_Application::getInstance()->getView();
that could also hold the current configuration, paths,
The name My_view
suggested is merely an example. Using some sort of naming convention helps organize the code and helps getting rid of all those include/require calls in your script headers. This is not in your question's scope, however for clarity's sake, I'll briefly explain :
In your bootstrap, you declare your autoloading function (as defined in the PHP manual) :
// My_Application.php located in /path/to/lib/My/Application.php
class My_View {
private $_instance;
static public function getInstance() {
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
private $_basePath;
public $view;
private function __construct() { }
public function __clone() {
trigger_error("Cannot make copy of this object", E_USER_ERROR);
}
public function initAutoloader($base) {
$this->_basePath = $base;
spl_autoload_register(array($this, 'autoload'));
}
public function autoload($name) {
require $this->_basePath . str_replace('_', '/', $name) . '.php';
}
// get the application global view
public function getView() {
if (null === $this->view) {
$this->view = new My_View();
}
return $this->view;
}
}
// perhaps have the parameter being a constant. I.g. APP_BASE_PATH
My_Application::getInstance()->initAutoload('/path/to/lib/');
And simply include the file '/path/to/lib/My/Application.php'
and when you will access My_View
, the load
function will be called with $name = 'My_View'
and the function will simply require the file '/path/to/lib/My/View.php'
for you. This is not much for one file, but if all classes are namespaces like so, you only need one include (Autoloader
) and everything else is loaded automatically.