I still have some trouble understanding all the changes from Laravel 4.2 to 5.0.
I have already managed to import all my models, controllers, config etc. I have namespaced almost everything but one thing that I can't seem to manage is to transform this code from 4.2 app\filters.php to my new 5.0 application.
Here's part of the code with some added explanations below that I'm having problems with. The following code was added so that we can conveniently ask for the permissions inside a group for all the actions/visible fields for the current user.
if(App::make('Authflag', $usergroup->id)->can(GroupPermissions::EDIT_MEMBERS)) ...
Code from 4.2:
App::before(function($request) {
App::instance('Authflags', array());
App::bind('Authflag', function($app, $param) {
$authflags = App::make('Authflags');
if(isset($authflags[$param]))
{
return $authflags[$param];
}
// Calculate generate flag value
$authflags[$param] = $authflag;
App::instance('Authflags', $authflags);
return $authflag;
});
});
Explanation:
instance Authflags contains group_id => permissionObject
Code explanation:
Get the Authflags array instance
If we already have the needed permissionObject return it
Else generate/calculate/request the permissionObject
Update the Authflags instance
Return the created permissionObject
But whatever I try I keep getting the ReflectionException in Container.php line 776: Class Authflag does not exist.
I tried to create a contract and a service and set a binding inside the AppServiceProvider. But I'm pretty sure I was doing a completely wrong/different thing.
I tried to just copy this code with some modifications inside the AppServiceProvder. But It just seemed wrong and didn't work.
(Come to think of it the whole code should have probably been inside the start/global.php)
How can I port this code to Laravel 5.0?
You have to use a middleware "encapsulation". Here is an example, that will show where you would have to put your custom before and after parts of your app.
use Closure;
class ChangeCookieLifetime {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
//anything put here will be run BEFORE your app
$response = $next($request);
//anything put here will be run AFTER your app
return $response
}
}
In your particular case iw dould like this:
use Closure;
class ChangeCookieLifetime {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
App::instance('Authflags', array());
App::bind('Authflag', function($app, $param) {
$authflags = App::make('Authflags');
if(isset($authflags[$param]))
{
return $authflags[$param];
}
// Calculate generate flag value
$authflags[$param] = $authflag;
App::instance('Authflags', $authflags);
return $authflag;
});
$response = $next($request);
//anything put here will be run AFTER your app
return $response
}
}
Although I can't promise that the parts I inserted will work, this is the direct "translation" from Laravel 4.2 to Laravel 5
Related
I wrote a very simple middleware, like this:
class CheckToken
{
private $token='xxx';
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (! $request->tokenz == $this->token) {
return response('Unauthorized.', 401);
}
return $next($request);
}
}
Then I register it trough kernel.php, like this:
protected $routeMiddleware = [
.....
'CheckToken' => \App\Http\Middleware\CheckToken::class,
];
then Ive a very simple function in a controller guarded by this controller:
public function __construct()
{
$this->middleware('CheckToken');
}
public function push()
{
return view('home');
}
Now starts what is not clear to me:
how can i "protect" my page using this simple method?
I've tried to put this tag on the header of page but it seems to not works, maybe im in the wrong path:
<meta name="tokenz" content="xxx">
I put it even in the body but no results.
what ive misunderstood?
I believe you need to add the middleware call to the actual route:
use App\Http\Middleware\CheckAge;
Route::get('admin/profile', function () {
//
})->middleware(CheckAge::class);
This was extracted from the Laravel 5.7 documentation: Middleware - Assigning Middleware to Routes
sorry i can't create a comment. but just want to help.
does $request passed a tokenz?
you can use ?tokenz=blablabla
or you can change your method to get the tokenz
I have problem that using multiple parameters in my Route::middleware isn't working for me. I am trying to assign a specific route only accessible for a superuser and admin role.
When I just use:
role:superuser
it works fine, but when I add a second parameter like:
role:superuser,admin
it fails when I assign myself the admin role but still works for the superuser role.
I am confused so any help would be appreciated!
Here is my RoleMiddleware:
namespace App\Http\Middleware;
use Closure;
class RoleMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $roles
* #return mixed
*/
public function handle($request, Closure $next, ...$roles)
{
$user = $request->user();
if ($user && $user->isSuperuser($roles)) {
return $next($request);
}
return redirect('/home')->withError('U heeft niet de juiste rechten!');
}
}
Here is my isSuperuser method in my User model:
public function isSuperuser(...$roles)
{
if ($roles) {
return $this->roles == $roles;
}
return $this->roles;
}
Last but not least my routes/web code for the middleware:
Route::get('/users', 'UsersController#index')->middleware(['role:superuser,admin']);
Btw: the method is called 'isSuperuser' but that's just a name. It also has to accept the admin role at some point.
use | instead of , like this:
Route::get('/users', 'UsersController#index')->middleware(['role:superuser|admin']);
Generally speaking this should be a rather simple problem. IT should be very similar to the following question on Stack Overflow
But seeing as it has been two years, maybe some of the syntax has changed.
All I want to do is pass a variable from the middleware to the controller, so I'm not duplicating mysql queries.
Here is my middleware:
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$id = $request->user()->id;
$rr = $request->user()->isSuperAdmin();
if ($request->user()->isSuperAdmin()) {
$request->merge(['group' => 123]);
return $next($request);
}
echo "not admin";
}
}
So the middleware works fine and if I DD($request) on the middleware I see my group => 123 on the page. (Right now it's 123 for the sake of simplicity.)
So I want to pass it to my AdminController:
<?php
namespace SleepingOwl\Admin\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use SleepingOwl\Admin\Form\FormElements;
use SleepingOwl\Admin\Form\Columns\Column;
use SleepingOwl\Admin\Display\DisplayTable;
use Illuminate\Contracts\Support\Renderable;
use SleepingOwl\Admin\Display\DisplayTabbed;
use Illuminate\Validation\ValidationException;
use SleepingOwl\Admin\Contracts\AdminInterface;
use SleepingOwl\Admin\Model\ModelConfiguration;
use Illuminate\Contracts\Foundation\Application;
use SleepingOwl\Admin\Contracts\Form\FormInterface;
use SleepingOwl\Admin\Contracts\ModelConfigurationInterface;
use SleepingOwl\Admin\Contracts\Display\ColumnEditableInterface;
class AdminController extends Controller
{
/**
* #var \DaveJamesMiller\Breadcrumbs\Manager
*/
protected $breadcrumbs;
/**
* #var AdminInterface
*/
protected $admin;
/**
* #var
*/
private $parentBreadcrumb = 'home';
/**
* #var Application
*/
public $app;
/**
* AdminController constructor.
*
* #param Request $request
* #param AdminInterface $admin
* #param Application $application
*/
public function __construct(Request $request, AdminInterface $admin, Application $application)
{
$this->middleware('CheckRole');
So as you can see I call the middleware on this constructor. After calling it I should be able do something like:
$request->get('group'); or $request->group;
After trying for quite a while nothing seems to be working and I keep getting a null value. Fundamentally, this shouldn't be terribly difficult, but I seem to have my syntax off or not using the right name spaces?
Instead of this code line:
$request->merge(['group' => 123]);
You can try:
$request->request->add(['group' => 123]);
What this code line will do is if a parameter named group exists in the $request it will overwrite with the new value, otherwise it will add a new parameter group to the $request
In your controller, you can get the value of group parameter as:
$group = $request->group; OR $group = $request->input('group');
Thanks to the joint help of #Rahul-Gupta and #shock_gone_wild. It was a joint effort I guess.
The first issue is that I'm using sleepingOwl laravel boilerplate. Probably not the best idea for someone new to Laravel. (not new to MVC / PHP).
Based on #shock_gone_wild comment, decide move my test over to a simple controller, and not the sleeping owl nonsense. (they have a lot of code.) Anyways, I believe that helped. I did leave the middleware in the constructor because I didn't apply the middleware to the routes.
Then I followed #Rahul-Gupta syntax.
So here is final result, hopefully this will save someone sometime someday...
namespace App\Http\Middleware;
use Closure;
class CheckRole {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next) {
if ($request->user()->isSuperAdmin()) {
$request->request->add(['group' => 123]);
return $next($request);
} else {
echo "not admin";
}
}
}
Then here is the simple controller.
use Illuminate\Http\Request;
use App\task;
use App\User;
use App\HasRoles;
class TaskController extends Controller {
public function __construct() {
// constructor code...
$this->middleware('auth');
$this->middleware('CheckRole');
}
public function index(Request $request) {
$group = $request->input('group');
echo "---->" . $group;
$tasks = Task::all();
return view('test_task', compact('tasks'));
}
}
I request api to check user , and the backurl will add a query param token like this :
www.test.com?store_id=2&token = 123
I want to show this
www.test.com?store_id=2
I handle it in middleware , I wish there is a mothod to remove token before return $next($request)
but I didn't find the method. And I can't just use some method to delte this params and redirect , it will make a redirect loop.
if there is no better method, maybe I will create a new method in LoginController to remove token and redirect to where the page I from.
You can have some sort of global middleware:
class RedirectIfTokenInRequest {
public function handle($request,$next) {
if ($request->token) {
return redirect()->to(url()->current().'?'.http_build_query($request->except("token")));
}
return $next($request);
}
}
This will just redirect if there's a token parameter there. If you need to store it somehow you can use session(["token" => $request->token]); to store it before your redirect.
Middleware is the best option. You can attach middleware class, to routes, in web or to single method. My middleware proposal:
namespace App\Http\Middleware;
use Closure;
class ClearFromAttributes
{
/**
* Remove some attributes which makes some confusion.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($request->get('unwanted_param')) {
return $this->removeFromQueryAndRedirect($request, 'unwanted_param');
}
if ($request->has('second_unwanted')) {
return $this->removeFromQueryAndRedirect($request, 'second_unwanted');
}
return $next($request);
}
/**
* Remove and make redirection.
*
* #param \Illuminate\Http\Request $request
* #param string $parameter
* #return mixed
*/
public function removeFromQueryAndRedirect($request, string $parameter)
{
$request->query->remove($parameter);
return redirect()->to($request->fullUrlWithQuery([]));
}
}
Of course, I have more complicated conditions in the handle method, in reality.
Usage in controller constructor without touching Kernel file:
$this->middleware(ClearFromAttributes::class)->only('index');
This is a nice option, for single usage.
Laravel 7
You can remove parameter(s) from url by passing null to fullUrlWithQuery function like below:
request()->fullUrlWithQuery(['token ' => null])
Laravel 8 added fullUrlWithoutQuery($keys)
class RemoveParameterFromRequest
{
public function handle(Request $request, Closure $next)
{
if ($request->has('unwanted_parameter')) {
return redirect()->to($request->fullUrlWithoutQuery('unwanted_parameter'));
}
return $next($request);
}
}
I'm quite new to Laravel and have been stumped on a problem for 2 days - I'd be grateful for some guidance.
I'm using the default out-of-the-box User authentication system with Laravel 5.3. A new user is created automatically behind the scenes by an existing Admin user - I will in time hide the user registration page. I have also successfully set up middleware to check if a user is newly registered (by looking for a null 'last_logged_in_date' that I've added to the migration).
All I want to happen is for a new registered user to be redirected to the password reset screen that ships with Laravel (again, in time I will create a dedicated page). I would like this to happen within the middleware file. So far, my middleware looks like this:
<?php
namespace App\Http\Middleware;
use Closure;
use App\Http\Controllers\Auth;
class CheckIfNewUser
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = $request->user();
if (! is_null($user->last_logged_in_date )) {
return $next($request);
}
// This is where I'm stuck!!!
}
}
I'm not sure what code to enter at the location indicated by the comments above. I've tried sendResetLinkEmail($request); etc and have imported what I though were the correct classes but I always end up with a Call to undefined function App\Http\Middleware\sendResetLinkEmail() message irregardless of what I 'use' at the top of my class.
Where am I going wrong? Thanks!
Well that happens because you have not defined your sendResetLinkEmail($request) function yet. You can do it like this, or you can create a new class with that and then call the class.
Call the trait SendsPasswordResetEmails and then access it with $this since traits are not classes and you cannot access their members directly.
<?php
namespace App\Http\Middleware;
use Closure;
use App\Http\Controllers\Auth;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class CheckIfNewUser
{
use SendsPasswordResetEmails;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = $request->user();
if (! is_null($user->last_logged_in_date )) {
return $next($request);
}
// This is where I'm stuck!!!
//EDIT
//return $this->SendsPasswordResetEmails->sendResetLinkEmail($request);
return $this->sendResetLinkEmail($request);
}
}