php - 用于包装数据库行子类的 OOP 方法

标签 php oop orm subclass

假设我想将狗存储在数据库表中,每只狗在 PHP 中都有自己的子类。

基本上我想避免在代码中的不同位置存储/列出子类名称。对此,什么是好的 OOP 方法?

abstract class Dog {
    protected $data;
    public function __construct($data) {
        $this->data = $data;
    }
    public function name() {
        return $this->data["name"];
    }
    abstract public function breed();
}

class GermanShepherd extends Dog {
    public function breed() {
        return _("German Shepherd");
    }
}

class BullDog extends Dog {
    public function breed() {
        return _("Bulldog");
    }
}

现在我有这个类来处理对象组(即狗):

class Dogs {
    public static function getDogs() {
        // ...
        $ret = array();
        while ($row = mysql_fetch_assoc()) {
            switch ($row["type"]) { // I could do this using a lookup array
                 case "shepherd": $dog = "GermanShepherd"; break;
                 case "bulldog": $dog = "Bulldog"; break;
            }
            $ret[] = new $dog($row);
        }
        return $ret;
    }
}

我想使用这个类来获取我 View 中的狗类型(特别是对于添加狗表单),而不是列出类名:

?><form><select name="type"><?php
foreach (array("GermanShepherd", "Bulldog") as $dog) { // here I would like to do avoid listing the class names again
    ?><option value="<?=$dog ?>"><?php
    $d = new $dog; // actually I can't instantiate the class here because I don't have any data at this point
    echo $d->name();
    ?></option><?php
}
?></select></form><?php

我想将其合并到 Dogs 类中,大致如下:

class Dogs {
    private static $dogs = array(
        "shepherd" => "GermanShepherd",
        "bulldog" => "Bulldog",
    );
    public static function getDogs() {
        // ...
        $ret = array();
        while ($row = mysql_fetch_assoc()) {
            $dog = self::$dogs[$row["type"]];
            $ret[] = new $dog($row);
        }
        return $ret;
    }

    public static function getDogTypes() {
        return array_values(self::$dogs);
    }
}

?><form><select name="type"><?php
foreach (Dogs::getDogTypes() as $dog) {
    ?><option value="<?=$dog ?>"><?php
    $d = new $dog; // here I still need to instantiate the class and I don't have any data to provide it with
    echo $d->name();
    ?></option><?php
}
?></select></form><?php

到目前为止,这在某种程度上是可行的,但是如果我需要更多类别特定信息,例如当我有更多特定于狗类型的字段时,该怎么办?

foreach (Dogs::getDogTypes() as $dog) {
    $d = new $dog; // instantiate again?
    foreach ($d->formFields() as $f) { // I wouldn't do it like this, just putting this here for demonstrative purposes
        echo $f;
    }
}

我认为部分问题在于我需要能够在有或没有数据库数据的情况下使用我的类:当我从数据库表中获取数据时,一切看起来都非常合理,但当我从数据库表中获取数据时,我也需要这些数据我在创建新狗时生成表单。

感谢您的想法!

最佳答案

首先使用Interfaces 。这将向您表明,拥有更具体的接口(interface)(每个子类不同的类方法和属性)将使您需要以不同的方式具体处理它们。因此,它们将向您展示缺陷所在,并使您能够将对象简化为更可重用的东西。

只要您的对象仅存储一些数据,请使用 data transfer object相反 - 它是任何“类型”。所以你不需要处理类型。但是,如果您想保持基本,您也可以使用 StdClassArray 来实现这一点。优点是:您不需要实际编写那么多代码。

如果它还不够(将来也会如此),请仅在需要时添加代码。从长远来看应该让事情变得更简单。因此,从基本的数据传输对象类开始,并在其基础上进行构建。

因此,使用您编写的类来分离关注点,而不是交织关注点。封装变化的部分,以便您的代码实际上可以从您的设计中受益。

关于php - 用于包装数据库行子类的 OOP 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7146594/

相关文章:

oop - 编译器如何编译虚拟/重写方法

java - 如何解决 `Raw use of parameterized class ' Comparable'` 警告?

mysql - 得到 .findOrCreate() 错误

php - laravel Eloquent 查询关系

c# - SQL 和 Dapper 性能隐式转换

php - MAMP:PHP 文件中的 HTTP 错误 500

PHP foreach 和引用资料

php - 反射异常 : Class ClassName does not exist - Laravel

php - 单击时发送 AJAX,但仍转到 href 的 URL

node.js - 如何让值对象远离服务器?