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.
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;
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
So building a few pages on the same template and loading the content via AJAX. Most of the content are forms. Views are defined by step number (1,2,3,4,5....32)
Here is how I built my route:
Route::get('onboarding/', [
'as' => 'get-onboarding-start',
'uses' => 'OnboardingController#getStart'
]);
Route::get('onboarding/{i}', [
'as' => 'get-onboarding-step',
'uses' => 'OnboardingController#getNextStep'
]);
Route::post('onboarding/{i}', [
'as' => 'post-onboarding-step',
'uses' => 'OnboardingController#postStepForm'
]);
Now one method in the controller cannot handle all the work. Meaning I will need to redirect to another method based on the $i (step number).
I am afraid that it is not simple to read if I put a big blog of switch case $i = 1,2,3...
At the same time I don't want to write 32 different routes.
What would you propose?
Hard code all the routes meaning: 'onboarding/username' then
'onboarding/email' etc... etc... The good point is that it is super
simple to read in the views and you know exactly what the next step
is... no need to check what the number corresponds to.
Catch all as coded now and redirect to different methods in the controller
Something better, super easy to read and with little lines of
code... which is .... ??
If these steps are going to remain as they are without many changes in the future, I'd go for the first option (having 32 get & 32 post routes). This will keep your application simple, if you'd want to apply parameters or middleware to them you can use route groups. Below I've posted a small code example from the laravel documentation
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
Well I have a little problem, and I don't know if I'm blind to find it inside the Laravel 4 Documentation or it doesn't even exist ...
I have two routes that route to one and the same controller function...
//List blog_posts
Route::get('/', 'BlogController#listPosts');
//List deleted blog_posts
Route::get('/bin', 'BlogController#listPosts');
Now, is there a way to determine inside the 'listPosts' function what route was hit ?
Of course I could create another function inside 'BlogController' but I dont like that idea ^^
You can try using Route::current(). It will return an object of type Illuminate\Routing\Route which has a method on it called getUri:
var_dump(Route::current()->getUri());
If you gave your routes a name, you can also make a decision based off of that:
var_dump(Route::currentRouteName());
You can also use named routes:
Route::get('/', ['as' => 'listIndex', 'uses' => 'BlogController#listPosts']);
Route::get('/bin', ['as' => 'listBin', 'uses' => 'BlogController#listPosts']);
This will set Route::currentRouteName() which you could if/else on.
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'));
}
}