How to avoid using PHP global objects?

2020-02-01 02:09发布

I'm currently creating blog system, which I hope to turn into a full CMS in the future.

There are two classes/objects that would be useful to have global access to (the mysqli database connection and a custom class which checks whether a user is logged in).

I am looking for a way to do this without using global objects, and if possible, not passing the objects to each function every time they are called.

标签: php global
4条回答
Evening l夕情丶
2楼-- · 2020-02-01 02:46

You could make the objects Static, then you have access to them anywhere. Example:

myClass::myFunction();

That will work anywhere in the script. You might want to read up on static classes however, and possibly using a Singleton class to create a regular class inside of a static object that can be used anywhere.

Expanded

I think what you are trying to do is very similar to what I do with my DB class.

class myClass
{
    static $class = false;
    static function get_connection()
    {
        if(self::$class == false)
        {
            self::$class = new myClass;
        }
        return self::$class;
    }
    // Then create regular class functions.
}

What happens is after you get the connection, using $object = myClass::get_connection(), you will be able to do anything function regularly.

$object = myClass::get_connection();
$object->runClass();

Expanded

Once you do that static declarations, you just have to call get_connection and assign the return value to a variable. Then the rest of the functions can have the same behavior as a class you called with $class = new myClass (because that is what we did). All you are doing is storing the class variable inside a static class.

class myClass
{
    static $class = false;
    static function get_connection()
    {
        if(self::$class == false)
        {
            self::$class = new myClass;
        }
        return self::$class;
    }
    // Then create regular class functions.
    public function is_logged_in()
    {
        // This will work
        $this->test = "Hi";
        echo $this->test;
    }
}

$object = myClass::get_connection();
$object->is_logged_in();
查看更多
闹够了就滚
3楼-- · 2020-02-01 02:52

Well, if you already have some object by which you refer to the blog system, you can compose these objects into that, so that they're $blog->db() and $blog->auth() or whatever.

查看更多
做个烂人
4楼-- · 2020-02-01 02:59

I recently revamped my framework in preparation for the second version of our company's CMS. I undid a huge amount of the things I made static in order to replace them with normal objects. In so doing, I created a huge amount of flexibility that used to rely on me going through and hacking into core files. I now only use static constructs when the only alternative is global functions, which is only related to low-level core functionality.

I'm going to show a few lines of my bootstrap.php file (all of my requests get sent through that file, but you can achieve the same result by including it at the top of every file) to show you what I mean. This is an pretty hefty version of what you'd probably use in your situation, but hopefully the idea is helpful. (This is all slightly modified.)

 //bootstrap.php

...

// CONSTRUCT APPLICATION

{       
    $Database = new Databases\Mysql(
        Constant::get('DATABASE_HOST'),
        Constant::get('DATABASE_USER'),
        Constant::get('DATABASE_PASSWORD'),
        Constant::get('DATABASE_SCHEMA')
    );

    $Registry     = new Collections\Registry;
    $Loader       = new Loaders\Base;
    $Debugger     = new Debuggers\Dummy; // Debuggers\Console to log debugging info to JavaScript console

    $Application  = new Applications\Base($Database, $Registry, $Loader, $Debugger);
}

...

As you can see, I have all kind of options for creating my application object, which I can provided as an argument in the constructor to other objects to give them access to these "global" necessities.

The database object is self-explanatory. The registry object acts as a container for object I may want to access elsewhere in the application. The loader acts as a utility for loading other resources like template files. And the debugger is there to handle debug output.

I can, for example, change the database class that I instantiate and, voila I have a connection to a SQLite database. I can change the class of the debugger (as noted) and now all of my debug info will be logged to my JavaScript console.

Okay, now back to the issue. How do you give other objects access to all of this? You simply pass it in an argument to the constructor.

// still bootstrap.php

...

// DISPATCH APPLICATION

{
    $Router = new Routers\Http($Application);
    $Router->routeUri($_SERVER['REQUEST_URI']); 
}

...

Not only that, but my Router (or whatever object I construct with it) is more flexible, too. Now I can just instantiate my application object differently, and my Router will behave differently accordingly.

查看更多
孤傲高冷的网名
5楼-- · 2020-02-01 03:01

You could pass the currently global objects into the constructor.

<?php
  class Foo {
    protected $m_db;
    function __construct($a_db) {
      $this->m_db = $a_db;
    }
  }
?>
查看更多
登录 后发表回答