How to resolve a "MethodNotAllowedHttpException" error in Laravel? - laravel

I am developing a passport API in Laravel. I am getting a "MethodNotAllowedHttpException".
I don't get any idea, what fix do I have to do.
<?php
use Illuminate\Http\Request;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::post('register', 'Api\Auth\RegisterController#register');
Route::post('login', 'Api\Auth\LoginController#login');
Route::post('refresh', 'Api\Auth\LoginController#refresh');
Route::middleware('auth:api')->group(function () {
Route::post('logout', 'Api\Auth\LoginController#logout');
Route::get('posts', 'Api\PostController#index');
});

this error can occur due to request type (GET / POST) mismatch in your route and the request type in your API call or form tag in your view
check if the request type matched in your route file and in your APIcall

See, you use 'post' method in your route:
Route::post('register', 'Api\Auth\RegisterController#register');
And the browser's default is 'get'. Are you trying to show a registration form or you are submitting a form to that route.
Either you should change that route to GET or create another route to show the page, then submit the form as post to the intended route

Related

Route type delete does not work in Laravel

I have following route and works
Route::post("delete-role", [RoleApiController::class, "Remove"]);
I tested it through postman like this
http://localhost/delete-role?api_token=hcvhjbhjb12khjbjhc876
Now, if I change above route and convert to type delete..
Route::delete("delete-role/{role_id}", [RoleApiController::class, "Remove"]);
it does not work. I get below error. It seems to be the reason that the api_token is missing.
I get same error when trying to update route like below
Route::delete("delete-role/{role_id}/{api_token}", [RoleApiController::class, "Remove"]);
You have to set header of your request as:
"Accept": "application/json"
in postman.
If you don't set the required header for api, Laravel Passport can't understand request as an API client and so it will redirect to a /login page for the web.
Or you can set a middleware to check it in code:
public function handle($request, Closure $next)
{
if(!in_array($request->headers->get('accept'), ['application/json', 'Application/Json']))
return response()->json(['message' => 'Unauthenticated.'], 401);
return $next($request);
}
You have an incomplete details. but I see few issues here.
You seem to be using web routes for your API requests which is a bad set-up
You do not have a route with login name.
based on the error you posted, your request seems to successfully destroyed the token and logged you out, then called the middleware App\Http\Middleware\Authenticate which supposed to redirect your request to login route which does not exist and the reason you are getting that error.
You can see from that Authenticate middleware it will supposed to redirect you to login route for unauthenticated request. thats why you need to use the api routes so you can handle the response manually
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}
Also, I'm not so sure about this, but the reason you are not getting the same issue with your POST request is probably because your POST request does not call the Authenticate middleware or whatever in your routes file or class function that calls the authenticate middleware.
But again, just use api routes if you don't want un-authenticated request to automatically redirect your request to login routes which does not exist in your application
The problem is that he doesn't define route ('login'),
add in Exceptions/Handler.php
$this->renderable(function (AuthenticationException $e, $request) {
if ($request->is('api/*')) {
return response()->json(['meassge' => 'Unauthenticated']);
}
});
Then you should use Passport Or Sanctum for auth with Api,
Continue from here https://laravel.com/docs/9.x/passport
Probably, this thread could help you. Route [login] not defined
(OR)
You need to setup auth scaffolding to get login route defined.
Important: your project will be overridden if you setup auth scaffold.
So, I would only recommend doing this if it is a new project or a testing app.
See this for detail doc but install Laravel Breeze would be suffice.
It Appears you have called route('login') without having defined it in your routes, Please remove route('login') from your code or define it in your routes. eg::
Route::get('login', [YourController::class, 'methodName'])->name('login');

How to use web route for auth controller in laravel 8

