Laravel Controller Delegation - laravel

Trying to keep my Laravel project organized here, while letting it grow.
Currently I use:
Route::controller('/admin', 'AdminController');
...in order to allow the controller to service general admin pages. This is working fine, however I'd like to delegate specific subqueries to other controllers for cleanliness reasons.
For example, I'd like /admin/dashboard to resolve to AdminController#getDashboard. I'd also like /admin/gallery/ to resolve to AdminGalleryController#getIndex, and /admin/foo/bar to resolve to AdminFooController#getBar.
Is there a simple way to slowly expand functionality like this?
We've migrated to Laravel 5 and 5.1, and this still remains a good way to do things. If you aren't using route groups in Laravel, then you aren't doing Laravel right.

You can define those others as controller routes as well. Just do it before Route::controller('admin') because Laravel searches the registered routes in the other you define them. Since /admin/gallery would match Route::controller('admin') as well as Route::controller('admin/gallery') latter has to be defined first:
Route::controller('admin/gallery', 'AdminGalleryController');
Route::controller('admin/foo', 'AdminFooController');
Route::controller('admin', 'AdminController');
Instead of writing admin every time a route group might be a nice improvement as well:
Route::group(['prefix' => 'admin'], function(){
Route::controller('gallery', 'AdminGalleryController');
Route::controller('foo', 'AdminFooController');
Route::controller('/', 'AdminController');
});

Yes. Simply declare your "exception" routes before your main controller route.
Route::get('/admin/gallery','AdminGalleryContoller#getIndex');
Route::get('/admin/dashboard','AdminController#getDasboard');
Route::controller('/admin','AdminController');

Related

Is it possible to make Single Page Application and MPA at the same time?

I am using Laravel and vue.js to make a SPA. So my routes looks like this:
In my routes/web.php
Route::get('/{any}' , 'SinglePageController#index')->where('any', '.*');
and then, the entire route will be handled by the vue router.
However, I decided to make a Multiple Pages(for my SEO) on other Pages while the SPA is for the loggedin users only.
I'm going to add another route in web.php but it returns 404 .
Route::get('/guests', 'GuestController#index');
[Note that I have GuestController and blades]
Is it possible? If so, please give me hints. I tried to search on google but haven't found.
Yes, you just have to place your route for /guests before your more general /{any}. Remember, Laravel check routes from top to bottom and the first matched will be used.
Route::get('/guests', 'GuestController#index');
// other specific routes
// ...
Route::get('/{any}' , 'SinglePageController#index')->where('any', '.*');

How does Laravel 5.4 Middleware work?

