Laravel route Action not defined - php

I am having trouble with Laravel routes. I'm trying to redirect to a controller after some middleware in the routes. But there is always this error.
The error is:
InvalidArgumentException in UrlGenerator.php line 558: Action
App\Http\Controllers\DashboardController#index not defined.
The route code is:
Route::get('/dashboard', ['middleware' => 'auth', function() {
return Redirect::action('DashboardController#index', array('user' => \Auth::user()));
}]);
The controller:
class DashboardController extends Controller
{
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
return view('dashboard')->with('user', \Auth::user());
}
}
But the above code actually works (so I guess that the controller actually works):
Route::get('/testdashboard', [
'uses' => 'DashboardController#index'
]);
So what is the problem? What is a valid route action?

This is might a better way to do it, change from
Route::get('/dashboard', ['middleware' => 'auth', function() {
return Redirect::action('DashboardController#index',
array('user' => \Auth::user()));
}]);
to
Route::get('/', [
'middleware' => 'auth',
'uses' => 'DashboardController#index'
]);

This is rather a comment than a post, but I can't send it at this time. I don't undestand why do you pass parameter (\Auth:user()) to a method that doesn't require it (but it's correct when you do it for the View).
Anyways I suggest you to work on your Middleware
public function handle($request, Closure $next)
{
if (Auth::check()) {
return redirect(...);
} else {
return redirect(...);
}
}

Use this route in place of your route and upgrade your Laravel Project to Laravel 8:
Route::middleware(['auth:sanctum', 'verified'])->group(function () {
Route::get('/dashboard', 'DashboardController#index')->name('daskboard');
});

Related

Laravel custom Authentication: Route [login] not defined

I created a custom authentication for my Laravel app following that tutorial: https://medium.com/#nasrulhazim/laravel-using-different-table-and-guard-for-login-bc426d067901
I adapted it to my needs but I didn't have to change much.
In the end, when I try to go the the /home route, but it says: "Route [login] not defined."
My guess is that a default behavior of the authentication call the login route instead of the /fidelite/login I've created.
Here is my provider:
fidelite' => [
'driver' => 'eloquent',
'model' => App\Fidelite::class,
],
And the guard
'fidelite' => [
'redirectTo' => 'fidelite.home',
'driver' => 'session',
'provider' => 'fidelite',
],
The routes defined in the web.php file
Route::prefix('fidelite')
->as('fidelite.')
->group(function() {
Route::get('/home', 'Home\FideliteHomeController#index')->name('home');
Route::namespace('Auth\Login')
->group(function() {
Route::get('login', 'FideliteController#showLoginForm')->name('login');
Route::post('login', 'FideliteController#login')->name('login');
Route::post('logout', 'FideliteController#logout')->name('logout');
Route::get('register', 'FideliteController#showRegisterForm')->name('register');
});
});
Basically, there is two controllers; the first one, FideliteController adds the middleware and show the needed forms to login / register
class FideliteController extends DefaultLoginController
{
protected $redirectTo = '/fidelite/home';
public function __construct()
{
$this->middleware('guest:fidelite')->except('logout');
}
public function showLoginForm()
{
return view('auth.login.fidelite');
}
public function showRegisterForm()
{
return view('auth.compte');
}
public function username()
{
return 'email';
}
protected function guard()
{
return Auth::guard('fidelite');
}
}
And the other one returns the /fidelite/home page when the user is logged
class FideliteHomeController extends Controller
{
public function __construct()
{
$this->middleware('auth:fidelite');
}
public function index()
{
return view('home.fidelite');
}
}
There is something I missing, but what ?
Many thanks for your help and time...
Found it ! Thanks to the Alpha whom helps me find the problem !
The problem was that the middleware I was using (Authenticate.php) was redirecting to the route('login') instead of the custom route I needed.
You are duplicating the login name route. change the name of login to any specific name that properly define your route behavior.

Laravel, add gate to see if user has access

