質問: phpをメインにfuelphp,cakephp,laravelなどいくつかフレームワークを使った開発経験があるのですが controllerの単位について悩んでいます。 プロジェクトや設計思想によってその定義はバラバラだと思いますが 例えばUserController1つに取って考えてみてもかなり吟味するパターンがいくつかあります。 例えば以下の行動(アクション)です。 * システム利用のために会員登録する * システム利用のためにメール認証して本人確認を済ませる * ログインする * ユーザー名を変える * メールアドレスを変更する * パスワードを変更する これらはUserに関する行動なので個人的には`UserController`に対応するアクションを定義すべきかと思っています。 `ログインする`はユーザーが行なっているのではなくシステムが行なっているから`LoginController`とずべきだ、という人もいるかもしれません。 Laravelの場合だと、`ログインとログアウト` `ユーザー登録` `パスワードの再発行` `パスワードリセット`の4コントローラーが`Auth`で束ねられていますが、私はこれを全部分解し、`UserController`に移行しました。 次は以下です。(laravelを扱いなれています、、、) * 掲示板に求人の募集を投稿する(create, store) * 管理している求人の一覧を見る(index) * 管理している求人の詳細を見る(show) * 管理しているの内容を修正する(edit, update) * 管理しているを削除する(destroy) これらはUserが行なっていることに間違いはありませんが、求人に関する操作を行なっているので `JobController` とか `WorkController` などが望ましいと思っています。 URLとROUTE的には ``` Route::resource('job/', 'Publish\JobController', ['only' => ['index', 'show']]); Route::group(['middleware' => ['auth']], function () { Route::resource('my_page/job/', 'Client\JobController'); }); ``` が望ましいかと思っています。 controllerの単位の決め方は同時に考えることが多すぎて数時間数日はまってしまうことがあります。 少なくとも私は以下のことを気にしながら開発しています。 1. SEOを意識した親和性のあるURLである、かつ、 2. Routeの記述がシンプルであり1アクションにおけるURLは同じだがGET/POSTで分けられメソッド名も違和感がない、かつ 3. {controller名}.{メソッド名}のビューで違和感がない、かつ 4. どこに何があるのかそれとなく分かってしまいそうなアーキテクチャ構造である 個人的には2番目と3番目に悩まされることが多いですが私は Controller名を軸にURLを決めルーティング設定し Controller名を軸に違和感がなければ {controller名}.{メソッド名}でビューを作るようにしています。 1つわかりやすい例をあげると以下です。 ``` // ログインフォーム Route::get('sign_in', 'Client\UserController@signInForm')->name('sign_in'); // ログイン実行 Route::post('sign_in', 'Client\UserController@signIn'); ``` これは`client.user.sign_in_form`というビューを作ればいいですし、ビューの命名的にも不自然はないどころかかなりマッチしているのではと個人的に思っています。 また、要件2の `Routeの記述がシンプルであり1アクションにおけるURLは同じだがGET/POSTで分けられメソッド名も違和感がない` もクリアしています。 最終的にはどれだけ整理整頓するのが上手いかどうかって話になってきますが、私もいろんなプロジェクトに参画して見てきていますが例えば`passwordResetController`というcontrollerもあったりしたことがあります。 個人的にはこのconrtoller名を見て真っ先に思うのは、何のパスワードをリセットするのだろうか? と思います。(passwordResetっていったらたいていユーザー絡みなので予想はできますが、ユーザーのパスワードであるとは100%言い切れません。) でも、これはどちらかというとアクションだと思うので自分ならこういったcontrollerは作りません。 と、ここまで話た上で、`UserContoroller`に戻ります。 `ユーザーが〜〜〜をする`、というアクションをこの`UserController`に定義していくとは肥大化していしまいます。 Service層とRepository層いれているのでそこの問題は心配していませんが、メソッド名の数です。 システムによってはユーザーがやることなんて結構な数があると思います。 この結構な数のアクションを`UserController`という1ファイルに収めるのを良しとするか不合理とするかで悩んでいます。 `結構な数のアクション`はざっくりですが、今作っているサービスでは普通に40以上はあると思っています。 そのことを考えると`userPasswordResetController`などというcontrollerの利用も考え出しているところですが、やはりパスワードリセットとかはアクションなのでそれをcontrollerとするのは個人的にはものすごく違和感があります。 なので現状こういったルーティングにしています。(ちょっとだけ公開) ``` // ログインフォーム Route::get('sign_in', 'Client\UserController@signInForm')->name('sign_in'); // ログイン実行 Route::post('sign_in', 'Client\UserController@signIn'); // ログアウト実行 Route::post('sign_out', 'Client\UserController@signOut')->name('sign_out'); // パスワード再設定メール送信フォーム Route::get('password/reset_link', 'Client\UserController@passwordResetLinkForm')->name('password.reset_link'); // パスワード再設定メール送信実行 Route::post('password/reset_link', 'Client\UserController@passwordResetLink'); // パスワード再設定フォーム Route::get('password/reset/{token?}', 'Client\UserController@passwordResetForm')->name('password.reset'); //パスワード再設定実行 Route::post('password/reset', 'Client\UserController@passwordReset'); ``` ミドルウェアがwebについては、get通信に対するメソッド名は末尾にFormをつけるということを自分の中でルール化しています。 何かベストプラティクスがありましたらご教示いただけますと助かります。
回答: URLの分離ケース 1. データベース分離型(crud):cakephpの基本思想 2. URL分離型(1url/1controler) 3. 機能分離型 (入力~完了画面) がわりかしおおいですが cakephpの場合、認証が必要な範囲で記載することになります。 (ルートは基本オートマッピングのため) /users ユーザー情報以下 だけの場合は /users/login UsersController ですし 上記に加え /orders 注文情報以下 もいるよなら /login LoginContller です なのでベストは要件によりけりとなります。 要約すれば 誰が操作するかは間違えで 何を操作するかがコントローラーの分離の目安になります。