11

技術的には可能ですが、これにより MVC アーキテクチャが壊れますか?

このタイプの通信がコントローラーとモデルの両方で推奨されるかどうかはわかりません。簡単な例と2つの方法を使用して説明します。

オプション 1 (モデルが例外をスローし、コントローラーがそれをキャッチする):

class Controller {
  private $model;

  public function save($data) {
     try {
         $this->model->save($data); 
     } catch (Exception $e) {  
         // handle exception
     }
  }
}

class Model {
  public function save($data) {
     // Call to internal function to save data in BD
     if (! $this->_save($data)) throw new Exception('Error saving data');
  }
}

オプション 2 (コントローラーは例外を完全に処理します):

class Controller {
  private $model;

  public function save($data) {
     try {
         if (! $this->model->save($data)) throw new Exception('Error saving data'); 
     } catch (Exception $e) { 
         // handle exception
     }
  }
}

class Model {
  public function save($data) {
     // Call to internal function to save data in BD
     if (! $this->_save($data)) return false;
  }
}

**

いくつかの応答後に編集:

**

これらは、あなたの提案に基づいて解決する他の方法です。物事が複雑になりすぎないように願っています。

オプション 3 (Ray が言ったように、モデルは例外を完全に処理します。KingCrunch もモデルでそれを行うことを提案しました)

class Controller {
  private $model;

  public function save($data) {

     if (! $this->model->save($data)) {
         // possible action: redirect to the form with an error message
     }

  }
}

class Model {
  public function save($data) {
     try {
         if (! $this->_save($data)) throw new Exception('Error saving data'); 
     } catch (Exception $e) { 
         // handle exception
         return false;
     }
     return true; 
  }
}

オプション 4 (shiplu.mokadd.im が言ったように、コントローラーはモデルによってスローされたカスタムの子例外を取得します。)

class Controller {
  private $model;

  public function save($data) {
     try {
         $this->model->save($data); 
     } catch (Exception $e) {  
         if ($e instanceof ValidationException) {
            // handle validation error
         }
         elseif ($e instanceof DBStorageException) {
            // handle DB error
         }
     }
  }
}

class Model {
  public function save($data) {
     if (! $this->_validate($data)) {
        throw new ValidationException ('Validation error');
     }
     if (! $this->_save($data)) {
        throw new DBStorageException ('Storage error');
     }
  }
}
4

3 に答える 3

9

モデルは例外をスローでき、コントローラーまたはビューはそれをキャッチする必要があります。そうしないと、すべてが適切に機能しているかどうかわかりません。したがって、最初のオプションを使用してください。ただし、コントローラーと View にとって意味のある適切に抽象化された Exception をスローしていることを確認してください

上記の太字の行を説明するには、モデル内で使用される次の 2 つの throw ステートメントを参照してください。

 throw new Exception('SQL Error: '.$mysqli->error()); // dont use it
 throw new DuplicateFieldException('Duplicate username'); // use this

2 番目の例は、内部エラーを示していません。むしろ隠している。コントローラーは、内部で何が起こっているかを知ることはできません。

コードでは、単一のモデルを単一のコントローラーに結び付けました。コントローラは単一のモデルを表していません。モデルを使用しています。また、モデルはいくつでも使用できます。したがって、単一のモデルを のような変数を持つコントローラーと結び付けないでprivate $modelください。

于 2013-01-08T22:21:47.177 に答える
2

間違いなく最初のオプション。いくつかの言葉:

  • それはコントローラーの仕事です...まあ、制御します。これは、少なくとも有用なエラー メッセージが表示されるように注意する必要があることを意味します。アプリケーションの他の部分は、例外的なケースを処理できる場合は、前にそれを行う場合があります。これにはモデル自体も含まれます。それを処理できる場合は、処理する必要があります。

  • save()「保存する」という意味です。戻り値をステータス情報として誤用しないでください。メソッドができない場合save()は例外であり、メソッドが何かを与える必要がない場合は、何かを与えるべきではありません。

于 2013-01-08T22:19:09.913 に答える
1

私はオプション 3 を好みます。

モデルは例外をキャッチし、解決を試みます。例外をコントローラーに浸透させるのではなく、コントローラーが対処して回復できるものである場合に限ります。この場合、(ある種の DB 保存の失敗) 返されるモデルでそれをキャッチすることはfalse、保存エラーの適切な解決策であり、コントローラーが保存時に問題が発生したことを知るのに十分な情報を提供する必要があります。

コントローラーは、モデルが保存を実装する方法に関する実装の詳細について心配する必要はありません。

于 2013-01-08T22:18:19.780 に答える