I have got a table with my permissions, I want to be able to setup a route like below so that I check the logged in users permissions and see if they have got access to the edit_users page for example.
Route::group([ 'prefix' => 'users', 'middleware' => 'can:access,edit_users' ], static function() {
I have added the following Gate, where I would do my query and check, however $permission is null...
public function boot()
{
$this->registerPolicies();
Gate::define('access', static function ($user, $permission) {
dd($user, $permission);
});
}
How would I go about doing this? As I don't want to hard-code all the permissions into gates!
The default middleware passes a route parameter as the second argument. I think what you'll need to do in this case is write your own middleware that takes a string as the argument, then do your check manually.
namespace App\Http\Middleware;
use Closure;
class HasPermission {
public function handle($request, Closure $next, $permission)
{
if($request->user()->can('access', $permission)) {
return $next($request);
}
return redirect()->back();
}
}
Then register your new middleware in the kernel file
'hasPermission' => \App\Http\Middleware\HasPermission::class
Then you can use your new middleware instead of the can middleware in your route.
Route::group([ 'prefix' => 'users', 'middleware' => 'hasPermission:edit_users' ], function() {});

Apply Middleware to all routes except `setup/*` in Laravel 5.4

I'm experimenting with Middleware in my Laravel application. I currently have it set up to run on every route for an authenticated user, however, I want it to ignore any requests that begin with the setup URI.
Here is what my CheckOnboarding middleware method looks like:
public function handle($request, Closure $next)
{
/**
* Check to see if the user has completed the onboarding, if not redirect.
* Also checks that the requested URI isn't the setup route to ensure there isn't a redirect loop.
*/
if ($request->user()->onboarding_complete == false && $request->path() != 'setup') {
return redirect('setup');
} else {
return $next($request);
}
}
This is being used in my routes like this:
Route::group(['middleware' => ['auth','checkOnboarding']], function () {
Route::get('/home', 'HomeController#index');
Route::get('/account', 'AccountController#index');
Route::group(['prefix' => 'setup'], function () {
Route::get('/', 'OnboardingController#index')->name('setup');
Route::post('/settings', 'SettingsController#store');
});
});
Now, if I go to /home or /account I get redirected to /setup as you would expect. This originally caused a redirect loop error hence why & $request->path() != 'setup' is in the Middleware.
I feel like this is a really clunky way of doing it, and obviously doesn't match anything after setup like the setup/settings route I have created.
Is there a better way to have this Middleware run on all routes for a user, but also set certain routes that should be exempt from this check?
There's nothing wrong with what you're doing, however, I would suggest splitting your route groups up instead i.e.:
Route::group(['middleware' => ['auth', 'checkOnboarding']], function () {
Route::get('/home', 'HomeController#index');
Route::get('/account', 'AccountController#index');
});
Route::group(['prefix' => 'setup', 'middleware' => 'auth'], function () {
Route::get('/', 'OnboardingController#index')->name('setup');
Route::post('/settings', 'SettingsController#store');
});
Alternatively, have a parent group for your auth:
Route::group(['middleware' => 'auth'], function () {
Route::group(['middleware' => 'checkOnboarding'], function () {
Route::get('/home', 'HomeController#index');
Route::get('/account', 'AccountController#index');
});
Route::group(['prefix' => 'setup'], function () {
Route::get('/', 'OnboardingController#index')->name('setup');
Route::post('/settings', 'SettingsController#store');
});
});
This will also mean you can remove the extra condition in your middleware:
/**
* Check to see if the user has completed the onboarding, if not redirect.
* Also checks that the requested URI isn't the setup route to ensure there isn't a redirect loop.
*/
return $request->user()->onboarding_complete ? $next($request) : redirect('setup');
Hope this helps!
You can utilize the Controller class for this with pretty spectacular results.
If you create a __construct function inside of HTTP/Controllers/Controller.php then you can declare middleware to run on every controller action and even declare exceptions as needed.
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function __construct(){
$this->middleware('auth',['except' => ['login','setup','setupSomethingElse']]);
}
}
Be careful not to put any of the standard index, store, update, destroy functions in the exception or you'll open up potential security issues.
Since Laravel 7.7 you can use excluded_middleware like this:
Route::group(['middleware' => ['auth','checkOnboarding']], function () {
Route::get('/home', 'HomeController#index');
Route::get('/account', 'AccountController#index');
Route::group([
'prefix' => 'setup',
'excluded_middleware' => ['checkOnboarding'],
], function () {
Route::get('/', 'OnboardingController#index')->name('setup');
Route::post('/settings', 'SettingsController#store');
});
});
In Laravel 8.x you can also use the withoutMiddleware() method to exclude one or many route to a group middleware
Route::middleware('auth')->group(function () {
Route::get('/edit/{id}',[ProgramController::class, 'edit'])->name('edit');
Route::get('/public', [ProgramController::class, 'public'])
->name('public')->withoutMiddleware(['auth']);
});
Check also the official doc: Here
There are 2 ways to go over this problem
Try screening your routes in routes file web.php or api.php
skip routes in middleware
In case of global middleware (middleware that you want to run before all routes), you should go with skipping routes in middleware.
For example:
//add an array of routes to skip santize check
protected $openRoutes = [
'setup/*',
];
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(!in_array($request->path(), $this->openRoutes)){
//middleware code or call of function
}
return $next($request);
}
For other middleware, you can easily skip in routes file and group routes based on your middleware.
For example:
Route::group(['middleware' => 'checkOnboarding'], function () {
Route::get('/home', 'HomeController#index');
Route::get('/account', 'AccountController#index');
});
Route::group(['prefix' => 'setup'], function () {
Route::get('/', 'OnboardingController#index')->name('setup');
Route::post('/settings', 'SettingsController#store');
});
Routes on which you dont want the middleware to run , simply put them outside of the function:
//here register routes on which you dont want the middleware: checkOnboarding
Route::group(['middleware' => ['auth','checkOnboarding']], function () {
//routes on which you want the middleware
});