I wanted to use multi step registration. But got trouble at route. This is my first route.
Route::get('register-step2', [Auth\RegisterStep2Controller::class,'showForm']);
Route::post('register-step2', [Auth\RegisterStep2Controller::class, 'postForm'])
->name('register.step2');
but it got error
Target class [Auth\RegisterStep2Controller] does not exist.
so I change and mix with this code.
Route::group(['middleware' => ['auth']], function() {
Route::resource('roles', RoleController::class);
Route::resource('users', UserController::class);
Route::resource('products', ProductController::class);
Route::get('register-step2', [RegisterStep2Controller::class,'showForm']);
Route::post('register-step2', [RegisterStep2Controller::class, 'postForm'])
->name('register.step2');
But it says that: Target class [RegisterStep2Controller] does not exist.
How to use controller in auth in laravel 8 or 9.
I wanted to use registerstep2 controller in auth folder.
Make changes in your routes/web.php as per below
use App\Http\Controllers\Auth\RegisterStep2Controller;
...
Route::get('register-step2', [RegisterStep2Controller::class,'showForm']);
Route::post('register-step2', [RegisterStep2Controller::class, 'postForm'])->name('register.step2');

In RouteAction.php line 84: Invalid route action

When I create a controller in laravel 5.4 I get this error
In RouteAction.php line 84:
Invalid route action:
[App\Http\Controllers\Admin\DashboardController].
I do not create Admin/DashboardController. Still makes a errors
web.php
Route::group(['namespace' => 'Admin', 'middleware' => ['auth:web', 'CheckAdmin'], 'prefix' => 'admin'],function (){
$this->resource('authorities', 'AuthoritiesController');
$this->resource('complaints', 'ComplaintsController');
$this->resource('schools-list', 'SchoolsListController');
$this->resource('inspection-failed', 'InspectionFailedController');
$this->resource('inspection-register', 'InspectionRegisterController');
$this->resource('inspection-results', 'InspectionResultsController');
$this->resource('inspectors-list', 'InspectionListController');
$this->resource('investigators', 'InvestigatorsController');
$this->resource('notification-infringement', 'NotificationInfringementController');
$this->resource('system-experts', 'SystemExpertsController');
$this->resource('submit-information', 'SubmitInformationController');
$this->resource('primary-committee-meeting', 'PrimaryCommitteeMeetingController');
$this->resource('list-violations-school', 'ListViolationsSchoolController');
$this->resource('announcing', 'AnnouncingController');
$this->resource('display-vote', 'DisplayVoteController');
$this->resource('announcing-supervisory-vote', 'AnnouncingSupervisoryVoteController');
$this->resource('supervisory-board-vote', 'SupervisoryBoardVoteController');
$this->resource('defense', 'DefenseController');
$this->resource('votiing-supervisory-board', 'VotiingSupervisoryBoardController');
$this->get('dashboard', 'DashboardController');
});
Because it is invalid. As you're using GET route, you must specify method name(unless you used ::resource):
$this->get('dashboard', 'DashboardController#methodName');
If you are using laravel 8 you need to add your controller and method name inside the array, otherwise, it will throw an error.
Route::get('/projects', User\ProjectController::class, 'index')->name('user.projects');
TO
Route::get('/projects', [User\ProjectController::class, 'index'])->name('user.projects');
I also face a similar problem:
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', 'Frontend\FrontendController#index')->name('home');
Route::get('/post', 'Frontend\FrontendController#post')->name('post');
Route::get('/contact', 'Frontend\FrontendController#contact')->name('contact_us');
Route::group(['prefix' => 'admin'], function () {
Route::get('/create', 'Backend\BackendController#index');
//User Route
Route::get('/registration', '');
});
And I just remove the Route::get('/registration', ''); and it's work for me :)
try removes route cache file by
php artisan route:clear
Those who are new to Laravel or learning use
Route::resource('resource_name','controller_name')
to avoid this kind of error when you type:
php artisan route:list
In cmd or any other command line.
i think its because of :: before the class name instead use #
Route::get('/about','App\Http\Controllers\DemoController::about'); (Not working gives an error)
Route::get('/about','App\Http\Controllers\DemoController#about'); (But this statement works)
I hit the same issue but with a different cause. So I'm documenting here just in case someone else hits the same cause.
Specifically if you are using a Single Action Controller (ie: with __invoke), if you haven't added or omitted the correct use Laravel will hide the missing controller with "Invalid route action: [XController]."
This will fail
<?php
use Illuminate\Support\Facades\Route;
Route::post('/order', XController::class);
This will pass
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\XController;
Route::post('/order', XController::class);
I think its a bit unfortunate that Laravel masks the underlying issue, but I think it only applies to invokable controllers, even though its a silly mistake on my behalf.
Lastly if you set the route like below:
Route::post('example', PostController::class);
You should have an __invoke method in your controller.
For recent versions of laravel, try adding square brackets like
Route::post('login',[AuthController::class,'login'])
instead of
Route::post('login', AuthController::class,'login']).
The second route will throw the error Invalid route action: since you are not invoking the route. Another alternative you can add an __invoke function on your controller if you are using the second route as mentioned above.

Laravel route group page redirects to home

I have installed Laravel and set up authentication and I have also created a route group like this:
// users that want to access test route should be logged in.
Route::group(['middleware' => ['web', 'auth']], function () {
Route::get('first', function () {
return 'first';
});
});
The problem is when I access the route like this:
http://localhost/first
I can see my "first" message, but when I refresh the same page laravel redirects me to:
http://localhost/home
I could not solve this and I have moved my first route out of the route group now everything is working well. If I keep it in the route group with auth & web middlewares it is not working.
Try to remove web middleware if you're using 5.2.27 and higher.

Laravel - Route::resource vs Route::controller

I read the docs on the Laravel website, Stack Overflow, and Google but still don't understand the difference between Route::resource and Route::controller.
One of the answers said Route::resource was for crud. However, with Route::controller we can accomplish the same thing as with Route::resource and we can specify only the needed actions.
They appear to be like siblings:
Route::controller('post','PostController');
Route::resource('post','PostController');
How we can choose what to use? What is good practice?
RESTful Resource controller
A RESTful resource controller sets up some default routes for you and even names them.
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
And you would set up your controller something like this (actions = methods)
class UsersController extends BaseController {
public function index() {}
public function show($id) {}
public function store() {}
}
You can also choose what actions are included or excluded like this:
Route::resource('users', 'UsersController', [
'only' => ['index', 'show']
]);
Route::resource('monkeys', 'MonkeysController', [
'except' => ['edit', 'create']
]);
API Resource controller
Laravel 5.5 added another method for dealing with routes for resource controllers. API Resource Controller acts exactly like shown above, but does not register create and edit routes. It is meant to be used for ease of mapping routes used in RESTful APIs - where you typically do not have any kind of data located in create nor edit methods.
Route::apiResource('users', 'UsersController');
RESTful Resource Controller documentation
Implicit controller
An Implicit controller is more flexible. You get routed to your controller methods based on the HTTP request type and name. However, you don't have route names defined for you and it will catch all subfolders for the same route.
Route::controller('users', 'UserController');
Would lead you to set up the controller with a sort of RESTful naming scheme:
class UserController extends BaseController {
public function getIndex()
{
// GET request to index
}
public function getShow($id)
{
// get request to 'users/show/{id}'
}
public function postStore()
{
// POST request to 'users/store'
}
}
Implicit Controller documentation
It is good practice to use what you need, as per your preference. I personally don't like the Implicit controllers, because they can be messy, don't provide names and can be confusing when using php artisan routes. I typically use RESTful Resource controllers in combination with explicit routes.
For route controller method we have to define only one route. In get or post method we have to define the route separately.
And the resources method is used to creates multiple routes to handle a variety of Restful actions.
Here the Laravel documentation about this.
i'm using Laravel 8 in my project
and in my route file web.php
i add this route
Route::controller(SitesController::class)->group(function() {
Route::get('index', 'index')->name('index');
}
in the Route::controller group we pass controller name we will use
inside the group we define the route we'll use as below syntax
Route::method-used('prefix in the URL', 'function used in the specified controller ')->name(); if the name not used in your code just delete it

Resources