0

現在、次のように「ファットコントローラー」で入力を検証し、エラーを返しています。

class SomeController
{
    public function register()
    {
        // validate input
        $username = isset($_POST['username']) && strlen($_POST['username']) <= 20 ? $_POST['username'] : null;

        // proceed if validation passed
        if (isset($username)) {
            $user = $this->model->build('user');
            if ($user->insert($username)) {
                $_SESSION['success'] = 'User created!';
            } else {
                $_SESSION['error'] = 'Could not register user.';
            }
        } else {
            $_SESSION['failed']['username'] = 'Your username cannot be greater than 20 characters.';
        }

        // load appropriate view here
    }
}

class SomeModel
{
    public function insert($username)
    {
        // sql for insertion
        // ...

        return $result;
    }
}

これは機能し、実装するのは簡単ですが、次のように「ファット モデル」を使用して修正しようとしているモデルに検証が属しているため、これは正しくないことを理解しています。

class SomeController
{
    public function register()
    {
        $user = $this->model->build('user');
        $user->insert($_POST['username']);

        // load appropriate view here
        // ...
    }
}

class SomeModel
{
    public function insert($username)
    {
        // validate input
        $error = false;
        $username = trim($username) != '' && strlen($username) <= 20 ? $username : null;

        // proceed if validation passed
        if (isset($username)) {
            // sql for insertion
            // ...

            $_SESSION['success'] = 'User created!';
        } else {
            // store error in session
            $error = true;
            $_SESSION['error']['username'] = 'Your username cannot be greater than 20 characters ';
        }

        return $error ? false : true;
    }
}

ここで私が目にする問題は、モデルを変更する必要がないという点で、モデルが移植可能であると想定されていることです。しかし、長さの要件が$username変更された場合、明らかにモデルを変更する必要があります。

これは本当によくある質問だと思いますが、まだ簡単な答えを見つけていません。余分な「レイヤー」、「マッパー」、またはその他の紛らわしい用語を実装せずに、このトランザクションを正しく処理するために、提供されている擬似コードの例をどのように変更できますか? (例: 入力を検証し、検証が失敗した場合はエラーを返します)?

4

2 に答える 2

6

追加の「レイヤー」、「マッパー」などを実装せずに

「モデル」は、単一のクラスではなく、アプリケーションであると考える必要があります。「レイヤー」という用語は、MVC サンドイッチの M スライスを参照する簡単な方法と考えることができます。したがって、希望する柔軟性を実現するには、それを作成する必要があります。

いくつかの明確な分離を行うことができます。サービス、データ マッパー、エンティティの 3 つの抽象化を検討します。

サービスはコントローラーに公開され、要求されたサービスを実行します。

// some controller
function register() {
  $service = $this->getUserService();
  $user = $service->register($_POST['first_name'], $_POST['last_name']);
  if ($user instanceof \My\Entity\User) {
    // set user in view
  } else {
    // redirect to error
  }
}

タスク 1 が完了すると、コントローラーはレジスター内で何が起こっても理解できなくなります。コントローラーが知りたいのは、適切な結果を解決する方法だけです。ユーザー オブジェクトがある場合は成功、それ以外の場合は false 何か問題が発生しました。

サービス クラス自体は、提供されるサービスをカプセル化します。

// class UserService.php
function register($firstname, $lastname) {
  // validate arguments
  if ($this->isValidUsername(....
    $userMapper = $this->getUserMapper();
    $user = new My\Entity\User();
    $user->setFirstName($firstname);
    $user->setLastName($lastname);
    return $userMapper->save($user);
  }
  return false;
}

引数の検証を処理し、新しいユーザーを作成して、データベース操作を抽象化する「実際の保存」を実行するデータ マッパーに渡します。

// UserMapper
function save($user) {
  // save $user to db
  $sql = 'INSERT INTO ....

 return true;
}
于 2013-10-14T01:03:08.197 に答える
1

何を望ましくない「レイヤー」または「マッパー」と見なすのかわかりません。これは興味深い質問です。私の最初の質問は、ユーザー名の長さの定数を定義した構成ファイルを含めることができるということでした。2 つ目は、 someModel でクラスを拡張したり、インターフェイスを実装したりできることです。値はプロパティまたは定数として設定されます。あなたはこれらのことを考えていて、避けているのではないかと思います。これが、「レイヤー」と「マッパー」を避けることで意味することです。このコードでは、これらのプリンシパルに導かれているようです:

  • 「マジックナンバー」を避ける
  • 接吻
  • 継承より合成
  • スキニーコントローラー/ファットモデル

では、php5.4+ を実行していますか? アプリケーションでユーザー名の長さやその他の変更可能な値を定義する、このモデルや他のモデルで使用できる特性を定義することもできます。それとも、それも「レイヤー」の多くですか?

于 2013-10-14T00:22:55.103 に答える