使用扩展类(PHP)时的最佳技巧 [英] best trick when using an extending class (PHP)

查看:77
本文介绍了使用扩展类(PHP)时的最佳技巧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于我在这里的帖子:扩展PHP类时的问题

最佳解决方案是什么?为什么呢?


$query = $this->Execute("SELECT * FROM $table");
$total = $this->NumRows($query);


$query = DBManager::Execute("SELECT * FROM $table");
$total = DBManager::NumRows($query);


$query = parent::Execute("SELECT * FROM $table");
$total = parent::NumRows($query);

解决方案

扩展类时,子类除了可以定义任何子类之外,还可以调用父类的所有公共和受保护的方法和属性.如果您不需要重写父级的方法,而只想在子级内部的某个地方使用它们,请使用

public function somethingUsingExecute()
{    
    $query = $this->Execute("SELECT * FROM $table");
    …
}


如果您需要在子类中重写execute,但又想使用父类的原始功能来调用该方法,请使用

public function execute($table)
{
    // can do something not in parent before parent call
    $query = parent::Execute("SELECT * FROM $table");
    // can do something not in parent after parent call
}


静态调用

$query = DBManager::Execute("SELECT * FROM $table");

是您应该忘记它存在的东西,因为您正在将一个类名硬编码到using类中,并且还将方法调用耦合到全局范围.两者都很难测试和维护.我不再赘述,因为之前已经在SO上进行过讨论.只需进行搜索即可.


关于该User/DBManager示例的最佳技巧"实际上根本就不会使用继承.继承会创建一个 is-a 关系.孩子是父母的特例.但是用户不是DBManager(我将其称为DbAdapter btw).

您的DBManager类的职责是允许访问数据库.您的用户不承担该责任.它使用使用DBManager来访问数据库,但是它确实需要知道如何进行详细操作. DBManager已经这样做了.

使用 的任何类都应注入/聚集.因此,您应该做的是:

class User …

    protected $db;
    protected $isAuthenticated = FALSE;

    public function __construct($db)
    {
        $this->db = $db;
    }

    public function authenticate($username, $password)
    {
        if($this->db->query('SELECT … ')) {
            $this->isAuthenticated = TRUE;
        }
        return $this->isAuthenticated;
    }

    …
}

那你就可以做

$db = new DBManager;
$john = new User($db);
$john->authenticate('JohnDoe', 'jd/12345');
$jane = new User($db);
$jane->authenticate('JaneDoe', 'jd/67890');
$logger = new DBLogger($db);
$logger->log('something to db');

注入DB类具有额外的好处,您可以在其他使用类中重用现有的DBManager实例.如果扩展DBManager类,则每个新实例都将创建到数据库的新连接,出于性能原因,这是不希望的.

Regarding my post here: problems when extending a PHP Class

What's the best solution? And why?


$query = $this->Execute("SELECT * FROM $table");
$total = $this->NumRows($query);

Or


$query = DBManager::Execute("SELECT * FROM $table");
$total = DBManager::NumRows($query);

Or


$query = parent::Execute("SELECT * FROM $table");
$total = parent::NumRows($query);

解决方案

When you extend a class, the child class can call all the public and protected methods and properties of the parent class in addition to any the child defines. If you do not need to override the parent's methods, but just want to use them somewhere inside the child, use

public function somethingUsingExecute()
{    
    $query = $this->Execute("SELECT * FROM $table");
    …
}


If you need to override execute in a child class but also want to call that method with the original functionality of the parent, use

public function execute($table)
{
    // can do something not in parent before parent call
    $query = parent::Execute("SELECT * FROM $table");
    // can do something not in parent after parent call
}


The static call

$query = DBManager::Execute("SELECT * FROM $table");

is something you should forget it exists, because you are hardcoding a classname into the using class and also couple the method call to the global scope. Both is hard to test and maintain. I won't go into more details, because this has been discussed on SO before. Just give it a search.


The "best trick" regarding that User/DBManager example would actually be not use inheritance at all. Inheritance creates an is-a relationship. The child is a special case of the parent. But a User is not a DBManager (I'd call it DbAdapter btw).

The responsibility of your DBManager class is to allow access to the database. Your User does not have that responsibility. It uses the DBManager to get access to the database, but it does need to know how to do that in detail. The DBManager already does.

Any class using another class should be injected/aggregated. So, what you should do is:

class User …

    protected $db;
    protected $isAuthenticated = FALSE;

    public function __construct($db)
    {
        $this->db = $db;
    }

    public function authenticate($username, $password)
    {
        if($this->db->query('SELECT … ')) {
            $this->isAuthenticated = TRUE;
        }
        return $this->isAuthenticated;
    }

    …
}

Then you can do

$db = new DBManager;
$john = new User($db);
$john->authenticate('JohnDoe', 'jd/12345');
$jane = new User($db);
$jane->authenticate('JaneDoe', 'jd/67890');
$logger = new DBLogger($db);
$logger->log('something to db');

Injecting the DB class has the added benefit that you can reuse the existing DBManager instance in other using classes. If you extend the DBManager class, each new instance will create a new connection to the database, which is undesired for performance reasons.

这篇关于使用扩展类(PHP)时的最佳技巧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