Laravel: Not picking up __invoke method? - php

Trying to use invokable controllers, but it seems to fail to find the __invoke method?
Invalid route action: [App\Http\Controllers\App\Http\Controllers\MainController].
It seems to be returning true on:
if (! method_exists($action, '__invoke')) {
throw new UnexpectedValueException("Invalid route action: [{$action}].");
}
Routes:
<?php
Route::get('/', \App\Http\Controllers\MainController::class);
MainController:
<?php
namespace App\Http\Controllers;
class MainController extends Controller
{
public function __invoke()
{
dd('main');
}
}

Laravel by default assumes that your controllers will be located at App\Http\Controllers\. So when you're adding the full path to your controller, Laravel will check it there, at App\Http\Controllers\App\Http\Controllers\MainController.
To solve it simply remove the namespace when you're registering the route, and register it like this:
Route::get('/', MainController::class);
Alternatively, you can stop this behavior by removing ->namespace($this->namespace) from mapWebRoutes() method on RouteServiceProvider class, which is located at App\Providers folder. Then you can register your routes like this:
Route::get('/', \App\Http\Controllers\MainController::class);

Alternatively, you can use:
use App\Http\Controllers\MainController;
Route::get('/', [MainController::class, '__invoke']);
In this case, the namespace provided in RouteServiceProvider won't be taken into account.
The advantage of this is that now your IDE will be able to reference the class usage and you can navigate by clicking on it.

The best answer that works for everyone is laravel documentation.
just use this at the top of your route(web.php) if (websiteController is the name of your controller)
use App\Http\Controllers\WebsiteController;
and define your route like this for your index page
Route::get('/', [WebsiteController::class, 'index']);
take note of the
[ ]

You have to create the crontoller with argument "--invokable"
php artisan make:controller YourController --invokable

Always Declare/Use in Top
use App\Http\Controllers\backend\DashboardController;
Then Use this way
Route::get('/dashboard', [DashboardController::class, 'dashboard'])->name('dashboard');
If have Auth and Use Group
Route::middleware([
'auth:sanctum',
config('jetstream.auth_session'),
'verified'
])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'dashboard'])->name('dashboard');
})

Change your route to:
Route::get('/', "MainController");

In my case I forget to set #action, so change your code from:
Route::get('admin/orders', 'Admin\OrderController')->name('admin.orders');
to:
Route::get('admin/orders', 'Admin\OrderController#index')->name('admin.orders');

you have mentioned get link, but you have not declared which method it should call.
Route::get('/', \App\Http\Controllers\MainController::class);// if you are importing lass like this you have to use resource instead of get.
you can solve this issue by two ways,
first way,
Route::get('/', '\App\Http\Controllers\MainController#index'); // you have to mention your method which you have mentioned in controller
another way is,
Route::resource('/', \App\Http\Controllers\MainController::class);
In, 2nd method laravel will automatically find which request and where should redirect.2nd option is prefered if you are using multiple method for the same route.

Route::resource('/', \App\Http\Controllers\MainController::class);
Use method 'resource'

Related

Is there any better way to write my Laravel Routes by avoiding namespace repeaters

I try to clean my code api.php in Laravel 9.
I'm not sure if there is a better way to avoid repeating controller namespace.
Here is my code:
Route::controller(App\Http\Controllers\Contacts\ContactController::class)->prefix('contacts')->group(function(){
Route::get('/', [App\Http\Controllers\Contacts\ContactController::class, 'index']);
});
Note : I want to groupe by Controller
You're half way there. Route::controller permits you to write your routes in the group like this:
Route::get('/', 'index');
i.e.
Route::controller(App\Http\Controllers\Contacts\ContactController::class)->prefix('contacts')->group(function(){
Route::get('/', 'index');
});
This will result in the index function of the group's controller being called.

Laravel Target class [App\Http\Controllers\App\Http\Controllers\ApiController] does not exist

For some reason, which is probably my fault, Laravel thinks it should be looking for the class ApiController in path: 'App\Http\Controllers\App\Http\Controllers', so... it doubles, but I have no idea why.
It's a brand new Laravel 6 project, I've created the ApiController with the make:controller artisan command and added a function, like this:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ApiController extends Controller
{
public function base() {
return 'This is a test function';
}
}
Then I've added a route to the api routes like this:
use App\Http\Controllers\ApiController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => '/v1', 'as' => 'api'], function () {
Route::get('/base', ['uses' => ApiController::class . '#base'])->name('base');
});
As you can see, I've even 'imported' the controller, but it just can't find it.
That's it, no other files or changes to the project. Also tried clearing route cache and dump-autoload, but that did not change anything.
In my case problew was, in RouteServiceProvider, in using routes Namespace
protected $namespace = 'App\Http\Controllers';
In Laravel 8 namespace was commented out, i remove namespace from chain, because my web routes not fully moved to Laravel 8 syntax and i need this namespace.
Route::prefix('api')
->middleware('api')
-̶>̶n̶a̶m̶e̶s̶p̶a̶c̶e̶(̶$̶t̶h̶i̶s̶-̶>̶n̶a̶m̶e̶s̶p̶a̶c̶e̶)̶
->group(base_path('routes/admin-api.php'));
If you wanna ::class reference in the router, it should be done like this.
Route::group(['prefix' => '/v1', 'as' => 'api'], function () {
Route::get('base', [ApiController::class, 'base'])->name('base');
});
This should work:
Route::group(['prefix' => '/v1', 'as' => 'api'], function () {
Route::get('base', 'ApiController#base')->name('base');
});
No need to add the "use", since controllers are referenced from the App/Controllers namespace, as you can corroborate on the RouteServiceProvider.
The syntax of your route is a combination of "old syntax" vs "new syntax"
What you are trying to achieve is:
Route::get('/base', [ApiController::class, 'base'])->name('base');
Either remove this line:
use App\Http\Controllers\ApiController;
or add a \ to the start:
use \App\Http\Controllers\ApiController;
In my case (Laravel 8 project), I needed a separate route for destroy, because deleting didn't use html form, so my web.php file is like:
use App\Http\Controllers\LocationController;
...
Route::resource('/locations', LocationController::class);
Route::get('/locations/destroy/{location}', [LocationController::class, 'destroy']);
But in that case if I put use App\Http\Controllers\LocationController the first line (Route::resource...) fails, if I remove it then the second line fails. So I removed use line and added App\Http\Controllers into the second line:
Route::resource('/locations', LocationController::class);
Route::get('/locations/destroy/{location}', [App\Http\Controllers\LocationController::class, 'destroy']);
So obviously Laravel doesn't automatically add App\Http\Controllers in the second form of Route.
I got this error when in resource controller description me pasted one from fresh project:
Route::resources([
'my_url' => LisseyDoruHisobotController:class,
..., //other controllers
]);
as being a recommended signature in Laravel 8 , but am currently busy on 7 or 6 version, where should be:
Route::resources([
'my_url' => 'path\to\LisseyDoruHisobotController',
..., //other controllers
]);
otherwize it will show doubled path
Laravel Target class [App\Http\Controllers\App\Http\Controllers\ ] does not exist

