Estou realizando uma verificação de permissões em um usuário para determinar se ele pode visualizar uma página ou não. Isso envolve passar a solicitação por meio de algum middleware primeiro.
O problema que tenho é que estou duplicando a mesma consulta de banco de dados no middleware e no controlador antes de retornar os dados para a própria visualização.
Aqui está um exemplo da configuração;
- routes.php
Route::get('pages/{id}', [
'as' => 'pages',
'middleware' => 'pageUser'
'uses' => 'PagesController@view'
]);
- PageUserMiddleware.php (classe 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]);
}
Como você pode ver, o Page::with('users')->where('id', $id)->first()
é repetido no middleware e no controlador. Preciso passar os dados de um para o outro para não duplicar.
Respostas:
Acredito que a maneira correta de fazer isso (no Laravel 5.x) é adicionar seus campos personalizados à propriedade de atributos.
A partir dos comentários do código-fonte, podemos ver os atributos usados para parâmetros personalizados:
/** * Custom parameters. * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $attributes;
Portanto, você implementaria isso da seguinte maneira;
$request->attributes->add(['myAttribute' => 'myValue']);
Você pode então recuperar o atributo chamando:
\Request::get('myAttribute');
Ou do objeto de solicitação em laravel 5.5+
$request->get('myAttribute');
fonte
$request->request->add(['myAttribute' => 'myValue']);
para poder usar a abreviação de getter mágico$request->myAttribute
Em vez de parâmetros de solicitação personalizados, você pode seguir o padrão de inversão de controle e usar injeção de dependência.
Em seu middleware, registre sua
Page
instância:app()->instance(Page::class, $page);
Em seguida, declare que seu controlador precisa de uma
Page
instância:class PagesController { protected $page; function __construct(Page $page) { $this->page = $page; } }
O Laravel irá resolver automaticamente a dependência e instanciar seu controlador com a
Page
instância que você vinculou em seu middleware.fonte
Em laravel> = 5 você pode usar
$request->merge
no middleware:public function handle($request, Closure $next) { $request->merge(array("myVar" => "1234")); return $next($request); }
E no controlador:
public function index(Request $request) { $myVar = $request->instance()->query('myVar'); ... }
fonte
Request::instance()
acessaria estaticamente, em vez de usar$request
?Laravel 5.7
// in Middleware register instance app()->instance('myObj', $myObj);
e
// to get in controller just use the resolve helper $myObj = resolve('myObj');
fonte
Conforme mencionado em um dos comentários acima para laravel 5.3.x
$request->attributes->add(['key => 'value'] );
Não funciona. Mas definir a variável assim no middleware funciona
$request->attributes->set('key', 'value');
Eu poderia buscar os dados usando isso no meu controlador
$request->get('key');
fonte
Tenho certeza que se fosse possível passar dados de um middleware para um controlador então estaria na documentação do Laravel.
Ter um olhar para isso e isso , pode ajudar.
Resumindo, você pode carregar seus dados no objeto de solicitação que está sendo passado para o middleware. A fachada de autenticação do Laravel também faz isso.
Portanto, em seu middleware, você pode ter:
$request->myAttribute = "myValue";
fonte
É muito simples:
Aqui está o código de middleware:
public function handle($request, Closure $next) { $request->merge(array("customVar" => "abcde")); return $next($request); }
e aqui está o código do controlador:
fonte
Se o seu site tem páginas cms que estão sendo buscadas no banco de dados e deseja mostrar seus títulos no bloco de cabeçalho e rodapé em todas as páginas do aplicativo laravel, use middleware. Escreva o código abaixo em seu middleware:
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); }
Em seguida, vá para header.blade.php e footer.blade.php e escreva o código abaixo para adicionar links de páginas 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>
Muito obrigado a todos e aproveitem o código :)
fonte
eu não falo inglês, então ... desculpe por possíveis erros.
Você pode usar a ligação IoC para isso. Em seu middleware, você pode fazer isso para vincular a instância $ page:
\App::instance('mi_page_var', $page);
Depois, em seu controlador, você chama essa instância:
$page = \App::make('mi_page_var');
O App :: instance não reinstala a classe, em vez disso retorna a vinculação anterior da instância.
fonte
Consegui adicionar valores ao objeto Request com:
$request->attributes->set('key', 'value');
e recuperá-los posteriormente com:
$request->attributes->get('key');
Isso é possível porque laravels Request estende Symfonys Request que tem o atributo " $ attribute " do tipo ParameterBag que se destina a manter parâmetros personalizados .
Eu acho que essa deveria ser a melhor prática para passar dados para middleware, controladores ou qualquer outro lugar onde seja possível acessar o objeto-solicitação.
Testado com Laravel 5.6 , mas provavelmente também funcionando com outras versões.
fonte
$request
é o array para que possamos apenas adicionar valor e chave ao array e obter o$request
com esta chave no controlador.$request['id'] = $id;
fonte