【问题标题】:Best way to share class instance between classes in PHP在 PHP 中的类之间共享类实例的最佳方法
【发布时间】:2015-03-29 21:11:07
【问题描述】:

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

// 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();

【问题讨论】:

  • “我可以将数据库实例分开,然后将其传入”。这是正确的做法,尤其是从 TDD 的角度来看。

标签: php


【解决方案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 构造函数数据库连接而不是在构造函数中创建新实例会更好。

编辑

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

【讨论】:

  • 这看起来很难/不可能进行单元测试。
猜你喜欢
  • 1970-01-01
  • 2011-03-11
  • 2014-01-21
  • 2015-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-07
相关资源
最近更新 更多