Reputation: 29870
I am making a simple PHP application with an MVC design. All of the requests are being sent to index.php
and then routed to the appropriate controller. Because all of the requests go through index.php
, I want to create some objects there and be able to use them globally, regardless of which controller handles the request. Namely, these objects are of type User
, ErrorHandler
, and Database
.
Having a global User
class, for example, allows any controller to check if the user is logged in by checking $user->loggedIn
(or something like that) where $user
is instantiated in index.php
.
Here is what I am describing in code:
// index.php:
<?php
include('lib/User.php');
$user = new User();
// other stuff that index.php needs to do, perhaps route to FooController
?>
// FooController.php:
<?php
class FooController {
function __construct() {
global $user;
if ($user->loggedIn) {
// do whatever
}
}
}
?>
This is just random code I just typed up so please excuse any stupid errors -- but I hope you get the idea. This code will work, but the global $user;
line must be included in every function inside FooController.php
.
This will get annoying when every function must have three global
statements, one for User
, ErrorHandler
, and Database
. Is there a better way to go about this, while preserving my MVC design?
Upvotes: 0
Views: 323
Reputation: 29870
I ended up doing this:
class BaseController
{
public $user, $db, $errors;
function __construct()
{
global $user, $db, $errors;
$this->user = $user;
$this->db = $db;
$this->errors = $errors;
}
}
Every controller extends the BaseController (which has some abstract functions as well, this is just an example of a BaseController which solves this specific problem). This way I only had to use global
once, and then I could use the user, db, and error handler instances across every controller by simply calling parent::__construct()
in each controller's constructor and then referring to them by $this->user
, etc.
Upvotes: 1
Reputation: 116110
You hardly ever need global
. Just don't create globals.
First. There's such a thing as parameters, for instance:
function __construct($user)
{ ... }
Now, you can call:
$controller = new MyController($user);
.. and you don't need 'global'.
Even better if your controller is, well, a controller that manages the flow of your entire application. In that case, you will only need to pass it a few classes, for instance a database class and maybe a parser for input. If you don't care about that, you can make the controller instantiate a database class and parser itself. You can always refactor that part if you need to support multiple types of databases and multiple kinds of input.
Then, those database can be set as a property of the controller. Each next class will know of this controller. You can set the controller instance in a global, or even better, pass it in the constructor of other classes, so they don't depend on globals at all.
If those classes don't need a controller, but just need a database, you can pass the database class only. That will make those classes even more independent from the controller and from any globals, so you can reuse them very easily in other applications, provided that the database itself doesn't depend (directly or indirectly) on the controller either.
Take a look at frameworks like Kohana. They solve these problems pretty well, although there's always room for improvement.
Upvotes: 2