ラムネグから一言:寝る前に読むとくだらなすぎて逆に寝れると好評なすごい適当なブログをこっちではじめてます.
laravelでWEBサービスを作っているとよく思うコトとして、
- 異なるコントローラー間で共通の処理(関数)だったり共通の定数ってどこに書けばいいんだろう
というのが私の中でずーっとありました。開発してるとコントローラーを分けるコトって当然ありますし、例えばPost処理だけを担うPostControllerと、Get処理だけを担うGetContorollerとかに分けますよね。…人によってはもっと細分化するかもしれません。
で、そういう時に「同じ関数だったり定数をどちらのコントローラーでも使いたいんだけれど…」という時、調べるのも億劫なので、もう同じ関数や定数を両コントローラーそれぞれに書いちゃったりしてました。
ここではlaravelで異なるコントローラー間で共通処理を行いたい時、どこに書けばベストなのかについて書きますね。
結論:トレイト(trait)がベスト
結論から先に。その他の選択肢は記事下部に書きますね。
laravelでコントローラー間で共通処理を行いたい時、トレイト(trait)というPHP自体の機能を使うのがベストと思います。
トレイトというのをざっくり説明すると、トレイトはクラスの継承ととっても似てるんですが、それを後からサクッと、手軽に上乗せサクサク出来ちゃう機能です。
つまり親クラスとか作らなくてもただ、その関数や定数を使いたいファイルで「use」って書くだけでトレイトで宣言した関数なり定数がすぐ使えるようになるんです。
いざ実装:laravelでトレイト実装
laravelでトレイトを実装するには、まずトレイト用のフォルダを作ります。作らなくてもいいんですが管理しやすくするために作ります。
ググって出てくるやり方そのままなんですが、「app」フォルダ内に「Traits」っていうフォルダを普通に作ってください。コントローラーとかミグレーションファイルとかとは違い、laravelにはトレイトを作る機能がないんですよね。
でその中にこれまた自分でテキストファイルを作ります。拡張子は「.php」で、ファイル名はトレイトだよーというのが自分で分かるやつならなんでもおっけーです。下の例ではファイル名を「CommonTrait.php」としました。
app/Traits/CommonTrait.php
<?php
namespace App\Traits;
trait CommonTrait
{
public function getMailSetting()
{
$setting = "ほにゃらら";
return $setting;
}
とりあえず上記をコピーして保存。
例では「getMailSetting」っていうのが共通化したい処理として書いていますので、これを消してもらって、似たような感じで共通処理化したい関数、共通化したい定数を返す関数、などを自由に追加していってください。例では1関数のみですが何個書いても大丈夫です。
コントローラー側の実装
これでトレイトは作れたので、後はこれをコントローラー側で使うだけ。
上でも書いたんですが「use」宣言するだけで、後は「$this->」ってするだけでトレイトの各関数を自由にコントローラー内で使えます。
PostController.php & GetController.php
use App\Traits\CommonTrait;
class PostController extends Controller
{
use CommonTrait;
public function mail_send(Request $req){
$setting = $this->getMailSetting();
:
:
(続く)
冒頭とクラス内の2行ぶんの「use」があるので注意。後はトレイトで実装した処理を使うとき「$this->getMailSetting()」みたいに書くだけ。
すごい簡単ですよね。トレイトすごい!
共通処理を実装するその他の選択肢
laravelで共通処理を実装するのはトレイト(trait)が一番!という話でしたが、一応他の選択肢も見てみますね。
- ミドルウェア(ファザード?)で実装
- コントローラーの継承で実装
- 共通化したいのが定数のみの場合、laravelのconfigに追加して都度読み出す
- 共通化したいのが定数のみの場合、データベースに保存しておいて都度読み出す
- 共通化したいのが定数のみの場合、普通にrequireで別ファイルを読み込む
ミドルウェア(ファザード?)で実装
laravelにはHTTPリクエストが入った後、処理がコントローラーに任されるようになる前に「ミドルウェア」という割り込み?前処理部分?があります。
laravelでデフォルトで有効になっているミドルウェアもあって、例えば入力フォームの空白トリムとかはこのミドルウェアさんが勝手にやってくれています。
全部のコントローラーで有効にしたい共通処理の場合、このミドルウェアを使うのもありだと思います。またミドルウェアにも$requestは引数で流れてきてるんで、ここに例えば共通化したい定数・変数を入れれば、その次に$requestが渡されるコントローラーでもその値を使えます。やり方はわたし自身この手法を取ったことがないのでググってみていただければと思います。
コントローラーの継承で実装
laravelの「make」コマンドでコントローラーを作ると、そのコントローラーはみんな「extends Controller」となっていますよね。
なのでこの「Controller」に共通処理化したい関数や変数を追加すれば、すべてのコントローラーでそれが継承されて使えるようになります。
ただいくつもあるコントローラーの中で共通処理したいのは2,3個だけなんだよなー、という時はもったいないというか、適さない気がします。
定数のみの場合の3パターン
コントローラー間で変数というか定数のみ共有したい場合ってありますよね。例えば暗号・複合化の際のSeed値とか、入力フォームの最大文字数であるとか、そういう値です。
処理(関数)じゃなくて変数のみっていう事であれば、例えばその変数をもうデータベースに保存しちゃってそれを各コントローラーで読みだすようにしたり、後はlaravelのconfigって自由に環境変数を追加できて、そして環境変数はどのコントローラーからでもアクセスできるんでこれで定数を宣言したり、後はもうPHP的なやり方ですが定数を宣言したファイルを作っておいてそれをコントローラーの上部でrequireすれば使えるようになります。
まとめ
laravelで異なるコントローラー間で共通処理を行う場合、関数や変数はどこに書くのがベストなのかについて書きました。
個人的にはPHPの機能「トレイト(trait)」で共通処理を実装するのがベスト、という感じ。これならグローバル変数を汚さないし、関数でも変数でも自由に1ファイルにまとめられるし、使うのもuseするだけでいいのでコントローラーごとに読み込まなかったり読み込んだりを変えられるしで、一番かゆい所に手が届いてると思います。
参考にしてみてくださいね。
【おしらせ、というか完全なる宣伝】
文体がもうぜんぜん適当すぎてあれだけどものすごい自由に書いてるブログ「檸檬だくだく」もよろしく.寝る前に読める恐ろしくくだらないやつです.
こんなにも一ミリも目を引かれないタイトルを取り扱ってます: ココア20g / ハイチュウとかってさ / なぜ米と小麦を食べようと思ったのかの謎 /