1

今日から、コントローラーではなくモデルレイヤーでフォームデータの検証を開始しました。コードスニペットを可能な限り短くします。

これは私のUserドメインオブジェクトのメソッドです(setLastName()メソッドは基本的に同じです)

public function setFirstName($firstName) {

    if(!$firstName) throw new \InvalidArgumentException('Some message');
    if( strlen($firstName) < 2  || strlen($firstName) > 20 ) throw new \LengthException('Some message');
    if(preg_match('/[^a-zA-Z\'.-\s]/', $firstName)) throw new FormatException('Some message');

    $this->firstName = $firstName;
}

私のコントローラーにはこのようなものがあります

$userService = $this->serviceFactory->build('User');

try {
    $userService->register('John', 'M');
} 
catch(\InvalidArgumentException $ex) {

}
catch(\LengthException $ex) {

}
catch(etc etc)

私のUserService方法では、register()私は次のようなものを持っています

$user->setFirstName($firstName);
$user->setLastName($lastName);

メソッドを実行するsetFirstName()と、指定された名が正常に設定されます。短すぎるため、setLastName()メソッドはをスローします。LengthException

それが私が望んでいることですが、それがサービスレイヤーに戻り、次にコントローラーに戻って、それをキャッチすると、LengthExceptionがスローされたことがわかりますが、「指定された姓が短すぎました」などの適切なメッセージをユーザーに与えることができません。例外がスローされたフィールドがわからないため、例外のタイプだけです。

これを回避するにはどうすればよいですか?ありがとう。

4

3 に答える 3

1

ビュー インスタンスは、モデル レイヤーからの情報を要求する必要があります。コントローラーは、情報を渡す責任を負いません。

これはまた、抽象化レイヤーのリークを引き起こす強迫観念的な例外の使用が完全に無意味であることを意味します。「エラー」はあくまでモデル層の状態です。これは想定される状況であり、例外ではありません。

MVC のコントローラーは、モデル レイヤーの状態と (ごくまれに) 現在のビュー インスタンスの状態を変更する責任があります。サービスからのフィードバックを受け取るべきではありません。

于 2013-02-23T18:37:09.230 に答える
0

メッセージを返す代わりに、 「提供された名が短すぎます」などの有用なエラー メッセージを返さないでください。その後、これをユーザーに返すことができます。

または、例外を拡張するときに、数値コードなどの追加情報を指定できることがわかります。もちろん、これを使用することもできます。

もちろん、さまざまな状況に合わせて Exception のサブクラスを作成することもできますが、何百ものExceptionサブクラスができてしまい、もちろん面倒です。

于 2013-02-23T18:25:17.373 に答える
0

同じ質問があります。すべての検証をモデルで行うべきだと言う人のほとんどは、完全な PHP MVC アプリケーションを自分で開発したことがなく、本と理論しか知らないと思います。そのトピックに関するコードが見られることはありません。

とにかく、私は可能な解決策を考えました。以下のコードについてどう思いますか。

// Controller

$user = User::make(
    $_POST['lastname'], $_POST['firstname'], 
    $_POST['gender'], [...]
);
if(is_array($user)) {
    // store the errors in a view variable and forward, or store in session and redirect
    $_SESSION['errors'] = $user;
    $this->_redirect('add');
    exit;
}

// Model

public static make($lastname, $firstname, $gender, [...]) {
    $errors = array();
    if(/* test firstname */) $errors[] = 'model_error_firstname';
    if(/* test lastname */) $errors[] = 'model_error_lastname';
    if(!empty($errors)) return $errors;

    return new User($lastname, $firstname, $gender, [...]);
}

モデルには、何かがうまくいかなかった場合にエラーを含む配列を返すか、検証が問題なかった場合に新しいモデル オブジェクトを返す静的関数があります。

コントローラーで、配列が返されたかどうかをテストします。

コンストラクターを使用してユーザーを直接構築すると、すべての検証がスキップされるため、ユーザーのコンストラクターをプライベートとして配置する可能性があります。しかし、これはシングルトンになるという意味ではありません。

モデルに渡す前に、フォーム フィールドをサニタイズして安全にすることもできます。

model_error_xyz のようなキーは、適切なテキストを含む翻訳ファイルにあります。

アップデート:

実際には、コンストラクターからカスタム例外をスローするだけで、メッセージの配列が含まれていると思います。しかし、私がそれを提案しなかった理由は、少なくともたとえば Java では半分構築されたオブジェクトにつながるからですが、PHP は Java ではありません...

また、各セッター関数を検証する必要があります:(モデルインスタンスで検証を行うのは面倒です。

どんな考えでも大歓迎です。

于 2013-06-21T02:43:19.713 に答える