Laravel 中间件 return 变量到控制器
Laravel Middleware return variable to controller
我正在对用户执行权限检查以确定他们是否可以查看页面。这涉及首先通过一些中间件传递请求。
我遇到的问题是,在将数据返回到视图本身之前,我在中间件和控制器中复制了相同的数据库查询。
这是设置示例;
-- routes.php
Route::get('pages/{id}', [
'as' => 'pages',
'middleware' => 'pageUser'
'uses' => 'PagesController@view'
]);
-- PageUserMiddleware.php (class 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 文档中。
看看 this and this,可能会有帮助。
简而言之,您可以在传递给中间件的请求对象上搭载您的数据。 Laravel 身份验证外观也是如此。
因此,在您的中间件中,您可以拥有:
$request->myAttribute = "myValue";
我认为正确的方法(在 Laravel 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');
我不会说英语,所以...很抱歉可能有错误。
您可以为此使用 IoC 绑定。在你的中间件中,你可以这样做来绑定 $page 实例:
\App::instance('mi_page_var', $page);
之后,在您的控制器中调用该实例:
$page = \App::make('mi_page_var');
App::instance 不会重新实例化 class,而是 return 之前绑定的实例。
您可以遵循控制反转模式并使用依赖注入,而不是自定义请求参数。
在您的中间件中,注册您的 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(["myVar" => "1234"]);
return $next($request);
}
并在控制器中
public function index(Request $request)
{
$myVar = $request->myVar;
...
}
正如上面对 laravel 5 的评论之一所述。3.x
$request->attributes->add(['key => 'value'] );
无效。但是在中间件中这样设置变量是可行的
$request->attributes->set('key', 'value');
我可以在我的控制器中使用它来获取数据
$request->get('key');
$request
是数组,这样我们就可以将值和键添加到数组中,并在控制器中使用此键获得 $request
。
$request['id'] = $id;
我能够通过以下方式向请求对象添加值:
$request->attributes->set('key', 'value');
稍后通过以下方式取回:
$request->attributes->get('key');
这是可能的,因为 laravels Request extends symfonys Request which has the attribute "$attributes" of type ParameterBag that is intended to hold custom parameters.
我认为这应该是将数据传递到后续中间件、控制器或任何其他可以访问请求对象的地方的最佳实践。
已使用 Laravel 5.6 进行测试,但可能也适用于其他版本。
很简单:
中间件代码如下:
public function handle($request, Closure $next)
{
$request->merge(array("customVar" => "abcde"));
return $next($request);
}
这里是控制器代码:
$request->customVar;
Laravel 5.7
// in Middleware register instance
app()->instance('myObj', $myObj);
和
// to get in controller just use the resolve helper
$myObj = resolve('myObj');
如果您的网站有从数据库中获取的 cms 页面,并希望在 header 和 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>
非常感谢大家享受代码:)
我正在对用户执行权限检查以确定他们是否可以查看页面。这涉及首先通过一些中间件传递请求。
我遇到的问题是,在将数据返回到视图本身之前,我在中间件和控制器中复制了相同的数据库查询。
这是设置示例;
-- routes.php
Route::get('pages/{id}', [
'as' => 'pages',
'middleware' => 'pageUser'
'uses' => 'PagesController@view'
]);
-- PageUserMiddleware.php (class 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 文档中。
看看 this and this,可能会有帮助。
简而言之,您可以在传递给中间件的请求对象上搭载您的数据。 Laravel 身份验证外观也是如此。
因此,在您的中间件中,您可以拥有:
$request->myAttribute = "myValue";
我认为正确的方法(在 Laravel 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');
我不会说英语,所以...很抱歉可能有错误。
您可以为此使用 IoC 绑定。在你的中间件中,你可以这样做来绑定 $page 实例:
\App::instance('mi_page_var', $page);
之后,在您的控制器中调用该实例:
$page = \App::make('mi_page_var');
App::instance 不会重新实例化 class,而是 return 之前绑定的实例。
您可以遵循控制反转模式并使用依赖注入,而不是自定义请求参数。
在您的中间件中,注册您的 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(["myVar" => "1234"]);
return $next($request);
}
并在控制器中
public function index(Request $request)
{
$myVar = $request->myVar;
...
}
正如上面对 laravel 5 的评论之一所述。3.x
$request->attributes->add(['key => 'value'] );
无效。但是在中间件中这样设置变量是可行的
$request->attributes->set('key', 'value');
我可以在我的控制器中使用它来获取数据
$request->get('key');
$request
是数组,这样我们就可以将值和键添加到数组中,并在控制器中使用此键获得 $request
。
$request['id'] = $id;
我能够通过以下方式向请求对象添加值:
$request->attributes->set('key', 'value');
稍后通过以下方式取回:
$request->attributes->get('key');
这是可能的,因为 laravels Request extends symfonys Request which has the attribute "$attributes" of type ParameterBag that is intended to hold custom parameters.
我认为这应该是将数据传递到后续中间件、控制器或任何其他可以访问请求对象的地方的最佳实践。
已使用 Laravel 5.6 进行测试,但可能也适用于其他版本。
很简单:
中间件代码如下:
public function handle($request, Closure $next)
{
$request->merge(array("customVar" => "abcde"));
return $next($request);
}
这里是控制器代码:
$request->customVar;
Laravel 5.7
// in Middleware register instance
app()->instance('myObj', $myObj);
和
// to get in controller just use the resolve helper
$myObj = resolve('myObj');
如果您的网站有从数据库中获取的 cms 页面,并希望在 header 和 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>
非常感谢大家享受代码:)