web-dev-qa-db-ja.com

MVCでのPDOの使用

私はこの質問をstackoverflowで質問し、応答がありませんでした(回答なしで重複として閉じられました)。私はOOPで実験しています、そして私は以下の基本的なMVCレイアウトを持っています:

class Model {
    // do database stuff
}

class View {
    public function load($filename, $data = array()) {
        if(!empty($data)) {
            extract($data);
        }

        require_once('views/header.php');
        require_once("views/$filename");
        require_once('views/footer.php');
    }
}

class Controller {
    public $model;
    public $view;

    function __construct() {
        $this->model = new Model();
        $this->view = new View();

        // determine what page we're on
        $page = isset($_GET['view']) ? $_GET['view'] : 'home';
        $this->display($page);
    }

    public function display($page) {
        switch($page) {
            case 'home':
                $this->view->load('home.php');
            break;
        }
    }
}

これらのクラスは私のセットアップファイルにまとめられています。

// start session
session_start();

require_once('Model.php');
require_once('View.php');
require_once('Controller.php');

new Controller();

ここで、データベース接続コードをどこに配置し、接続をモデルに渡すにはどうすればよいですか?

try {
    $db = new PDO('mysql:Host='.DB_Host.';dbname='.DB_DATABASE.'', DB_USERNAME, DB_PASSWORD);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $err) {
    die($err->getMessage());
}

Dependency Injection、ファクトリー、その他のさまざまな設計パターンについて、SQLをモデルから除外することについて説明しましたが、抽象的な例を使用して頭の中で説明しました。誰かが私に単純明快な実用的な例を見せていただけますか?

3
mister martin

Falconが述べたように、データアクセスコードはControllerにある必要があります。少なくとも、サービスレイヤーまたはデータアクセスレイヤーへの唯一のアクセスはControllerから行われる必要があります。 Modelは主に、ビューに表示するデータを構造化するために使用されます。つまり、ドメインモデルを模倣する必要があります。通常、データベースからデータをクエリし、データを使用してModelを作成し、ModelViewにロードします。すべてController内にあります(一般的に、実装は異なる場合があります)。

あなたの例では、それはこのように見えるかもしれません(ここでも、単なる概要の例です)、

class Model {
    // domain model properties: id, name, age... 
}

class View {
    // view stuff        
}

class Repository {
    function __construct() {
       // connect to database and return a viable connection for data access
    }
}

class Controller {
    public $model;
    public $view;
    public $repository   

    function __construct() { 
        $this->repository = new Repository();       

        $this->model = new Model();
        $this->model = $this->repository.LoadModelFromDatabase();

        // load your model onto the view
        $this->view = new View($this->model);

        // determine what page we're on
        $page = isset($_GET['view']) ? $_GET['view'] : 'home';

        // display your view with your model loaded
        $this->display($page);
     }

     public function display($page) {
         switch($page) {
             case 'home':
                 $this->view->load('home.php');
             break;
     }
}

他のViewsおよびModelsについても同様のパターンに従い、Controllerを使用してデータベースへのアクセスとプログラムとの相互作用を調整する必要があります。

3
rae1

それはすべて、コードにどの程度の設計と抽象化を加えたいかに依存します。物事を比較的シンプルに保ち、柔軟性を持たせて、頭痛やコードの記述をそれほど必要としない場合、コードは問題ありません。データベースアクセスを専用オブジェクトに配置します。専用オブジェクトは、DBのデータをプルし、Modelオブジェクトを構築します(これはファクトリーです)。次に、コントローラーメソッド内でそのファクトリをクエリし、正しいモデルインスタンスを取得してビューに入力します。モデル自体は、それがどこから来ているのかを本当に知る必要はないので、ファクトリは代わりにファイルベースのストレージから自由に構築できます。ファクトリに必要なのは、いくつかのパラメータのみです($_GETコード内の関連フィールド)、どのデータをフェッチする必要があるかを把握します。

class ModelFactory {
    private $dbhandle;
    function __construct(){
          // open db etc...
    }
   function loadModel($params){
         // run db queries and construct/fill up the Model instance
   }
   function saveModel($model){
        // pull out model fields to fill the insert/update query
   }
   // etc...you get the idea
}

次に、ドメインオブジェクトがデータベース行の直接転置である基本モデルレイヤーがある場合、これはほとんどの場合ActiveRecordパターンを直接使用する場合であり、エンドユーザーに実行させるだけでよい [〜#〜 ] crud [〜#〜] 演算を実行し、それを実行します。そのパターンからインスピレーションを得て、その上にORMを構築すると、基本的なマスター/詳細、1対多、多対多の関係が処理されます。それは正しい方向への最初のステップです(これがCakePHPまたはコードイグナイターの初期バージョンを見て、これがどのように機能するかを理解することができます)が、正しい方法(TM)で実行したい場合は、 MVCははるかに複雑になる可能性があることを確認してください。

MVCアーキテクチャは実際にはそれよりも抽象的です。モデルパーツは、アプリケーションの「レイヤー」であり、非常に広い意味で、さまざまなservicesのセットで構成されます。これにより、基本的には「より高いレベル」の機能を実現できます(たとえば、さまざまな場所からデータをプルする必要があるが、これらの詳細がコントローラーレベルに漏出してはならない認証を考えてください)。これは、異なるリクエストで使用できますドメインオブジェクト(ユーザーのように)、次にデータマッパー(ActiveRecordパターンのように)。

SO this one のように、そのトピックに関する詳細な記事を掲載しています。

0
didierc