ユーザーがページを表示できるかどうかを判断するために、ユーザーのアクセス許可チェックを実行しています。これには、最初にミドルウェアを介して要求を渡すことが含まれます。
私が抱えている問題は、データをビュー自体に返す前に、ミドルウェアとコントローラーで同じデータベースクエリを複製していることです。
セットアップの例を次に示します。
-routes.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()
が繰り返されています。複製しないように、一方から他方にデータを渡す必要があります。
(Laravel 5.xで)これを行う正しい方法は、カスタムプロパティをattributesプロパティに追加することだと思います。
ソースコードのコメントから、カスタムパラメータに属性が使用されていることがわかります。
/**
* Custom parameters.
*
* @var \Symfony\Component\HttpFoundation\ParameterBag
*
* @api
*/
public $attributes;
したがって、これを次のように実装します。
$request->attributes->add(['myAttribute' => 'myValue']);
その後、次を呼び出して属性を取得できます。
\Request::get('myAttribute');
または、laravel 5.5+のリクエストオブジェクトから
$request->get('myAttribute');
カスタム要求パラメーターの代わりに、制御の反転パターンに従って、依存性注入を使用できます。
ミドルウェアで、Page
インスタンスを登録します。
app()->instance(Page::class, $page);
次に、コントローラーにPage
インスタンスが必要であることを宣言します。
class PagesController
{
protected $page;
function __construct(Page $page)
{
$this->page = $page;
}
}
Laravelは依存関係を自動的に解決し、ミドルウェアでバインドしたPage
インスタンスを使用してコントローラーをインスタンス化します。
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');
...
}
上記のlaravel 5.3.xのコメントの1つで述べたように
$request->attributes->add(['key => 'value'] );
動作しません。しかし、ミドルウェアでこのような変数を設定すると動作します
$request->attributes->set('key', 'value');
コントローラーでこれを使用してデータを取得できました
$request->get('key');
// in Middleware register instance
app()->instance('myObj', $myObj);
そして
// to get in controller just use the resolve helper
$myObj = resolve('myObj');
それは非常に簡単です:
ミドルウェアコードは次のとおりです。
public function handle($request, Closure $next)
{
$request->merge(array("customVar" => "abcde"));
return $next($request);
}
ここにコントローラーコードがあります:
$request->customVar;
$ requestは配列なので、配列に値とキーを追加するだけで、コントローラーでこのキーを使用して$ requestを取得できます。
$ request ['id'] = $ id;
Webサイトにデータベースから取得される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>
すべてに感謝し、コードをお楽しみください:)
次の方法でRequest-objectに値を追加できました。
$request->attributes->set('key', 'value');
後でそれらを取得するには:
$request->attributes->get('key');
これは、 laravels Request extends symfonys Request 属性のタイプが- $ attributes " ParameterBag つまり カスタムパラメータ を保持することを目的としています。
これは、後続のミドルウェア、コントローラー、またはリクエストオブジェクトにアクセスできる他の場所にデータを渡すためのベストプラクティスであると思います。
Laravel 5.6でテストしましたが、おそらく他のバージョンでも動作します。
私は英語を話せないので、可能性のあるエラーのために申し訳ありません。
これにはIoCバインディングを使用できます。ミドルウェアでは、$ pageインスタンスをバインドするためにこれを行うことができます。
\App::instance('mi_page_var', $page);
その後、コントローラーでそのインスタンスを呼び出します。
$page = \App::make('mi_page_var');
App :: instanceはクラスを再インスタンス化せず、代わりに以前にバインドしたインスタンスを返します。