0

私のアプリケーションでは、非常に大規模で複雑な 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;

...

}

これはほとんどの場合うまく機能していますが、このようにクエリを労働者階級から分離することについて他の人の意見を知りたいと思いました。より良い方法はありますか?私はこれを細かく管理していますか?

4

1 に答える 1

2

いくつかの方法を使用しました。1 つは、クエリを実行して結果を返すメソッドを含むクラスです。

もう 1 つは、単一のクエリをカプセル化し、クエリされたデータを返す 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();

この方法の利点は、クラス自体が小さくて単純で、クエリが 1 つしかないことです。ただし、データの追加の変更を実装することも、いくつかのクエリを実行して結果を 1 つの結果に結合することもできます。

頻繁に使用されるクエリの結果をキャッシュするなど、追加の機能を導入することもできます。

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;
  }
}

おそらく、そのキャッシングを基本クラスに分離して、すべてのクエリ クラスに実装しやすくすることもできます。

自動ローダーの使用については説明していませんが、これは一般的なテーマであり、この回答に厳密にはリンクされていません。ただし、使用するすべてのクエリ クラスに対してincludeorを呼び出す必要がないため、作業が楽になります。require

于 2013-11-12T20:28:36.600 に答える