我的应用程序使用了一些非常大且复杂的SQL查询。我不想在使用它们的类中使用它们,因为它们会混乱。所以我尝试了一些新功能:将它们存储在Queries
类中,并将我的应用程序使用的各种查询设置为该类中的const
变量。然后,在我的其他类中,我将查询称为Db::query(Queries::queryID, array($parameter))
。这会将查询的混乱存储在其他地方,并使工作类保持整洁。这也有助于减少重复,因为有多个类使用了一些查询。
示例:
abstract class Queries {
const queryID = <<<'SQL'
SELECT t.typeID, t.typeName, ROUND(greatest(0,sum(t.quantity)) * (1 + (b.wasteFactor / 100))) * ? AS quantity
FROM
(SELECT invTypes.typeid typeID, invTypes.typeName typeName, quantity
FROM invTypes, invTypeMaterials, invBlueprintTypes
WHERE invTypeMaterials.materialTypeID = invTypes.typeID AND
invBlueprintTypes.productTypeID = invTypeMaterials.typeID AND
invTypeMaterials.TypeID = ?
UNION
SELECT invTypes.typeid typeid, invTypes.typeName name, invTypeMaterials.quantity * r.quantity * - 1 quantity
FROM invTypes, invTypeMaterials, ramTypeRequirements r, invBlueprintTypes bt
WHERE invTypeMaterials.materialTypeID=invTypes.typeID AND
invTypeMaterials.TypeID =r.requiredTypeID AND
r.typeID = bt.blueprintTypeID AND
r.activityID = 1 AND
bt.productTypeID = ? AND
r.recycle = 1
) t
INNER JOIN invBlueprintTypes b ON (b.productTypeID = ?)
GROUP BY t.typeid, t.typeName
SQL;
...
}
这在大多数情况下运作良好,但我想知道其他人对于从工作类中分离查询的意见。有更好的方法吗?我是否对此进行了微观管理?
答案 0 :(得分:2)
我使用了几种方法。 一个是包含执行查询并返回结果的方法的类。
另一个是封装单个查询的类,它包含一个返回查询数据的Execute方法。后者的优点是,当您需要更多查询时,您没有失控的类。这是每个查询的一个类。这也允许您在同一个类中对数据进行额外的预处理。它就像是您的数据工厂。
如果你有一个合适的自动加载器,拥有一个查询类的文件夹很容易维护和使用。
按要求提供一个例子:
class Query_User {
function __construct($username)
{
$this->username = $username;
}
function execute() {
// A piece of pseudo code to execute the query:
$result = YourDatabase::Instance->QuerySingleObject(
"SELECT * FROM users WHERE username = :username",
array("username" => $this->username));
// Example post-processing of the data before it is returned.
$result->age = DateUtils::yearsBetween($result->birthdate, time());
return $result;
}
}
然后你就可以这样称呼它:
$user = new QueryUser('JohnDoe')->execute();
此方法的优点是类本身小而简单,只包含一个查询。但是它可以实现数据的附加修改,或者它可以执行几个查询并将结果合并为一个结果。
您还可以引入额外的功能,例如缓存一些使用频繁的查询的结果:
class Query_User {
function __construct($username)
{
$this->username = $username;
}
function execute() {
$key = get_class() . ',' . $this->username;
// Assuming there is some cache class to cache on disk or into MemCache.
$result = Cache::read($key);
if ($result === false)
{
$result = $this->performQuery();
Cache::write($key, $result);
}
return $result;
}
function performQuery() {
// A piece of pseudo code to execute the query:
$result = YourDatabase::Instance->QuerySingleObject(
"SELECT * FROM users WHERE username = :username",
array("username" => $this->username));
// Example post-processing of the data before it is returned.
$result->age = DateUtils::yearsBetween($result->birthdate, time());
return $result;
}
}
也许您甚至可以将缓存隔离到基类中,从而更容易在所有查询类中实现它。
我没有解释使用自动装载机,但这是一个常见的主题,并没有严格地与这个答案相关联。但是,它会让您的生活更轻松,因为您不必为要使用的每个查询类调用include
或require
。