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

时间:2015-03-29 21:11:07

标签: 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 = 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();

1 个答案:

答案 0 :(得分:1)

如果你想达到你想要的效果,你可以这样做:

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构造函数数据库连接,而不是在构造函数中创建新实例。

修改

作为替代方案,您可以将Database传递给构造函数并使用magic __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