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

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

ただいまの
回答率

90.51%

  • Laravel 5

    2513questions

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

  • オブジェクト指向

    325questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

laravelで共通処理を別メソッドに分けて定義しただけで動作しなくなりました

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,979

■概要
Laravelで特定のページ(/manage)を管理者IDを持っているユーザーのみ表示出来るようにしたいと考えています。
laravelのPolicyを使って管理者IDの利用者以外がmanage.blade.phpにアクセスしようとするとTOPページ('/')にリダイレクトさせる処理を書いたのですが、アクセス制限したいページが増えたので別のメソッドに定義してそのメソッドを呼び出すようにしたところリダイレクトしなくなりました。(制限したいページが通常通り表示されてしまう)
原因、対処法等わかりましたら教えていただけると助かります!

A.最初のコード(ちゃんと動作したコード)

//ProjectController.php

class ProjectController
{
    /* プロジェクト管理画面表示 */
    public function getProjectManager(){

        //①policyを使って特定ユーザー以外を'/'にリダイレクト
        $id = \Auth::user()->id;
        $user = User::findOrFail($id);
        if (Gate::denies('display',$user)) {
            return redirect("/");
        } 

        //②projectsテーブルからidとtitleを全て取得
        $keys = ['id','title'];
        $projects = $this->project->getProjectInfo($keys);

        //③取得したデータと一緒にviewにリターン
        return view('manager.manage')->with('projects',$projects);

    }
}
//UserPolicy.php

class UserPolicy
{
     //userのidが2の場合trueを返す
     public function display(User $user){
        return $user->id == 2;
    }
}

B.ProjectControllerのgetProjectManager()メソッド内のアクセス制限部分を別メソッドcheckManager()に分割したコード(UserPolicy.phpは変更なし)
(ちゃんと動作せずに管理画面が表示されてしまう)

//ProjectController.php

class ProjectController
{
    /* プロジェクト管理画面表示 */
    public function getProjectManager(){

     //外出ししたcheckManagerメソッドを実行
        $this->checkManager();

        $keys = ['id','title'];
        $projects = $this->project->getProjectInfo($keys);

        return view('manager.manage')->with('projects',$projects);

    }

   public function checkManager(){
        //①policyを使って特定ユーザー以外を'/'にリダイレクト
        $id = \Auth::user()->id;
        $user = User::findOrFail($id);
        if (Gate::denies('display',$user)) {
            return redirect("/");
        }  
    }
}


Aのコードだとちゃんとリダイレクトされるのですが、Bのコードだとリダイレクトされずに制限したいはずのページが表示されてしまいます。

■原因調査過程
Bのコードにてexit()を使って調べたのですが、どうも、
if(Gate::denies('display',$user)){}の中までは処理が進んでいるようで、中身を以下のように記述すると、ページにはaと表示されます。

if(Gate::denies('display',$user)){
   echo 'a';
   exit();
   return redirect("/");
}

なのでreturn redirect("/")の部分がちゃんと効いていないと思います。
ただ、同じProjectController.php内でメソッドとして外出ししただけでredirectが効かなくなる理由が全くわかりません。
もしおわかりになる方がいらっしゃいましたらご教示頂けると嬉しいです。

■環境
・cloud9

どうぞ宜しくお願い致します。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

直接的な要因としては、
Aのコードだとコントローラの処理(getProjectManager)の
最終的にreturnしている値がredirect("/")なのに対し、
Bのコードでは、return redirect("/")している先がgetProjectManager()メソッドであり、
そのgetProjectManager()メソッドの最終的なreturnしている値では無いからですね。

redirect()自体は、実行すれば即座にリダイレクトされるというものではなく、
RedirectResponseクラスのインスタンスを作成するものなので、実行するだけでは効果が無いです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/10/06 17:31

    具体的な解決策は記述しませんでしたが、例えば権限不足だったらそれに応じたエラーを発生させて Exceptions/Handler.php の中で拾ってリダイレクトする、チェック自体をmiddlewareの中で行う、ポリシークラスを利用するなどという方法もあります。

    キャンセル

  • 2016/10/06 20:19

    ありがとうございます!
    なるほど、getProjectManager()にreturnしていることになるんですね。
    とても解りやすい解説ありがとうございました!

    キャンセル

checkベストアンサー

0

以下のように修正してみてください。

class ProjectController
{
    /* プロジェクト管理画面表示 */
    public function getProjectManager(){

     //外出ししたcheckManagerメソッドを実行
        // $this->checkManager();
        if ($this->checkManager()) {
            return redirect("/");
        }

        $keys = ['id','title'];
        $projects = $this->project->getProjectInfo($keys);

        return view('manager.manage')->with('projects',$projects);

    }

   public function checkManager(){
        //①policyを使って特定ユーザー以外を'/'にリダイレクト
        $id = \Auth::user()->id;
        $user = User::findOrFail($id);

        // if (Gate::denies('display',$user)) {
        //     return redirect("/");
        // }  
        return Gate::denies('display',$user);
    }
}

メソッドとして外出ししただけでredirectが効かなくなる理由

は、checkManager()メソッド内でreturn redirect("/");を呼び出しているためです。

すると、制限すべきユーザーがアクセスしてきた際でもgetProjectManager()メソッドの処理が中断しないため、
結局 最終行のreturn view('manager.manage')->with('projects',$projects);が呼び出されてしまいます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/10/06 20:18

    ありがとうございます!
    無事動作しました。
    具体的なコードまで提示して頂き助かりました!

    キャンセル

同じタグがついた質問を見る

  • Laravel 5

    2513questions

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

  • オブジェクト指向

    325questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。