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

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

ただいまの
回答率

89.98%

Laravel で コントローラーでサービスコンテナを登録したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 84

Mao_3309

score 1

前提

前提条件としてすでに 1つのモジュール(以下の例で BModule)はすでに実装されております。
モジュールは API(REST 通信)にて情報を取得し、後続処理でそのデータを使用します。
今後別の APIプログラムにアクセスする CModule を実装を予定しており、
それはユーザーの情報によって切り替える必要があります。

既存の処理を変更したくないため、サービスコンテナを切り替えることで、新たなモジュール
「CModule」を実装したいと考えています。

実現したいこと

通常はサービスプロバイダーで行うとと思いますが、リクエストパラメーターを使用したDBアクセスを伴うためコントローラーで行いたいです。
そのような方法は可能でしょうか?

現状の実装

完全なプログラムを公開することはできないため、一部加工してあります。

インターフェイス

namespace App\Modules;

interface ModuleBase {
   public function getData();
   public function getPath();
   public function getItem();

//その他複数のメソッド

作成したインターフェイスを継承する 2つのモジュール

namespace App\Modules;

class BModule implements ModuleBase {
   private $data;
   public function getData(){
     $url = 'https://b.xxxxx.xxx/api/xxx';
     $client = new \GuzzleHttp\Client();
     $response = $client->request(
       'POST',
        $url,
        ['key' => 'xxxxxxx']
     );
     $this->data = $response->getBody(); 
   }
   public function getPath(){
     return $this->data['path'];
   }
   public function getItem(){
     return $this->data['item'];
   }

//その他複数のメソッド
namespace App\Modules;

class CModule implements ModuleBase {
   public function getData(){
     $url = 'https://c.xxxxx.xxx/api/xxx';
     $client = new \GuzzleHttp\Client();
     $response = $client->request(
       'POST',
        $url,
        ['key' => 'xxxxxxx', 'user' => 'xxxxxx']
     );
     $this->data = $response->getBody(); 
   }
   public function getPath(){
     $res = implode('/', $this->data['path'])
     return $res;
   }
   public function getItem(){
     return $this->data['item'];
   }

//その他複数のメソッド

既存処理である BModule はサービスコンテナに登録されている

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
       $this->app->bind(
          'App\Modules\ModuleBase',
          'App\Modules\BModule'
       );    
    }
}

既存処理 BModule をコントローラーで CModule に切り替えたい

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App;

class ItemController extends Controller
{
    public function index(Request $request)
    {
      $id = $request->input('user_id');
      $user = \App\User::find($id);

      if($user->apiStatus == 1){
      //■■ここで ModuleBase と CModule をバインドする方法が知りたいです。■■

      }
      $api = App::make(App\Modules\ModuleBase::class);
      $api->getData();

      //これ以降にも「App::make(App\Modules\ModuleBase::class)」を使用してデータを取得する処理があります。
      //既存の処理を変更したくないため、サービスコンテナで切り替えたいと考えております。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2019/11/15 15:30

    >Lalavel
    Laravel です。

    >以下のようなモジュールを作成し
    何をしたいのかわかりませんがこの書き方はあまりよろしくないかと。クラス名が仮すぎる、1ファイルにクラスとインターフェース、複数詰め込んでる、など。

    キャンセル

  • Mao_3309

    2019/11/15 15:47

    ご指摘ありがとうございます。
    修正いたしましたので、ご確認いただけないでしょうか。
    至らない点がございましたら修正いたしますので、ご教授ください。

    キャンセル

  • Kosuke_Shibuya

    2019/11/15 17:03

    提示されたコードの処理を追ってみると、modelにアクセサを設定すれば済むように思うのですが、サービスコンテナを使う必要性が読み取れませんでした。

    キャンセル

  • Mao_3309

    2019/11/15 18:02

    ご指摘ありがとうございます。
    私の至らない点で、誤解を招き申し訳ありません。
    前提条件と、コードを修正しました。
    よろしければご確認をお願いします。

    キャンセル

回答 1

checkベストアンサー

0

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App;

class ItemController extends Controller
{
    public function index(Request $request)
    {
      $id = $request->input('user_id');
      $user = \App\User::find($id);

      switch ($user->apiStatus)
      {
           case 1:
               $clazz = new BModule();
               break;
           case 2:
               $clazz = new CModule();
               break;
      }
      if (!isset($clazz)) {
            return;
      }
      $data = $clazz->getData();
}

こういうことですかね?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/15 18:32

    回答ありがとうございます。
    記載いただいたコードでもほぼほぼ、実装可能です。
    $api = App::make(App\Modules\ModuleBase::class); の部分を毎回 case文で new するのが面倒で質問しましたが、この内容で実装しようと思います。

    キャンセル

  • 2019/11/15 18:44 編集

    うーん。。。
    正直、どの値とクラスが結びつくのかルールが提示されていないので、switchで書くしか方法がないだけです。

    キャンセル

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

  • ただいまの回答率 89.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる