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