Laravel 미들웨어는 컨트롤러에 변수를 반환합니다.


87

사용자가 페이지를 볼 수 있는지 여부를 확인하기 위해 권한 검사를 수행하고 있습니다. 여기에는 먼저 미들웨어를 통해 요청을 전달하는 것이 포함됩니다.

내가 가진 문제는 데이터를 뷰 자체에 반환하기 전에 미들웨어와 컨트롤러에서 동일한 데이터베이스 쿼리를 복제하고 있다는 것입니다.

다음은 설정의 예입니다.

-route.php

Route::get('pages/{id}', [
   'as' => 'pages',
   'middleware' => 'pageUser'
   'uses' => 'PagesController@view'
]);

-PageUserMiddleware.php (클래스 PageUserMiddleware)

public function handle($request, Closure $next)
    {
        //get the page
        $pageId = $request->route('id');
        //find the page with users
        $page = Page::with('users')->where('id', $pageId)->first();
        //check if the logged in user exists for the page
        if(!$page->users()->wherePivot('user_id', Auth::user()->id)->exists()) {
            //redirect them if they don't exist
            return redirect()->route('redirectRoute');
        }
        return $next($request);
    }

-PagesController.php

public function view($id)
{
    $page = Page::with('users')->where('id', $id)->first();
    return view('pages.view', ['page' => $page]);
}

보시다시피 Page::with('users')->where('id', $id)->first()미들웨어와 컨트롤러 모두에서 반복됩니다. 중복되지 않도록 데이터를 하나에서 다른 것으로 전달해야합니다.


저도 똑같은 질문을하려고했는데이 대답을 찾는 데 오랜 시간이 걸렸습니다. 여기 내 질문이 있습니다. SEO / 검색 가능성을 위해 여기에 추가하겠습니다. 괜찮기를 바랍니다. Laravel 5.0-미들웨어 및 컨트롤러에 모델로드. 미들웨어와 컨트롤러 모두에서 동일한 인스턴스 (하나의 데이터베이스 쿼리 만)를 사용할 수 있도록 사용자 모델의 인스턴스를로드하려면 어떻게해야합니까? 미들웨어에서 사용자가 인증되었는지 확인하고 컨트롤러에서 사용자에 대한 정보를 제공하거나 어떻게 든 사용자를 조작하고 싶기 때문입니다.
alieninlondon

답변:


136

이 작업을 수행하는 올바른 방법 (라 라벨 5.x에서)은 사용자 정의 필드를 속성 속성에 추가하는 것입니다.

소스 코드 주석에서 사용자 지정 매개 변수에 사용되는 속성을 확인할 수 있습니다.

 /**
 * Custom parameters.
 *
 * @var \Symfony\Component\HttpFoundation\ParameterBag
 *
 * @api
 */
public $attributes;

따라서이를 다음과 같이 구현합니다.

$request->attributes->add(['myAttribute' => 'myValue']);

그런 다음 다음을 호출하여 속성을 검색 할 수 있습니다.

\Request::get('myAttribute');

또는 laravel 5.5+의 요청 객체에서

 $request->get('myAttribute');

1
그런 다음 수신 컨트롤러 내의 속성에 어떻게 액세스합니까?
user985366

1
컨트롤러 메소드 인수에 요구 클래스를 추가 IOC (컨테이너) 또는 정적 클래스 \ 호출 요청
Gaz_Edge

8
$ myAttribute = \ Request :: get ( 'myAttribute');
Shawn C.

4
와,이 솔루션은 매우 깨끗해 보입니다!
schellingerht

3
당신은 또한 사용할 수있는 $request->request->add(['myAttribute' => 'myValue']);마법 게터 속기 사용할 수 있도록$request->myAttribute
jonan.pineda

29

사용자 지정 요청 매개 변수 대신 제어 반전 패턴을 따르고 종속성 주입을 사용할 수 있습니다.

미들웨어에서 Page인스턴스를 등록합니다 .

app()->instance(Page::class, $page);

그런 다음 컨트롤러에 Page인스턴스가 필요하다고 선언 합니다.

class PagesController 
{
    protected $page;

    function __construct(Page $page) 
    {
        $this->page = $page;
    }
}

Laravel은 자동으로 종속성을 해결하고 Page미들웨어에 바인딩 한 인스턴스로 컨트롤러를 인스턴스화합니다 .


1
이것은 정말 좋은 생각입니다. 계속해서 서비스 공급자를 만든 다음 서비스 컨테이너를 등록했습니다. 이렇게하면 몇 가지 속성이 필요할 때 종속성을 주입 할 수 있습니다. 훨씬 깨끗하고 투명합니다. 감사!
Arian Acosta

1
@ArianAcosta 제발, 당신의 방식으로 대답을 자세히 설명해 주시겠습니까? 내 말은, 의존성 주입을 사용하는 방법과 그것이 미들웨어와 어떻게 연관되어 있는지를 의미합니다.
JCarlosR

4
@JCarlos 물론입니다! 아이디어는 미들웨어와 컨트롤러 사이에서 전달해야하는 데이터를 내부 속성으로 보유하는 사용자 정의 서비스 컨테이너 클래스를 갖는 것입니다. $ this-> app-> singleton (...)을 사용하여 해당 서비스 컨테이너를 싱글 톤으로 등록하면 삽입 할 때마다 항상 동일한 인스턴스가됩니다. 따라서 기본적으로 먼저 미들웨어에 삽입하고 (단순히 인수로 요구하여) 데이터를 내부에 넣고 마지막으로 데이터에 액세스 할 수있는 컨트롤러에 데이터를 요구합니다. 참조 laravel.com/docs/5.4/container의 좋은 행운을
아리안 아코 스타에게

