在一个特定的应用程序上工作,我一次又一次地写着非常相似的查询。它们不完全相同,但形式非常相似,并且嵌入在几乎相同的代码块中,例如,
$Mysqli = new mysqli;
if ($Stmt = $Mysqli->prepare("SELECT foo
FROM tblFoo
WHERE something = ?")) {
$Stmt->bind_param('s', $this->_something);
$Stmt->execute();
if (0 != $Stmt->errno)
throw new Exception("blah, blah, blah");
$Stmt->bind_result($foo);
while ($Stmt->fetch()){
$this->_foos[] = new Foo($foo);
}
$Stmt->close();
} else {
throw new Exception("blah, blah, blah"););
}
}
以后,其他地方......
$Mysqli = new mysqli;
if ($Stmt = $Mysqli->prepare("SELECT bar, baz
FROM tblBar
WHERE somethingElse = ?")) {
$Stmt->bind_param('s', $this->_somethingElse);
$Stmt->execute();
if (0 != $Stmt->errno)
throw new Exception("blah, blah, blah");
$Stmt->bind_result($bar, $baz);
while ($Stmt->fetch()){
// do something else with $bar and $baz
}
$Stmt->close();
} else {
throw new Exception("blah, blah, blah"););
}
}
......然后另一个,以及其他地方......等等。
这是否真的违反DRY?编写一个用于执行此类查询的类(使用构造函数params或setter for table,column,bound变量等)然后在我的应用程序中重用它似乎没有意义。但与此同时,我无法摆脱这种唠叨的感觉,即我在重复自己。
也许只是因为只有很多方法可以编写一个简单的查询,并且可以预期会有一定程度的重复。
思想?
答案 0 :(得分:1)
很多人都是这样做的。创建一个表示每个表的类,它们都从同一个类继承。基类可以处理加载和保存数据。因此,如果要加载数据,只需调用load方法即可。您可以通过对象的属性设置和访问字段值。
还有像hibernate这样的库可以为你处理很多肮脏的工作。
答案 1 :(得分:1)
我会说这是违规行为。从一瞥您的代码(除非我遗漏了一些东西),这两个语句是相同的,除了字符串“foo”和“bar”(重复几次)和您的实际业务逻辑。
至少你可以提取它。更重要的是,应该提取所有SQL字符串。对我来说,他们似乎总是比代码更像数据。如果你有一个SQL字符串,表格等数组 - 会使重构更明显吗?
(从代码中提取字符串和其他数据是开始重构的好方法)
一种可能性,如果你有一个具有表名的对象和一个包含你的业务逻辑的方法,你可以将它传递给一个带有所有样板的“处理器”(这是你所拥有的所有其余代码)
我认为这可能会让它变干。
(PS。总是喜欢组合而不是继承。对可以“运行”对象的类使用继承没有任何好处。
答案 2 :(得分:0)
你遇到了第一个模块化的愿望之一。 : - )
有两种通用解决方案。第一种是将调用抽象为所有(或大多数)类似查询。然后再次进行另一组查询。然后到另一个。等等。不幸的是,这会导致许多块执行相同的操作:调用查询,检查问题,组合结果集,将其传回。这是一个DAL,但只有一种。它也没有扩展。
第二种解决方案是抽象查询和返回结果的过程,然后查看抽象的数据访问(这基本上意味着你构建了一些组装SQL的东西)。这更有可能成为一个合适的ORM而不是简单的DAL。扩大规模要容易得多。