I have a laravel app with 2 groups of routes:
Route::group(array('prefix' => 'api'), function()
{
Route::post('/login', ['uses' => 'AuthenticationController#apiLogin']);
}
Route::group(array('prefix' => 'admin'), function()
{
Route::post('/login', ['uses' => 'AuthenticationController#adminLogin']);
}
In an effort to save time and prevent writing double code I'd like to condense the apiLogin() and adminLogin() function to one function: login(). I'd also like to return different things based on the route that is calling the function.
If the request is coming from /api/login I want to return Response::json($apiResponse). If the request is coming /admin/login I want to return Redirect::('route.to.redirect.to')
Is there a way I can tell where the controller function is being called from? (preferable without parsing the URL)
You can check the route in your controller. (I'm not saying this is the best solution for your problem, but you can)
The best way to do this is by naming your routes. Laravel Docs
Route::post('/login', ['as' => 'apiLogin', 'uses' => 'AuthenticationController#apiLogin']);
Route::post('/login', ['as' => 'adminLogin', 'uses' => 'AuthenticationController#adminLogin']);
And then you just do
Route::currentRouteName();
If for some reason you can't name your routes you can still get the path of the route (that's not the full url but the segment that's defined in the route. groups included)
So Route::getCurrentRoute()->getPath() should return either api/login or admin/login
You can check URL in controller, but the better solution in this case would be probably leaving routes as they are, create login method with parameter:
public function login($from) {
}
and define apiLogin and adminLogin functions this way:
public function apiLogin() {
return $this->login('api');
}
public function adminLogin() {
return $this->login('admin');
}
this way, if you will decide in future to change the code you will change the code only of those methods, leaving routes without a change.
Related
I have two kind of routes, admin routes and frontend routes.
The frontend routes
Route::get('{locale?}/', ['uses' => '\App\Http\Controllers\loadViewController#home']);
Route::get('{locale?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#index']);
Route::get('{locale?}/{template?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#detail']);
The backend routes
Route::prefix('admin/dashboard')->group(function () {
Route::get('/', 'DashboardController#index')->name('dashboard');
});
Now when i type admin/dashboard or api/admin, laravel uses the frontend routes to load the views, while i want the backend views to be loaded.
So to filter out the backend routes i tried this
Route::group(['where' => ['page' => '^(?!admin|api)$', 'template' => '^(?!admin|api)$']], function ({
Route::get('{locale?}/', ['uses' => '\App\Http\Controllers\loadViewController#home']);
Route::get('{locale?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#index']);
Route::get('{locale?}/{template?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#detail']);
});
which obviously did not work
Also the frontend routes should not have something like /website, they should all start with /
My question is: How can i load the backend and frontend routes separately without interfering when called, even if they have the same url length in terms of parameters, keep in mind that the admin routes always start with /admin or /api.
Note: i can't put the backend routes before the frontend routes
Thanks in advance!
If you want to you could put a constraint on the locale route parameter:
Route::pattern('locale', '^(?!(api|admin)$)(\w*)');
You can put this in the boot method of you RouteServiceProvider and it will now not allow the locale route parameter to match for 'api' or 'admin'.
You can register seperate routes in RouteServiceProvider. Following is how you can do it.
Inside RouteServiceProvider.php do:
public function map()
{
$this->mapFrontendRoutes();
$this->mapAdminRoutes();
}
Definition of mapFrontendRoutes():
protected function mapFrontendRoutes()
{
Route::prefix('{locales?}')
->middleware('frontend')
->namespace($this->namespace.'\Frontend')
->group(base_path('routes/frontend.php'));
}
Definition of mapAdminRoutes():
protected function mapAdminRoutes()
{
Route::prefix('admin')
->middleware('admin')
->namespace($this->namespace.'\Admin')
->group(base_path('routes/admin.php'));
}
I personally find this very useful, helps to declare interference free and logical routes. Open to feedback.
The simple way is to group both url's as separate groups. Example as follows :
Route::group(['prefix' => 'admin', 'as' => 'admin'], function () {
Route::post('/dashboard', 'AdminController#dashboard');
});
Route::group(['prefix' => 'home', 'as' => 'home'], function () {
Route::get('/record/{id}', 'HomeController#getRecord');
});
I'm using this package in my project and there have default package routes.
Like this:
I want use this route in my controller. I'm trying to use with name but it did not work this way.
Route::group(['prefix' => 'admin', 'as' => 'admin.'], function () {
Voyager::routes();
});
And
Route::group(['prefix' => 'admin'], function () {
Voyager::routes();
})->name('admin');
I'm trying to use like this:
I want to give access like this, as if I'm trying to access 'admin' route then I could access all routes under these route group. I don't know how I will do that?
Please help me.
You cannot redirect to route with name admin. because such route doesn't exist.
When you use:
Route::group(['prefix' => 'admin', 'as' => 'admin.'], function () {
Voyager::routes();
});
it means all routes created by Voager::routes() will have name starting with admin. but it doesn't mean admin. route exist.
So I assume you should instead use rather admin.voyager.dashboard instead, so you should rather use:
return redirect()->route('admin.voyager.dashboard');
instead of:
return redirect()->route('admin.');
I have two applications, the routes file of the working one is below:
routes.php
<?php
Route::auth();
Route::group(["prefix" => "api"], function() {
Route::resource("places", "PlacesController");
Route::resource("users", "UsersController");
Route::group(["prefix" => "auth"], function() {
Route::get("/", "AuthController#GetAuth");
Route::get("logout", 'Auth\AuthController#logout');
});
});
Route::get('/', 'RedirectController#toAngular');
I have the same thing in another application but it is not working. I get an InvalidArgumentException because it can't find the login.blade.php file which I deleted because it is handled by Angular. How do I properly and most efficiently override the /login and /register GET routes generated by Route::auth()?
If you want to override /login and /register, you can just add those two routes after declaring Route::auth() like following:
Route::get('login', ['as' => 'auth.login', 'uses' => 'Auth\AuthController#showLoginForm']);
Route::get('register', ['as' => 'auth.register', 'uses' => 'Auth\AuthController#showRegistrationForm']);
As the application can't find the 'login.blade.php' which is actually returned from controller method, not in routes, then you need to override the showLoginForm method in AuthController and return what view you want to load.
public function showLoginForm() {
return view('path.to.your.view');
}
I created a new laravel project and laravel flash seems to not be working as i want. The moment I return to a route the flash is gone. I have controller method that does absolutly nothing but flash and return to a route.
Like so
public function activateContract(Request $request ){
return redirect()->to('test')->with('status', 'test');
}
My routes file
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get('/', function(){
return redirect()->intended(route('contract.index'));
});
Route::group(['middleware' => 'auth'], function () {
Route::group(['prefix' => 'contract'], function(){
Route::get('', ['as' => 'contract.index' , 'uses' => 'User\ContractController#index']);
Route::post('', ['as' => 'contract.index' , 'uses' => 'User\ContractController#activateContract']);
Route::get('mijn', ['as' => 'user.contract.index' , 'uses' => 'User\ContractController#userContracts']);
});
});
Route::get('test', function(){
dd(session('status'));
});
c});
Here is the ouput of the die dump in the test route witch magicaly lost the flash message.
null
You need to send the message with the redirect like so:
return redirect()->to('test')->with('status', 'test');
And then you can access it with the session helper function:
session('status');
docs
Edit: Place your Route::get('test') into your group with middleware 'web'.
See more about HTTP Middleware here
Laravel 5.2 changed middleware document as :Keep in mind, the web middleware group is automatically applied to your default routes.php file by the RouteServiceProvider.
It means that if you keep a route in another ['middleware' => 'web'], the data set by session()->flash() would be lost by executed web middleware twice.
It is also the answer someone asked why web executed twice.
Laravel 5.2 : Web middleware is applied twice
In my Laravel app I have a resource route where I want to control access to individual routes based on a filter. I do this by declaring the resource with only the "view" routes and then declaring it again with only the "edit/create" routes in a nested filtered group. The filter is a custom one that check the logged-in user's capabilities.
My routes looks like this:
Route::group(['before' => 'auth'], function()
{
$edit_routes = ['create', 'store', 'destroy', 'edit', 'update'];
Route::resource('things', 'ThingsController', ['except' => $edit_routes]);
// We'll filter the routes that involve editing resources
Route::group(['before' => 'edit_resource'], function() use ($edit_routes)
{
Route::resource('things', 'ThingsController', ['only' => $edit_routes]);
});
}
Is this correct? It seems not to work, although no errors are thrown. When I visit a route in the nested filter (e.g. things/create) I just get a blank page.
Is there a better way of achieving this?
Is this correct?
No
Is there a better way of achieving this?
Yes. Here is a great blog post by Phil Sturgeon that explains why you should just define each route manually.
If you really want to continue using the Resource Controller, you can apply the edit_resource inside the controller constructor like this:
Route::resource('things', 'ThingsController', ['before' => 'auth']);
Then in your resource controller
public function __construct()
{
$this->beforeFilter('edit_resource', array('only' => ['create', 'store', 'destroy', 'edit', 'update']);
}