【问题标题】:PHP: Parent Class and a Child ClassPHP:父类和子类
【发布时间】:2017-01-22 13:06:30
【问题描述】:

我正在尝试更多地了解 PHP 中的 OOP,所以我设置了一个简单的情况。

我有一个 MySQL 数据库,其中包含一个带有钱包的表。然后我做了以下课程:

class WalletConnection {

    private $db;
    private $user_id;
    private $wallets;

    public function __construct ($user_id) {

        $this->user_id = $user_id;
        $this->db = new PDO('mysql:host=localhost;dbname=ws;charset=utf8', 'dbuser', '***');
        $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

    }

    public function loadWallets () {

        $sql = $this->db->prepare('SELECT id, CurrencyCode, Balance FROM wallets WHERE UserID = :UserID');
        $sql->execute([':UserID' => $this->user_id]);
        $this->wallets = $sql->fetchAll(PDO::FETCH_ASSOC);

    }

    public function getWallet ($num) {

        // do something like: new Wallet($this->wallets[$num])

    }

}

然后我像这样创建钱包连接:

$wallets = new WalletConnection(40); // 40 = UserID of wallet owner
$wallets->loadWallets();

现在我想创建一个子类 Wallet 来处理个人钱包。

class Wallet extends WalletConnection {

    private $id, $balance, $currency_code;

    public function __construct($data) {
        $this->id = $data['id'];
        $this->balance = $data['Balance'];
        $this->currency_code = $data['CurrencyCode'];
    }

    public function getBalance() {
    }

}

要了解有关 OOP 的更多信息,我想构建这个:

$wallet = $wallets->getWallet(0); // This will now contain the id, CurrencyCode, Balance of the first wallet of the parent's $wallets.

所以我想我需要在 WalletConnection 类中添加一个 getWallet() 函数并从那里调用“new Wallet”。

然后在我想做的客户端代码中:

$wallet->getBalance()

目前我不知道我这样做是否正确,如果我需要知道下一步该做什么以确保例如 getBalance() 函数可以使用父级的 $db 连接.

【问题讨论】:

  • 当然,在getWallet() 方法中通过new Wallet 实例化一个新钱包确实有意义。然后,您将该钱包返回到外部范围。正好。但是,您想将该对象“缓存”在 $wallets 对象中,以防它被第二次调用。在这种情况下,您确实想创建第二个对象,我想。您可以为此在 WalletConnection 类中定义一个属性。如果它已经为特定索引保存了一个对象,则返回该对象,否则实例化、缓存并返回一个新对象。
  • 好的,但是当我从 getBalance() 调用函数以在 Parent 中运行 sqlQuery 时,$this 变成了“孩子的”$this,因此 $this->db 变得不可用。我不想为每个钱包创建新的连接。
  • 好吧,您可以通过构造函数将数据库对象“注入”到钱包对象中,或者更优雅地,您可以在钱包中存储对 WalletCollection 的反向引用,这样您就可以使用它钱包对象内的对象数据库连接。
  • 我用一个简单的(非数据库)示例尝试了最后一部分。我在 WalletConnection 中添加了:protected function getUserID () { return $this->user_id; } -- 现在,如果我从钱包(子)调用 $this->getUserID(),那么它是空的,因为父级的 getUserID() 中的 $this 现在是子级的 $this() 而不是父级的。
  • 哇,对不起,我没注意。您的问题是您实际上从 WalletConnection 类派生了 Wallet 类,这实际上没有意义。 WalletConnection 实现了一组东西,但钱包实现了其中一个特定的东西。因此它们描述了完全不同的语义含义。那么为什么要从WalletConnection 扩展Wallet

标签: php mysql oop


【解决方案1】:

如果您想了解有关 OOP 的更多信息,请先了解它的原理。 http://codebetter.com/raymondlewallen/2005/07/19/4-major-principles-of-object-oriented-programming/

您应该深入了解 封装 原则,因为您在这里通过在数据库和钱包之间建立依赖关系违反了它。

更好的做法是将钱包作为模型,以及负责与之相关功能的服务(例如 getWalletById)。

您需要一个知道如何从数据库(通常是数组)中获取信息并将其映射到钱包模型的映射器。

您还想使用可以连接到数据库的适配器,而不仅仅是使用钱包。

请记住,扩展并不总是解决方案,有时您应该使用组合而不是继承。

例如,服务包含映射器,映射器包含适配器。

总结一下,试试这样的:

  1. 创建一个钱包模型。创建钱包服务。创建钱包 映射器。创建 PDO 适配器。
  2. 使用 PDO 适配器获取原始 SQL 钱包数据
  3. 将数组映射到正确的钱包模型并通过映射器返回
  4. 通过服务返回钱包模型。

最后你应该有一行代码:

$wallet = $walletService->getWalletById($id);

您应该能够通过公开或通过 getter 来使用它的属性:

$balance = $wallet->balace;

$balance = $wallat->getBalance();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    相关资源
    最近更新 更多