I've read manual of Laravel 5 but still don't find a solution for my problem.
My task: I need to run multiple websites on the one codebase.
What have I done for it? I made one main website and create table "sites" where I can add new satellites. It's all worked fine. But now, in front end part, I need to create middleware which will help me to divorce different parts of my engine.
I start to create middleware but I've only found 2 ways of middleware:
redirect to the correct URL
return $next($request) which means that this middleware will be always working.
I don't need a redirect. I just need one thing:
I need that in my web.php route file I can make routes with my middleware group:
For example:
Route::group(['middleware' => 'site'], function () {
//there will be only routes for my satellites
And
Route::group(['middleware' => 'web'], function () {
//There will be another routes which won't be on satellites
The problem is if I make a redirect on the main site my middleware still working and going into the cycle.
Is there any way to break middleware and don't going into the certain routes?
I've tried with HttpException but I've received only 404 or 500 errors, but I don't need it in this case.

How to exclude slugs from a Laravel route pattern

I have a Laravel Spark application, and would like to use the first two parameters in a route for team and project, with exceptions like about_us, settings, api etc.
I have set up my routes, similar to:
Route::pattern('team', '[a-zA-Z0-9-]+');
Route::pattern('project', '[a-zA-Z0-9-]+');
Route::get('/home', 'HomeController#show');
Route::group(['prefix' => '{team}'], function () {
Route::get('/', 'TeamController#dashboard');
Route::group(['prefix' => '{project}'], function () {
Route::get('/', 'ProjectController#dashboard');
...
//Spark defines routes such as /settings after the apps routing file is processed;
//thus I cannot route to /settings as it's caught by /{team}.
I am struggling to do one of two things. Either, exclude values like 'api', 'settings' etc from the {team} pattern; or get the Laravel Spark routes to run before my web routes, so that I can ensure all valid routes are checked before the catch-all of /{team}.
Any ideas would be appreciated!
One suggestion I'd have, is to consider having the prefix of teams, then the team name after, you may find you want to add more sort of catch-alls like this for another section and run into more problems down the line. Perhaps listing all the teams using the index of this closure could be of benefit to admins of the system too?
If you'd like to continue down this route, take a look in your config.app.php, I believe that switching around the following two providers may well achieve what you're after. End result order:
App\Providers\SparkServiceProvider::class,
App\Providers\RouteServiceProvider::class,
I'm using the latest version of Spark after a recent install myself, this seems to be the default now, apologies if this is a red-herring!
I appear to have solved it, using the following pattern:
Route::pattern('team', '(?!^settings$)([a-zA-Z0-9-]+)');
For those who are new to the question, the principles are as follows. In a plain Laravel installation, you could re-order your routes to ensure they are processed in the right order, putting wildcards after your fixed routes.
With Spark, there are a number of routes all encapsulated away in the Spark package. Preferring not to mess around with this, allowing for easier Spark upgrades later amongst other things, it is possible to use a route pattern to limit the acceptable values for your parameter. As such, with some Googling on RegExs, I appear to have found a pattern that will exclude slugs matched by my {team} parameter.
I believe that adding more exclusions is as easy as inserting a pipe operator.
This would also obviously work on standard Laravel installations, but re-ordering your routes is probably a better first call.
You should define the routes you want to exclude first.
Then define your patterns below them. They will have precedence over the patterns because in Laravel routes are evaluated in top to bottom order.

Laravel 5 - Assign Middleware to Controller Namespace

I need to do an ACL check for the user before allowing access to the admin panel of a Laravel 5 website. What is the best way to do this for an entire controller group in the namespace App\Http\Controllers\Admin\*? Ultimately, I'm looking for a "set and forget" method to do this, and middleware looks like the best option so far.
The initial idea was to assign a middleware to the admin route, but this does not prevent any other non-admin route from accessing the controllers. This means a route can still target the admin controllers and bypass the ACL check.
The next idea was to insert the assignment in the constructor on the controllers, but this would require each additional controller to explicitly include the middleware. This would require a developer to know that the middleware should be included, which allows them to miss it entirely. This also applies to using one base controller as the parent for all admin controllers, since the developer would need to know that the base controller should be extended. Right now, this looks like the best solution.
This leads us back to the question: can middleware be assigned to a controller wildcard namespace like App\Http\Controllers\Admin\*? Or, is there a better way for the ACL check to never need to be explicitly assigned to every admin controller?
This leads us back to the question: can middleware be assigned to a controller wildcard namespace like App\Http\Controllers\Admin*?
No
The most simplest approach you can do is create a base controller such as App\Http\Controllers\Admin\Controller and include the middleware
while all other App\Http\Controllers\Admin\* extends it.
Alternatively, while still adding App\Http\Controllers\Admin\Controller, you could instead inject the middleware through IoC Container.
App::afterResolving('App\Http\Controllers\Admin\Controller', function ($controller) {
$controller->middleware('acl');
});
EDIT
My previous answer didn't quite work for all situations; it broke a lot of other routes. Here's what I ended up doing instead (in app/Http/routes.php):
Route::group(['namespace' => 'Admin', 'prefix' => 'admin', 'middleware' => 'App\Http\Middleware\Acl'], function()
{
Route::get('/', 'AdminController#index');
Route::get('/user', 'User\UserController#index');
...
});
This at least targets all admin controllers when I define a route. It's not exactly everything I had hope for, but it will do.

Laravel 4.x, using both controller & resource routing

I'm trying using this:
Route::resource('users', 'UserController');
Route::controller('users', 'UserController');
When I'm using one of them - WORK,
otherwise - only resource work.
There is an option to using them both?
Which ever is on-top will take priority so if you put Route::controller on-top then that's the one that would work. I would post this as a comment but I don't have the rep to do it. Also why would you wanna use both of them at the same time?
Try moving Route::controller declaration above Route::resource:
Route::controller('users', 'UserController');
Route::resource('users', 'UserController');
The thing is that Laravel tries to match request with your defined routes by going from top to bottom and stops when it finds one.
localhost/users/example in your example actually hits show method in your UserController class as explained in documentation (see Actions Handled By Resource Controller).
Therefore Route::controller('users', 'UserController'); is ignored in this case.
I believe it's only working with one because once you use Route::resource(), all routes starting with users is going to be grabbed, and since Route::resource() does not work by prepending the action with the last segement in the uri (public function getUsers()), it's failing.
With your example provided, all you should need to use is Route::controller(). If there are some cases where that won't do, before it, add whatever routes you need using Route::get(), Route::post() or Route::any()
Route::resource() and Route::controller() were I believe not designed to work together and there shouldn't be much need to actually use them together.

Resources