ReflectionException Class App\Http\Controllers\StaticPagesController#faq does not exist Laravel-5

I cloned this todstoychev/Laravel5Starter from Github and installed it.
After creating this StaticPagesController controller and updating my routes.php file. The controller does not seem to work. For some reason i keep getting the following error.
ReflectionException in ControllerInspector.php line 32:
Class App\Http\Controllers\StaticPagesController#faq does not exist
My routes.php file
<?php
// Admin routes
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function () {
Route::controller('permissions', 'AdminPermissionsController');
Route::controller('settings', 'AdminSettingsController');
Route::controller('roles', 'AdminRolesController');
Route::controller('users', 'AdminUsersController');
Route::controller('/', 'AdminController');
});
// Public and user routes
Route::controller('contacts', 'ContactsController');
Route::controller('users', 'UsersController');
Route::controller('/', 'IndexController');
Route::controller('faq', 'StaticPagesController#faq');
My StaticPagesController.php file
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class StaticPagesController extends Controller
{
public function faq(){
return 'this is faq page';
}
}
I have tried composer update, php artisan acl:update, composer dumpautoload to no avail.
Please help me. Thanks
With this line:
Route::controller('faq', 'StaticPagesController#faq');
You are telling Laravel that the controller for faq shoule be StaticPagesController#faq. The Route::controller method sets an entire controller for a route, it does not specify a method to be used on that route, Laravel handles this internally. Take a look at your error to prove my point:
Class App\Http\Controllers\StaticPagesController#faq does not exist
It is looking for class StaticPagesController#faq not StaticPagesController as you are intending.
Unless you are building an API using REST, you should not use the controller method and instead specify your routes explicitly, i.e.
Route::get('faq', 'StaticPagesController#faq');
This will use the faq method on your controller when the user makes a GET request to the URI faq. If you insist on using the controller method, then remove the #faq from the second argument and you will be good, although I'm pretty sure Laravel expects the methods index, show, create, etc to be in your controller. I suggest taking a look at the Laravel 5 Fundamentals video course to help you get a better understanding.

Laravel. Routes do not match

At first it seems that the same routes. But in first route not working middleware that I ordered in the constructor.
How to fix that?
Route::get('/cars.get', function() {
return App::make('App\Http\Controllers\CarsController')->{'get'}();
});
Route::get('/cars.get', 'CarsController#get');
sorry for my English =)
Edit
I was wrong about callAction() it does nothing else than call the method.
Unfortunately there doesn't seem to be a simple API to call middleware manually. A solution to this would just be to define the middleware on the route:
Route::get('/cars.get', ['middleware' => 'auth', function() {
return App::make('App\Http\Controllers\CarsController')->{'get'}();
}]);
original answer:
By directly calling the get() method you skip middleware defined in the controller. You should use callAction() instead:
return App::make('App\Http\Controllers\CarsController')->callAction('get');
Also note that you can use app() as a shortcut for App::make():
return app('App\Http\Controllers\CarsController')->callAction('get');

Laravel controller define with mask

I have PagesController defined in my routes file:
Route::controller('/', 'PagesController');
But i use some more routes like:
Route::get('/admin', function()
{
....some code here
});
My second route doesn't work, because all other routes try to find functions in PagesController. I can change my controller to:
Route::controller('pages', 'PagesController');
But then in my home page, all links will be like www.test.com/pages/..., but i don't need that 'pages' in there. How to define my controller with mask or something like that?
Laravel allows you to easily define a single route to handle every action in a controller using simple, REST naming conventions. First, define the route using the Route::controller method:
Route::controller('pages', 'PagesController')
This is a single route to define all actions in a controller using REST naming conventions therefore you get the /pages.
For the root of your app you need to specify the method that you want to call within your PagesController.
Example:
Route::get('/', array('as' => 'home', 'uses' => 'PagesController#getIndex'));
Place this line at the top of your routes in the routes file.
Change the order of your route definition to this:
Route::get('/admin', function()
{
....some code here
});
Route::controller('/', 'PagesController');
It will now look for /admin first, and if it cant find it, it when they go to your other routes...
Try changing Route::controller({same content as the question}) to Route::resource({same content as the question})

Categories