Laravel 5.2 blade views not being rendered, even though the foot view shows. Internal server error

I have tried every thing and even checked the whole of stack overflow. My Laravel blade views are not being rendered. There is an internal server error. the default root view shows but the rest aren't. The permissions are fine, currently 777 on all folders and files. I'm really stuck. What could it be?
Route::group(['middleware' => ['web']], function () {
//Routes using UserController
Route::get('/welcome1ab', [
'uses'=>'UserController#getWelcome1ab',
'as' => 'welcome1ab',
]);
Route::post('/welcome1ab', [
'uses'=>'UserController#postWelcome1ab',
'as' => 'register1',
]);
Route::get('/', [
'uses'=>'UserController#getWelcome',
'as' => 'welcome',
]);
Route::get('/welcome1a', [
'uses'=>'UserController#getWelcome1a',
'as' => 'welcome1a',
]);
Controller functions:
class UserController extends Controller{
public function getWelcome1ab(Request $request){
return view('welcome1ab');
}
public function getWelcome1a(Request $request){
return view('welcome1a');
}
public function getWelcome1(Request $request){
return view('welcome1');
}
public function getWelcome(Request $request){
return view('welcome');
}

Laravel 5 - before auth not working

Today I tried to make some changes to my application. I tried to pass all pages through authentication first. I tried one of the answer on this site. But that didn't help. Please help. Here's my code in routes.php
<?php
Route::get('/', function(){
return view('homepage');
});
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
Route::group(['before' => 'auth'], function () {
Route::get('home', function(){
return \Redirect::to('twitter');
});
Route::get('twitter', 'HomeController#index');
.
.
.
.
});
There are several routes in my file. But only twitter route works.
In laravel 5,
['before' => 'auth']
is deprecated. But instead, I should use
['middleware' => 'auth']
Laravel5 has middlewares instead of filter. I assume you are trying to show certain page to only guests and for that we have a guest middleware already built in.
Route::group(['middleware' => 'guest'], function () {
Route::get('home', function(){
return \Redirect::to('twitter');
});
Route::get('twitter', 'HomeController#index');
});
you may also use middlewares on particular functions of your controller if you want, e.g
class MyController extends Controller {
public function __construct()
{
//to add auth middleware only on update method
$this->middleware('auth', ['only' => 'update'])
//to add auth middleware on all fucntions expcept login
$this->middleware('auth', ['except' => 'login'])
}
}

Categories