【问题标题】:Writing adaptive PHP methods?编写自适应 PHP 方法?
【发布时间】:2013-03-09 15:14:31
【问题描述】:

假设我有一个名为 Books 的课程。在该类中,我有一个方法可以获取一本书或几本书的标题、价格和类别。所以是这样的:

public function fetchRows () {
  $sql = $con->prepare("SELECT Title, Price, Category FROM Books");
  $sql->execute();
  return $sql->fetchAll();
}

一切都很好,但是假设我现在想获取另一行,order 结果和limit 返回的行数。为此编写另一种方法会起作用,但这会导致方法数量荒谬,而且这很混乱并且不符合 DRY 规则。我可以使用参数来自定义准备语句,然后我可能最终会在一个参数中编写整个查询,而且这似乎也不可靠和干净。

我的问题是如何编写/构造方法/类以适应最终用户想要获得的内容?

很抱歉,这真的不是针对特定问题的问题。我已经阅读了一些关于我的问题的材料,但是我很难将这种模式缠绕在我的脑海中,我希望有人可以提供一个解释或示例来帮助我理解这一点。

【问题讨论】:

  • 是的,很多时候你会有一个单独的抽象来处理数据库交互。所以完全是另一个类,然后您可以将所有参数传递给它,并使用类似 API 的简单接口处理所有数据库请求。

标签: php class design-patterns methods


【解决方案1】:

您是否考虑过使用位于数据库顶部的 ORM(对象关系映射器)?我强烈推荐 Doctrine 2 http://www.doctrine-project.org 。这样,您可以将数据库表中的行视为对象:所有数据库交互都被抽象出来(如果需要,您仍然可以直接运行 SQL 查询)。

如果您不熟悉 ORM 的概念,Doctrine 可以让您编写如下代码:

$user = new User();
$user->username = 'test';
$user->email = 'test@example.com';
$entityManager->persist($user);
$entityManager->flush();

您只是运行了INSERT INTO user (username, email) VALUES ('test', 'test@example.com');,而没有编写任何 SQL。

类似地,用户可以按如下方式检索:

$user = $entityManager->getRepository('User')->findOneByUsername('test')

$user = $entityManager->getRepository('User')->findOneByEmail('test@example.com')

这些查找器方法是根据用户表上存在的字段自动为您生成的,可帮助您保持代码 DRY。

【讨论】:

  • 拒绝投票者:想解释一下原因吗?我觉得这回答了这个问题。
  • 我没有告诉你,但我认为问题是你建议添加查找器方法,而 OP 担心添加它们(参见“这会导致大量的方法”) .可能对 OP 有所帮助的是展示如何使用从用户输入组装的 DQL 和 Criteria 对象。
  • Finder 方法由 Doctrine 自动生成:不需要用户编写。
  • 不是每个人都知道这一点,所以你可能想添加它。
【解决方案2】:

适应最终用户想要得到的东西?

你在这里进入了摇摇欲坠的地方。您可能希望最终用户允许她访问数据库层,以便她可以准备查询。

否则,您将开始重新发明轮子。老实说,我怀疑你真的有那么多函数和那么多参数。

所以这在很大程度上取决于您的最终用户。如果最终用户想做很多事情,请以源代码形式提供软件,以便最终用户可以根据需要修改软件。

在此之前,发布您的软件并从最终用户那里获得真正需要哪些功能的反馈。

对于您的应用程序来说,ORM 可能只是一种无用的开销,但您只需要在 PDO 之上增加一些功能,例如延迟查询和稍后重命名列名的功能。

$result = PDOQuery::create('* FROM config')->limit(2);

$result->orderBy('`option`');

$result->aliasNames(['option' => 'name'], $removeOther = true);    

foreach ($result as $row) {
    print_r($row);
}

这只是示例,代码只会将行提供为关联数组:

Array
(
    [name] => Insert Option 50e60ca17bdf4
)
Array
(
    [name] => Insert Option A 50e78a79ead49
)

仅在涉及到 foreach 时执行(例如,您可以将其传递到视图中,如果视图不需要它,则永远不会执行数据库查询)。

您可以进一步扩展它,例如定义查询的所有内容都将成为您可以传递的查询定义。

您可以使迭代器成为堆叠迭代器,这样如果查询已执行,您可以对结果应用限制,而不是再次运行查询。还有什么。

这实际上只是根据您的需要增强 PDO 的接口,因此您需要自己编写该组件。

它也应该比上面示例代码中描述的更解耦。

【讨论】:

    猜你喜欢
    • 2012-10-08
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    相关资源
    最近更新 更多