使用类开始关于类的OOP问题

时间:2011-07-16 05:54:46

标签: php oop class

我正在尝试用一组很好的课程来替换一个程序化的网站作为学习练习。

到目前为止,我已经创建了一个基本上在数据库主表中保留一行的记录类。

我还创建了一个loader类,它可以:

loadAllFromUser($username)
loadAllFromDate($date)
loadAllFromGame($game)

这些方法从数据库中获取所有有效行,将每行打包成一个记录,并将所有记录粘贴到一个数组中。

但是,如果我只想使用一个记录呢?我对此进行了一次尝试,最后得到的代码几乎与我的程序原件相同。

我也不确定那条记录会去哪里。我的loader类是否有受保护的记录属性?

我有点困惑。

编辑 - 同样,我会在哪里放置类似HTML模板的内容来输出网站的记录?这是记录类,加载器还是第三类?

4 个答案:

答案 0 :(得分:2)

您可以在实用程序方法中封装loadAllFrom...loadOneFrom...的唯一部分:

private function loadAll($tableName) {
    // fetch all records from tableName
}

private function loadOne($tableName) {
    // fetch one record from tableName
}

然后你不会看到这么多的重复:

public function loadAllFromUser() {
    return $this->loadAll("user");
}

public function loadOneFromUser() {
    return $this->loadOne("user");
}

如果您愿意,可以进一步细分:

private function load($tableName, $all = true) {
    // return all or one record from tableName
    // default is all
}

然后,您可以使用以下调用替换所有这些方法:

$allUsers = $loader->load("users");
$date = $loader->load("date", false);

答案 1 :(得分:2)

我建议使用像Doctrine之类的东西来抽象你的数据库到对象的东西,而不是用于学习目的。

也就是说,有很多方法可以对这种类型的东西进行建模,但总的来说,处理它的图书馆(本土或未成熟的)似乎倾向于在高层次上进行:

  • 表示映射到db
  • 的对象的类
  • 表示该对象映射到db
  • 的方式的类
  • 表示从db
  • 检索对象的方法的类

考虑需要完成的不同任务,并尝试将它们干净地封装起来。 The Law of Demeter对于记住是有用的,但是不要因为试图在面向对象的设计理论中弄清楚这一切而陷入困境 - 思考,设计,编码和思考它会更有用。看看你的设计中的弱点在哪里。

对于“使用一条记录工作,但没有复制一堆代码”的问题,或许类似于使用loadAllFromUser方法实际上是调用私有方法的方法,该方法采用(例如)一个参数要检索的记录数,如果该参数为null,则检索所有记录。

您可以更进一步,并在loader课程上实施__call。假设它可以知道或找出你想要加载的字段,你可以构造一个以编程方式进行加载的函数的参数 - 查看函数的公共部分,看看有什么不同,看看你能不能找到一种方法将这些不同的部分组成功能参数,或者其他可以避免重复的东西。

MVC值得您阅读第二个问题。至少,我可能希望将它放在一个单独的类中,该类期望传递一个记录来呈现。记录可能不应该关心它是如何在html中表示的,使得记录标记的事情不应该关心记录的获取方式。一般来说,您可能希望尝试尽可能独立。

习惯这不是一件容易的事,而且大多数在这种设计中“变好”都是一种练习。对于实际的功能,测试可以提供很多帮助 - 比如说你正在编写你的加载器类,而且你知道如果你调用loadAllFromUser($me),你应该得到一个包含数据集的三个特定记录的数组(即使它是一个数据集仅用于测试),如果你有一些你可以运行的东西会在你的加载器上调用它并检查正确的结果,它可以帮助你知道你的代码至少是从行为的角度来看,如果不是从设计 - 当您更改设计时,您可以确保它仍然正常运行。 PHPUnit似乎是php-land中最受欢迎的工具。

希望这可以指出一组有用的方向,而不仅仅是让人困惑:)祝你好运,并且速度快。

答案 2 :(得分:1)

您可以检查进入方法的参数并从那里决定。

    $args = func_get_args();
    if(count($args) > 1)
    {
        //do something
    }
    else // do something else

这可能有用。或者你可以在你的类中创建两个单独的方法来处理每种类型的请求,就像@ karim的例子一样。无论哪种方法最适合您想做的事情。

希望我明白你在问什么。

回答您的修改:

通常,您需要创建一个视图类。这将负责处理数据的HTML输出。保持这些分开是一种好习惯。最好的方法是将“数据类”对象直接注入视图类,如:

class HTMLview
{
    private $data;

    public function __construct(Loader $_data)
    {
        $this->data = $_data;
    }
}

然后继续输出,此类保存已处理的数据库信息。

答案 3 :(得分:0)

完全有可能并且合理的是,您的记录类可以附加一个知道如何加载单个记录的实用程序方法,前提是您提供了一条识别信息(例如其ID)。 / p>

我一直在使用的模式是一个对象可以知道如何加载自己,并提供静态方法来执行“loadAll”操作,将这些对象的数组返回给调用代码。

所以,我自己也经历了一个我开发的小型开源网络应用程序,我在程序上写了大部分内容,因为这是我知道如何工作(嘿,是的)应用程序在最短的时间内完成 - 现在我将重新开始并实施繁重的OOP和MVC架构。