So I have used this format again. In my routes.php I have
Route::controller('datatables', 'HomeController', [
'PaymentsData' => 'payments.data',
'getIndex' => 'datatables',
]);
In my HomeController.php I have
public function getIndex()
{
return view('payments.index');
}
/**
* Process datatables ajax request.
*
* #return \Illuminate\Http\JsonResponse
*/
public function Payments()
{
return Datatables::of(DB::table('customer'))->make(true);
}
Anytime I try php artisan I get [BadMethodCallException] Method controller does not exist.
Question, is this form of doing it Deprecation or why anyone spot something wrong? Kindly assist. Thank you.
The controller method is deprecated since Laravel 5.3. But now, you can use the resource method, which is meant for the same purpose as the controller method:
From the docs:
Laravel resource routing assigns the typical "CRUD" routes to a controller with a single line of code. For example, you may wish to create a controller that handles all HTTP requests for "photos" stored by your application.
Use it as:
Route::resource('datatables', 'HomeController');
The downside of this implicit routing is that you have to name your methods consistently, more about it in the docs.
In most cases, better practise would be explicit routing, as it makes your code much more clear and understandable.
As far as I'm aware that's never been available for Laravel 5. I haven't used 4 so I'm not sure about prior to 5. But in 5 you need to use Route::get and Route::post.
Route::get('datatables', ['as' => 'HomeController', 'uses' => 'HomeController#getIndex']);
Route::get('payments-data', ['as' => 'HomeControllerPaymentsData', 'uses' => 'HomeController#Payments']);
Yep, it was removed as using implicit controllers is bad practice - https://github.com/illuminate/routing/commit/772fadce3cc51480f25b8f73065a4310ea27b66e#diff-b10a2c4107e225ce309e12087ff52788L259
Related
I'm trying to setup a laravel application with oauth autorization by using the laravel passport functionality. I'm using the official tutorial (https://laravel.com/docs/master/passport). But now if I make a post request to '/oauth/authorize' the following error message occurs:
Class App\Http\Controllers\Laravel\Passport\Http\Controllers\ApproveAuthorizationController does not exist
I don't know what I've been doing wrong. I use the routes getting from 'Passport:routes' and no self defined routes.
I've already made a composer update, install and clear cache but nothing worked.
The problem get caused here:
/**
* Register the routes needed for authorization.
*
* #return void
*/
public function forAuthorization()
{
$this->router->group(['middleware' => ['web', 'auth']], function ($router) {
$router->get('/authorize', [
'uses' => 'AuthorizationController#authorize',
]);
$router->post('/authorize', [
'uses' => 'ApproveAuthorizationController#approve',
]);
$router->delete('/authorize', [
'uses' => 'DenyAuthorizationController#deny',
]);
});
}
I've already tried it by importing the missing class with a use statement but it still wont work.
Can somebody help me?
It looks like you're missing a use statement at the top of a controller or service proivder. Somewhere you have a class being used with out properly importing it first. That's why you're seeing the concatenated string like:
App\Http\Controllers\Laravel\Passport\Http\Controllers\ApproveAuthorizationController.
I assume what you need is this:
use Passport\Http\Controllers\ApproveAuthorizationController;
or Passport in Passport::routes is not being imported, one of the two. In AppServiceProvider:
use Laravel\Passport\Passport;
I have some code in my routes file:
Router::scope('/v1', function (RouteBuilder $routes) {
$routes->resources( 'Files');
});
And then a FilesController with a delete function like:
public function delete($id){
echo "here"; exit();
}
When I do:
DELETE http://192.168.1.197/v1/files/1
The response is here, however, if I do:
DELETE http://192.168.1.197/v1/files
The response is that it is missing the V1Controller.
What I would expect instead is for CakePHP to turn around and say "oops, you have passed the wrong number of required parameters".
Something very weird seems to be going on here and I am not quite sure what. How can I make the two do the same thing and point to the controller?
CakePHP operates very differently on exceptions when debug mode is enabled. When debug is true all exceptions are rendered with debug information, stack tracing and developer friendly messages.
When debug mode is false the exception is rendered as a standard HTTP response type. With handles for 400 and 500 error codes.
When the router can't find a match for a route there is no controller involved. The HTTP request never gets past the dispatching phase. It's the dispatcher that throws a 400 type exception.
In your given example the framework is throwing a MissingControllerException with the HTTP code of 404.
400 error codes are rendered via the ErrorController. CakePHP comes a with a default error controller, but if you generate a new application using the composer template, then you should have a default ErrorController in your app's controller holder.
In your templates there should be a src/Template/Error/error400.ctp file which displays the response for 400 codes. Keep in mind, that this template is not used when debug mode is enabled.
You can modify this template to find "closely" matching routes and offer them as recommendations to the user as feedback in the error message.
You can iterate all configured Routes easily like this:
foreach (Router::routes() as $route) {
$name = isset($route->options['_name']) ? $route->options['_name'] : $route->getName();
$output[] = [$name, $route->template, json_encode($route->defaults)];
}
Above taken from cakephp/src/Shell/RoutesShell.php:
Since this is technically a 404 error. There is no matching route and what you can do is try to find routes that are "close" to a match. The problem here is that you are subject to the same route matching challenges as the Router class.
The Router class uses dynamic routing techniques that take parts of the URL parameters and fills them in as names of controllers, names of actions and user defined parameters.
This can change significantly depending upon what kind of default router class you are using.
For example, you might be using the DashedRoute routing class which does the following:
/**
* This route class will transparently inflect the controller, action and plugin
* routing parameters, so that requesting `/my-plugin/my-controller/my-action`
* is parsed as `['plugin' => 'MyPlugin', 'controller' => 'MyController', 'action' => 'myAction']`
*/
class DashedRoute extends Route
You might instead be using the InflectedRoute routing class which does the following:
/**
* This route class will transparently inflect the controller and plugin routing
* parameters, so that requesting `/my_controller` is parsed as `['controller' => 'MyController']`
*/
class InflectedRoute extends Route
Since there are cases where routing could be using dynamic routing. It's not possible to know if a URL segment is a controller, action or named parameters.
Add to the complexity that you're also using a scoped segment named /v1 it becomes even more challenging to predict what the intended route is.
You can either create custom routes to catch these edge cases and render an informative error message, or you can try to add logic to the error400.ctp to display a more informative error message.
There is also a final option. Where CakePHP allows you to write your own custom Route classes, and/or modify the middleware with your own dispatcher.
I solved this another way entirely, just stop using the resource routes in CakePHP; I changed my code to:
$routes->get('/files/*', ['controller' => 'Files', 'action' => 'view'], 'files:get');
$routes->post('/files', ['controller' => 'Files', 'action' => 'add'], 'files:post');
$routes->put('/files/*', ['controller' => 'Files', 'action' => 'edit'], 'files:put');
$routes->patch('/files/*', ['controller' => 'Files', 'action' => 'view'], 'files:patch');
$routes->delete('/files/*', ['controller' => 'Files', 'action' => 'delete'], 'files:delete');
And it works exactly as how I wanted in the question...
(1/1) BadMethodCallException
Method [show] does not exist. in Controller.php (line 82)
I am new to Laravel and PHP and have been stuck on this error for a very long time with other questions not providing a solution. I was following an example (where the example worked) and made very little changes beside name changes.
Here is the code:
web.php file
Route::get('/', 'PagesController#home');
Route::get('faq', 'PagesController#faq');
Route::resource('support', 'UserInfoController');
UserInfoController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\UserInfo;
class UserInfoController extends Controller
{
//
public function create(){
$userInfo = new UserInfo;
return view('contact', ['userInfo' => $userInfo]);
}
public function store(Request $request){
$this->validate($request, [
'name' => 'required',
'email' => 'required',
'subject' => 'required',
'description' => 'required',
]);
UserInfo::create($request->all());
return redirect()->route('contact')->with('success','Enquiry has been
submitted successfully');
}
}
UserInfo.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserInfo extends Model {
protected $fillable = [
'name','email','subject','description',
];
}
The Route::resource is the one giving me the problem as I am trying to access the page support/contact. Would be very grateful if someone knew how to solve this.
That is because you are doing resource routes in your routes.php file that generates all the routes for the CRUD functions when you have to generate a route for the show method you find that it does not exist.
To solve it only creates the methods that you ask or, also you can define only the routes that you need.
The controller is trying to invoke the 'show' method - which you should have defined if you're going to load /support/{id} via GET in your browser. You can see the expected methods for a resource here:
https://laravel.com/docs/5.4/controllers#resource-controllers
You can also make your life somewhat easier by starting with a valid controller by using the built in generator:
php artisan make:controller UserInfoController --resource
If you don't want to supply ALL the methods, you have to specify, for example:
Route::resource('support', 'UserInfoController', ['only' => [
'create', 'store'
]]);
Have you added method Show to your Controller ? Route::Resource has 7 basic routes:
Verb Path Action Route Name
GET /support index support.index
GET /support/create create support.create
POST /support store support.store
GET /support/{support} show support.show
GET /support/{support}/edit edit support.edit
PUT /support/{support} update support.update
DELETE /support/{support} destroy support.destroy
As you see there is a route called show which will be default when you route to support so you must connect this route to it's method in the controller which is in resource case CONTROLLER/show, however in your case you're trying to get a static page from a prefix called support which is different from resources because show in resource handling dynamic results.
Use this syntax to get a page called contact from prefix called support
Route::prefix('support')->group(function () {
Route::get('contact', function () {
// Matches The "/UserInfoController/contact" URL
});
});
I've been stuck with a problem in Laravel 5.
Question: Is is possible to have a default function in a Laravel controller if no other functions are activated?
Explanation:
In routes I have this:
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
'/projects' => 'ProjectController'
]);
By doing this I can call functions in my ProjectController like getIndex or postCreate. I'd like to have the following
/projects/create, /projects/edit/{id} etc. AND /projects/{slug} <- name of project. Before, when I set all my routes individually I could just place the /projects/{slug} at the bottom and it would check for that at last.
I thought of a solution: go trough all the functions, if none of them are executed do the default function (for /projects/{slug})
How would I do this? If more code is needed, please ask! :)
I think you might be looking for missingMethod:
public function missingMethod($parameters = array())
{
// code goes here
}
Read more in the Laravel Documentation.
I try to learn Laravel, and I'd like to verify the user is logged in before calling a controller to do stuff.
There seems to be at least 3 different ways to accomplish this, and I'd like to know what is the difference between these.
Route::get('/main', 'StuffController#doStuff')->before('auth');
Route::get('/main', array('before' => 'auth', 'uses' => 'StuffController#doStuff'));
Or in the controllers constructor:
public function __construct() {
$this->beforeFilter('auth');
}
There are no differences. Laravel is the Framework that allow you to accomplish many tasks in many ways.
I prefer to add filters in routes grouping them, for example:
// logged users paths
Route::group(
['before' => 'auth'],
function () {
Route::get('/dashboard', [
'as' => 'dashboard',
'uses' => 'DashboardController#mainPage'
]);
}
);
// paths only for admin
Route::group(
['before' => 'admin'],
function () {
Route::get('/admin',
['as' => 'admin_dashboard',
'uses' => 'AdminDashBoardController#mainPage'
]);
Route::get('/categories/{page?}',
['as' => 'categories',
'uses' => 'CategoryController#displayList'
])->where('page', '[1-9]+[0-9]*');
}
);
There is one benefit of such use - its' much easier to look if all routes have correct filters.
Assume you want to display some content only for logged users and you need to use auth filter. You have many controllers to display content for logged users.
If you use beforeFilter directly in those controllers or in parent controllers constructor the following things can happen:
you may forget to put beforeFilter in all your controller constructors
you may forget in your controller constructor to run parent constructor (where you have beforeFilter)
you may extend not the class you wanted (for example you extend BaseController and you have beforeFilter defined in AuthController and in one or some classes you extend BaseController)
Those situations can cause that you display content for unlogged users because you need to remember about auth filter it in each controller and if you want to make sure you did everything right, you need to look at code of all your controllers.
Using route grouping (as I showed above) you can easily look at one file (of course assuming you use one file for routing) and you will see which routes use auth filter and which don't.
Of course I assume many people will have their own opinion on that thing but that's me personal preference to use filters in routes.
Your two ways have no difference, just different syntax style.
I prefer to put the auth filter in a BaseController, then extends all controllers I want to be authed from BaseController. Just write once, used everywhere. Btw, you can also put your csrf filter here.
class BaseController extends Controller {
public function __construct() {
$this->beforeFilter('auth');
$this->beforeFilter('csrf', array('on' => 'post'));
}
}