在两个继承类之间共享类实例的最佳方式是什么?
// 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