2
이것은 훌륭한 대답입니다 ... 깔끔합니다! :)
Pietro

5
비고 : __constructor에서는 미들웨어가 컨트롤러의 생성자 다음에로드 되었기 때문에 작동하지 않습니다. 그러나 컨트롤러의 모든 동작에서 DI를 사용할 수 있습니다.
Serhii Topolnytskyi

18

laravel> = 5 $request->merge에서는 미들웨어에서 사용할 수 있습니다 .

public function handle($request, Closure $next)
{

    $request->merge(array("myVar" => "1234"));

    return $next($request);
}

그리고 컨트롤러에서 :

public function index(Request $request)
{

    $myVar = $request->instance()->query('myVar');
    ...
}

11
Request::instance()사용하는 대신 정적으로 액세스하는 이유는 무엇 $request입니까?
jjok

17

라 라벨 5.7

// in Middleware register instance
app()->instance('myObj', $myObj);

// to get in controller just use the resolve helper
$myObj = resolve('myObj');

7

laravel 5.3.x에 대한 위의 주석 중 하나에서 언급했듯이

$request->attributes->add(['key => 'value'] ); 

작동하지 않습니다. 하지만 미들웨어에서 이와 같은 변수를 설정하면

$request->attributes->set('key', 'value');

내 컨트롤러에서 이것을 사용하여 데이터를 가져올 수 있습니다.

$request->get('key');

6

미들웨어에서 컨트롤러로 데이터를 전달할 수 있다면 Laravel 문서에있을 것입니다.

이것이것 좀 봐 , 도움 될 수 있습니다.

요컨대 미들웨어로 전달되는 요청 객체에 데이터를 피기 백 할 수 있습니다. 라 라벨 인증 파사드도 그렇게합니다.

따라서 미들웨어에서 다음을 가질 수 있습니다.

$request->myAttribute = "myValue";

고마워 @norman-좋은 해결책이고 나는 당신이 그것을 할 수 있다는 것을 몰랐습니다 ...! 이 시점에서 미들웨어를 사용해야하는지 의문이 들었지만 그래야 할 것 같습니다. 문서에는 그런 종류의 언급이 없습니다. 다시 한 번 감사드립니다
Alex

1
@Alex 예, 모든 컨트롤러 동작에서 실행되는 공통 코드 조각이라면 미들웨어로 구현하는 것이 나쁜 생각이 아닙니다.
Noman Ur Rehman 2015 년

5

매우 간단합니다.

다음은 미들웨어 코드입니다.

public function handle($request, Closure $next)
{

    $request->merge(array("customVar" => "abcde"));

    return $next($request);
}

다음은 컨트롤러 코드입니다.

$request->customVar;

2

웹 사이트에 데이터베이스에서 가져 오는 cms 페이지가 있고 laravel 응용 프로그램의 모든 페이지에서 머리글 및 바닥 글 블록에 제목을 표시하려면 미들웨어를 사용하십시오. 미들웨어에서 아래 코드를 작성하십시오.

namespace App\Http\Middleware;

use Closure;

use Illuminate\Support\Facades\DB;

public function handle($request, Closure $next)
{    

$data = DB::table('pages')->select('pages.id','pages.title')->where('pages.status', '1')->get();

\Illuminate\Support\Facades\View::share('cms_pages', $data);

return $next($request);

}

그런 다음 header.blade.php 및 footer.blade.php로 이동하여 아래 코드를 작성하여 cms 페이지 링크를 추가하십시오.

<a href="{{ url('/') }}">Home</a> | 

@foreach ($cms_pages as $page) 

<a href="{{ url('page/show/'.$page->id) }}">{{ $page->title }}</a> | 

@endforeach

<a href="{{ url('contactus') }}">Contact Us</a>

모두에게 감사하고 코드를 즐기십시오 :)


1

저는 영어를 못합니다. 그래서 ... 가능한 오류에 대해 죄송합니다.

이를 위해 IoC 바인딩을 사용할 수 있습니다. 미들웨어에서 $ page 인스턴스를 바인딩하기 위해 다음을 수행 할 수 있습니다.

\App::instance('mi_page_var', $page);

그런 다음 컨트롤러에서 해당 인스턴스를 호출합니다.

$page = \App::make('mi_page_var');

App :: instance는 클래스를 다시 인스턴스화하지 않고 대신 이전에 바인딩 된 인스턴스를 반환합니다.


1

다음을 사용하여 Request-object에 값을 추가 할 수있었습니다.

$request->attributes->set('key', 'value');

다음을 사용하여 나중에 다시 가져옵니다.

$request->attributes->get('key');

이것은 laravels Request사용자 정의 매개 변수 를 보유하기위한 ParameterBag 유형의 " $ attributes " 속성을 갖는 심포니 요청을 확장 하기 때문에 가능합니다 .

데이터를 후속 미들웨어, 컨트롤러 또는 요청 객체에 액세스 할 수있는 다른 장소로 전달하는 것이 모범 사례라고 생각합니다.

Laravel 5.6 에서 테스트 되었지만 다른 버전에서도 작동 할 수 있습니다.


1

$request배열에 값과 키를 추가 $request하고 컨트롤러에서이 키로 가져올 수 있도록 배열 입니다.

$request['id'] = $id;

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.