8

ここ数日、より良いプログラマーになれるように、PHP の OOP と MVC に関する書籍や Web ページを幅広く読みました。MVC の理解に少し問題がありました。

どこに置くのmysql_queryですか?

それをコントローラーに入れて、提供されたクエリに基づいてデータを返すモデルのメソッドを呼び出す必要がありますか? それとも、モデル自体に入れる必要がありますか?私が提供しているオプションは両方ともゴミですか?

4

5 に答える 5

15

MVCに関する資料

MVC に触れているほとんどの (すべてではないにしても) php の本は間違っているため、読んでいた本をリストすることもできます。

より優れた開発者になりたい場合は、Marting Fowler の記事 - GUI Architecturesから始めることをお勧めします。続いて同じ著者の本「エンタープライズ アプリケーション アーキテクチャのパターン」次のステップは、 SOLID の原則を研究し、デメテルの法則に従うコードの書き方を理解することです。これは基本をカバーする必要があります=]

PHP で MVC を使用できますか?

あまり。少なくともSmalltalk 用に定義された従来の MVC ではありません。

代わりに、PHP には、同じ目標を目指す 4 つのパターンがあります。MVC Model2、MVP、MVVM、および HMVC です。繰り返しになりますが、違いについてもう一度書くのが面倒なので、私の古いコメントにリンクします。

モデルとは?

最初に理解しなければならないことは、MVC のモデルはクラスでもオブジェクトでもないということです。多数のクラスを含むレイヤーです。基本的に、モデル レイヤーはすべてのレイヤーを組み合わせたものです (ただし、2 番目のレイヤーは「ドメイン モデル オブジェクト」を含むため、「ドメイン オブジェクト レイヤー」と呼ぶ必要があります)。モデル層の各部分に何が含まれているかについての簡単な要約を読みたい場合は、この古いコメントを読んでみてください(「補足」セクションにスキップしてください)。

                            モデルレイヤーは3つの同心円すべてで構成されています
この画像は、Fowler のサイトのService Layerの記事から引用したものです。

コントローラは何をしますか?

Controller は、MVC で 1 つの主要な役割を果たします (ここでは Model2 の実装について説明します)。

モデル レイヤー (サービスまたはドメイン オブジェクト) からの構造に対してコマンドを実行し、構造の状態を変更します。

通常、モデル層からビューに構造をバインド (または別の方法で渡す) という二次的な責任がありますが、SRPに従う場合、これは疑わしい慣行になります。

SQL 関連のコードはどこに置くのですか?

情報の保存と取得はデータ ソース レイヤーで処理され、通常はDataMapperとして実装されます(その名前を悪用する ORM と混同しないでください)。

これを単純化して使用すると、次のようになります。

$mapper = $this->mapperFactory->build(Model\Mappers\User::class);
$user = $this->entityFactory->build(Model\Entities\User::class);

$user->setId(42);
$mapper->fetch($user);

if ($user->isBanned() && $user->hasBannExpired()){
    $user->setStatus(Model\Mappers\User::STATUS_ACTIVE);
}

$mapper->store($user);

ご覧のように、ドメイン オブジェクトは、そこからの情報が保存されたことをまったく認識していません。また、データをどこに置くかについても問題ではありません。MySQL、PostgreSQL、または一部の noSQL データベースに保存できます。または、リモート REST API にプッシュされる可能性があります。あるいは、マッパーがテスト用のモックだったのかもしれません。マッパーを置き換えるために必要なことは、このメソッドに別のファクトリを提供することだけです。

また、次の関連記事もご覧ください。

于 2012-05-21T12:16:27.293 に答える
8

モデルクラスとエンティティクラスは、アプリケーションのデータとロジックを表します。これは多くの人がビジネスロジックと呼んでいます。通常、それは以下の責任があります:

  1. アプリケーションデータの保存、削除、更新。通常、データベース操作が含まれますが、外部WebサービスまたはAPIを呼び出す同じ操作を実装することはまったく珍しいことではありません。
  2. アプリケーションロジックのカプセル化。これは、アプリケーションのすべてのロジックを実装する必要があるレイヤーです

これは、httpリクエスト中のフローを示すMVCシーケンス図です。

ここに画像の説明を入力してください

この場合、モデルは、データベースにアクセスするために作成されたコードを実装するのに最適な場所です。

于 2012-05-20T17:38:17.450 に答える
2

mysql_query()1 つには、家族を使用しないでください。それらは非推奨になっているため、PDO や mysqli についても学習することを検討してください。

モデルがデータ処理を担当します。情報を取得および/または保存するためのコントローラーへのインターフェースを提供します。したがって、これはデータベース アクションが行われる主要な場所になります。

アップデート

コメントでOPから尋ねられた質問に答えるには:「データベース全体の1つの一般的なモデルですか、それともテーブル/アクションごとのモデルですか?」

モデルは、個々のテーブルを抽象化することを目的としています (ただし、単一のテーブルのみを処理するモデルもあります)。たとえば、すべての記事を要求してから著者のユーザー名をクエリする代わりに、次のような 1 つの関数を使用します。

function getArticles()
{
    // query article table and join with user table to get username
}

作成するモデルの数は、プロジェクトの規模とデータの相互関係によって大きく異なります。データの独立したグループを識別できる場合は、グループごとにモデルを作成する可能性があります。しかし、これは厳格なルールではありません。

読み取り専用モデルと書き込み専用モデルを明確に分離したい場合を除き、データ操作は同じモデルの一部にすることができます (これを保証する状況はわかりませんが、誰にもわかりません)。

于 2012-05-20T17:23:19.213 に答える
2

モデルには、アプリケーションの状態を表すドメイン オブジェクトまたはデータ構造が含まれています。[ウィキペディア] . したがって、モデルはデータベース呼び出しを行う場所になります。

「クラシック」(より適切な単語 atm がない) MVC パターンでは、ビューはモデルから現在の状態を取得します。

モデルはデータベースにアクセスするためのものであると誤解しないでください。データベースにアクセスするだけではありません。

于 2012-05-20T17:28:21.570 に答える
1

さらに、モデルにデータベース アクセス コードを含めないようにする必要があります。これは、モデル/ビュー/コントローラーの外部にある別のレイヤーに属します。これは永続レイヤーと呼ばれ、人気のあるPHP 用のDoctrine 2などのオブジェクト リレーショナル マッパーを使用して実装できます。

この方法では、(私の)SQL コードに触れることはありません。永続層がこれを処理します。Doctrine チュートリアルをご覧になることを強くお勧めします。これは、アプリケーションを作成するための本当に専門的な方法です。

データベースから読み込まれた生データを操作する代わりに、データを保持するオブジェクトとそれに関連付けられた動作を作成します。

たとえば、次のUserようなクラスがあるとします。

class User
{
    protected $id;
    protected $name;
    protected $privileges;

    public function setName($name) { ... }
    public function getName() { ... }

    public function addPrivilege(Privilege $privilege) { ... }
    public function getPrivileges() { ... }
}

コントローラーはオブジェクトとのみ対話します。

class UserController
{
    public function testAction()
    {
        // ...

        $user = $em->getRepository('User')->find(123); // load User with id 123
        $user->setName('John'); // work with your objects,
        echo $user->getName();  // and don't worry about the db!
        $em->flush(); // persist your changes
    }
}

舞台裏では、ORM がSELECTクエリの発行、オブジェクトのインスタンス化、オブジェクトへの変更の検出、必要なUPDATEステートメントの発行などの低レベルの作業をすべて処理します。

于 2012-05-20T17:52:16.707 に答える