5

PDO クエリについて別の質問をしているときに、PDO 接続オブジェクトをグローバルとして保存して、データベースへのクエリを呼び出すさまざまな関数で使用することは一般的に悪い習慣であると言われました。

PDO オブジェクトの一般的な使用方法は次のとおりです。

function somefunction(){
    global $pdo;

    $statement = $pdo->prepare("some query");
    $statement->execute();
}

私が読んだ議論は、コードのメンテナンスとデバッグに関するもので、誰が PDO オブジェクトを変更したのか、コード内のどこで変更したのかを追跡するのは困難です。他の人々は、PDO オブジェクトを格納するためにグローバル変数を使用することを単純に拒否しますが、なぜグローバル変数が悪いアプローチなのかを実際に説明することはできません。

しかし、データベースが 1 つしかない中小規模のプロジェクトの場合、グローバル変数を使用することのデメリットは本当にあるのでしょうか? 私は通常、接続スクリプトと関数スクリプトを別々に用意します。関数スクリプトは、PDO オブジェクトが作成される接続スクリプトを require_once() します。このようにして、接続は常に確立され、PDO オブジェクトへのすべての変更は接続スクリプトで行われます。

このアプローチの使用に根本的な欠陥はありますか?

4

2 に答える 2

12

このアプローチの使用に根本的な欠陥はありますか?

最初に理解しなければならないことは、それがストレージロジック$pdoの一部であるということです。つまり、SQL テーブルであれコレクションであれ、抽象データ アクセスを行うクラス内でのみ使用する必要があります。

コードを見てみましょう。

function somefunction(){
    global $pdo;

    $statement = $pdo->prepare("some query");
    $statement->execute();
}

将来、MySQL から Mongo/MSSQL/PgSQL に切り替えたい場合はどうしますか? 次に、多くのコードを書き直す必要があります。

また、データベース ベンダーごとに、異なる変数を使用して個別のファイルを作成する必要があります。ちょうどこのような

function somefunction(){
    global $mongo;
    return $mongo->fetch(...);
}

グローバル状態を使用すると、パラメーターを渡すことができず、実行時に関数の動作を変更できないため、大量のコードの重複が発生します。

では、これを見てみましょう。

function somefunction($pdo){
    $statement = $pdo->prepare("some query");
    $statement->execute();
}

ここで$pdoは、引数として渡されるため、グローバルな状態はありません。しかし、問題は残ります。単一責任の原則に違反することになります。

保守可能で、クリーンで、非常に読みやすいものが本当に必要な場合は、DataMappersを使用することをお勧めします。これが例です。

$pdo = new PDO(...);

$mapper = new MySQL_DataMapper($pdo);
$stuff = $mapper->fetchUserById($_SESSION['id'])    

var_dump($stuff); // Array(...)

// The class itself, it should look like this
class MySQL_DataMapper
{
    private $table = 'some_table';

    private $pdo;

    public function __construct($pdo)
    {
        $this->pdo = $pdo;
    }

    public function fetchUserById($id)
    {
        $query = "SELECT * FROM `{$this->table}` WHERE `id` =:id";
        $stmt = $this->pdo->prepare($query);

        $stmt->execute(array(
           ':id' => $id
        ));

        return $stmt->fetch();
    }
}

結論

  • プロジェクトが小さいか大きいかは問題ではありません。すべての形式 (グローバル変数、静的クラス、シングルトン) で常にグローバル状態を避ける必要があります -コードの保守性のために

  • $pdoこれはビジネス ロジックの一部ではないことを覚えておく必要があります。ストレージロジックの一部です。つまり、重い計算など、ビジネス ロジックで何かを開始する前に、テーブル アクセス (CRUD 操作を含む) を実際に抽象化する必要があります。

  • data access abstractionあなたとあなたをつなぐ架け橋computation logicは通常サービスと呼ばれます

  • 常に関数の必要性をパラメータとして渡す必要があります

  • コードについて心配するのをやめて、抽象化レイヤーについて考え始めたほうがよいでしょう。

  • 最後に、何らかの処理を開始する前に、まずすべてのサービスを初期化し、ユーザーの入力 (または)bootstrap.phpに従ってストレージのクエリを開始します。$_POST$_GET

と同じように、

public function indexAction()
{
    $id = $_POST['id']; // That could be $this->request->getPost('id')
    $result = $this->dataMapper->fetchById($id);

    return print_r($result, true);
}
于 2013-10-13T03:49:18.797 に答える