PHP中类之间共享类实例的最佳方式


Best way to share class instance between classes in PHP

在两个继承类之间共享类实例的最佳方式是什么?

// Let's create a main class that hold common methods and connects to the database
class MyApp {
    public $DB;
    function __construct () {
        // Connect to the database here
        $this->DB = new Database();
    }
}
// This will hold methods specific to the user management
class Users extends MyApp {
    function __construct() {
        parent::__construct();
    }
}
// This will hold methods specific for fetching news articles
class News extends MyApp {
    function __construct() {
        parent::__construct();
    }
}

现在,在我的应用程序中,我有一个页面,在同一页面上显示用户和新闻。所以我做了这样的事情:

// Instantiate the users class (this will connect to the db)
$users = new Users();
// Instantiate the news calls (PROBLEM! This will create a new db connection instead of re-using the previous one)
$news = new News();

我可以将DB实例分开,然后传入

$db = new Database();
$users = new Users($db);
$news = new News($db);

但现在我到处传递这个愚蠢的$db变量——这感觉很混乱,很容易出错。

有更好的方法来构建它吗?理想的解决方案是这样的:

// Instantiate a global class which will connect the DB once
$App = new MyApp();
// Reference sub-classes which all share the parent class variables.
// Unfortunately PHP doesn't seem to have sub-class support :(
$App->Users->someMethod();
$App->News->someMethod();

如果你想实现你想要的,你可以这样做:

class Database
{
    public function __construct()
    {
        echo "connecting to database...<br />";
    }
}
class MyApp
{
    public $Users;
    public $News;
    public function __construct()
    {
        $this->db = new Database();
    }
    public function initialize(array $classes)
    {
        foreach ($classes as $class) {
            $this->$class = new $class($this->db);
        }
    }
}
class Users
{
    public function __construct(Database $db)
    {
        echo "users have now db connection<br />";
    }
    public function someMethod()
    {
        echo "hello from users<br />";
    }
}
class News
{
    public function __construct(Database $db)
    {
        echo "news have now db connection<br />";
    }
    public function someMethod()
    {
        echo "hello from news<br />";
    }
}
$App = new MyApp();
$App->initialize(['Users', 'News']);
// Reference sub-classes which all share the parent class variables.
// Unfortunately PHP doesn't seem to have sub-class support :(
$App->Users->someMethod();
$App->News->someMethod();

当然,这只是一个示例,您应该添加更多的检查,运行上述代码的输出将是:

connecting to database...
users have now db connection
news have now db connection
hello from users
hello from news

然而,更好的方法是注入MyApp构造函数数据库连接,而不是在构造函数中创建新实例。

编辑

作为替代方案,您可以将数据库传递给构造函数并使用神奇的__get函数,这样您现在就可以使用:

class Database
{
    public function __construct()
    {
        echo "connecting to database...<br />";
    }
}
class MyApp
{
    protected $data;
    protected $allowed = ['Users','News'];
    public function __construct(Database $db)
    {
        $this->db = $db;
    }
    public function __get($name) {
        if (in_array($name, $this->allowed)) {
            if (!isset($this->data[$name])) {
                $this->data[$name] = new $name($this->db);
            }
            return $this->data[$name];
        }
        throw new Exception('No '.$name.' property!');
    }
}
class Users
{
    public function __construct(Database $db)
    {
        echo "users have now db connection<br />";
    }
    public function someMethod()
    {
        echo "hello from users<br />";
    }
}
class News
{
    public function __construct(Database $db)
    {
        echo "news have now db connection<br />";
    }
    public function someMethod()
    {
        echo "hello from news<br />";
    }
}
$App = new MyApp(new Database());
$App->Users->someMethod();
$App->News->someMethod();

其输出为:

connecting to database...
users have now db connection
hello from users
news have now db connection
hello from news