Logan Serman
Logan Serman

Reputation: 29870

Eliminating the need for the global keyword in PHP

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

Answers (2)

Logan Serman
Logan Serman

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

GolezTrol
GolezTrol

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

Related Questions