質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

2回答

2974閲覧

ビジネスロジッククラスにAuth::user()の結果を外から差し込むスマートな方法

mihit

総合スコア61

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

2クリップ

投稿2019/04/03 13:15

編集2019/04/03 13:28

前提・実現したいこと

ログインしないとほとんどの画面が動作しないサイトの開発を行っています。そのサイトのコードで、Laravelに直接依存していないビジネスロジッククラスに、うまいことAuth::user()の情報を自動で注入したいと思っています。
どんな方法があるかご教示ください。

前提

  • ビジネスロジックの中はLaravelから切り離したいのでAuth::user()と書きたくない。
  • Laravel側から登録しにくるサービスコンテナは使ってもいいと思っている。

ゴール

class SomePlainOldPhpLogic { private $user; }

このロジッククラスのインスタンスが呼ばれると常に$userにAuth::user()が入っていて欲しいです。

試したこと

コンストラクタインジェクション

- 呼び元がコントローラなのでそちらのコンストラクタを利用しようとしました。タイプヒントでビジネスロジックをインジェクションしてから、後追いで情報を追加($logic->setUser( Auth::user() )しようとしました。 - しかしそもそもコンストラクタ内ではAuth::user()が呼べませんでした。 - 上の対策にmiddlewareを使う方法というのも試しましたが、事前にAuth::login()で認証情報を仕込んだテストケースから動かすと情報が入らないという動きをしたので、採用できませんでした。

auth::user()と紐付いたサービスコンテナとしてサービスプロバイダに登録

  • registerのときはAuth::user()が呼べませんでした。
  • bootのときは呼べそうですが、どう呼んで紐付ければいいのかわかりません。(ここが解決すればなんとかなる?)

ちなみに今は

ビジネスロジックのpublicなメソッドに毎回 Auth::user()を渡しています。ダサいです。
せめて$logic->setUser( Auth::user() )を自動で呼ぶことはできないかな…

補足情報(FW/ツールのバージョンなど)

Laravel 5.4 です。古くてすみません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

  • Illuminate\Contracts\Auth\Guard
  • Illuminate\Contracts\Auth\Factory

GuardFactory をDIするのが正攻法だと思います。Guard がデフォルト認証方法に設定されているもの(例えば SessionGuard),FactoryAuthManager に対応します。

php

1class SomePlainOldPhpLogic 2{ 3 protected $guard; 4 5 public function __construct(Guard $guard) 6 { 7 $this->guard = $guard; 8 } 9 10 public function user(): User 11 { 12 return $this->guard->user(); 13 } 14}

コンテナの利用方法については
【Laravel】サービスコンテナ・サービスプロバイダ・ファサード・契約に関する補足資料 - Qiita
をご覧ください

投稿2019/04/03 17:53

編集2019/04/03 18:02
mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mpyw

2019/04/03 18:44 編集

>> SomePlainOldPhpLogic内にuser持ったら結局依存してる気がするけど この通りなんですよね… フレームワーク独立を謳うのであれば,すべて Contract ベースに書かないといけないです。User を User であるとして使っちゃいけないんです,あくまでそれは Authenticatable です。完全な非依存は無理ゲーですね。
mihit

2019/04/04 11:38

ありがとうございます。 Authの契約をこうして利用できるのですね。「デフォルトの認証方式が入る」なども、サービスコンテナの性質から考えれば言われてみるとなるほどと思うのですが…! ありがたいです。 UserをUserであるとして使ってはいけないというのはつまり、$userを注入するのではなく、契約をベースに$userを「提供する機能」を注入すると考えた方が、より独立性が高まると理解すればよいでしょうか?
mpyw

2019/04/04 18:10

>> 契約をベースに$userを「提供する機能」を注入する 今回の回答はまさにそんな感じなんですが、コメントに書いたのは少し趣旨が違います。Eloquent Model を直接サービス層で使う時点でもう完全な独立は守れない、ということです。 Eloquent Model クラス自体が Laravel とかなり密結合です。(↓のREADMEにあるようにCapsuleとして使ったとしてもここはそんなに変わらないと思う) illuminate/database: [READ ONLY] Subtree split of the Illuminate Database component (see laravel/framework) https://github.com/illuminate/database
mpyw

2019/04/04 18:20 編集

以下のようなものを作り、 ・そのサービス層専用のUserオブジェクト(例えばUserEntity) ・そのサービス層専用のGuardのラッパー(例えばUserEntityProvider) ↓多分ここまでしないと「SomePlainOldPhpLogic は Laravel から独立している」とは言えないと思います。 class UserEntityProvider implements UserEntityProviderContract {     protected $guard;     public function __construct(Guard $guard)     {         $this->guard = $guard;     }     public function user(): UserEntityContract     {         $this->guard->user()->toUserEntity(); // この変換メソッドは User Model 上に実装     } } class SomePlainOldPhpLogic {     protected $provider;     public function __construct(UserEntityProviderContract $provider)     {         $this->provider = $provider;     }     public function user(): UserEntityContract     {         return $this->provider->user();     } }
mpyw

2019/04/04 18:21

ここまでするメリットがあるかどうかでいうと正直無いことのほうが多いと思うので、あまり独立性にこだわらなくてもいいかなと思います(本音
mihit

2019/04/05 07:20

なるほど、UserもUserの発行元も本当にLaravelと無関係な実体にまで分離する、これこそが厳密なやり方だというのはよくわかります! そこまでする必要ない感ただよってるのもわかります!???? 遅くなりましたがあっさり動作確認も取れました。直接の問題解決以外にもいろいろな気づきをいただけたのでBA差し上げます。ありがとうございました。
guest

0

SomePlainOldPhpLogic内にuser持ったら結局依存してる気がするけど
サービスコンテナ使うならこういうのでいいのでは。

php

1public function register() 2{ 3 $this->app->bind(SomePlainOldPhpLogic::class, function ($app) { 4 return new SomePlainOldPhpLogic(auth()->user()); 5 }); 6}

普通にregister()でauth()->user()が正しく取得できることは手元で確認した。
もちろんsingletonはやめたほうが良さそう。

投稿2019/04/03 14:34

kawax

総合スコア10377

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mihit

2019/04/04 11:17

動作確認ありがとうございます! それで一度うまくいかなかったのですが元気出ました。もう一度確認してみます。 $user使うなら結局依存するのはおっしゃるとおりですね。まあLaravelから逃げても普通ORマッパーまでは捨てないか移植するかでしょうし(userのプロパティが変わっちゃうならロジックだって使い回せませんし)、user()の後ならgateも通った後だし、必要なプロパティのおててが生えてくる容れ物としてだけ扱えばだいたい互換する程度の出来栄えを想定してはいます。
mihit

2019/04/05 07:29 編集

$this->app->bind(SomePlainOldPhpLogic::class, function(){ return new SomePlainOldPhpLogic( auth()->guard() ); } ); resolve( SomePlainOldPhpLogic::class )->resolveMyConcerns() 動きました! Auth:: より auth() のほうがimportを汚さなくていいですね。 ひとまずこんな実装を試しています。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問