Routing in Laravel 7 - php

Hello i'm new to laravel and im building my first api.
I have several routes that have the same prefix and i was wondering if its possible to group them under one route group and switch the last part of the uri to match the controller i need
Here is a example
main prefix: 'tenant'
possible routes: 'tenant/email_template' , 'tenant/review' , 'tenant/static_metas'
the routing that i want to achieve its something like this
Route::group(['prefix' => 'tenant/{entity}' , 'middleware' => 'auth'], function($router){
Route::post('{entity}/create', '{entity}Controller#create)->name({entity}.create);
});
Where the entity stand for the last part of the uri , if i give 'tenant/static_metas' i want to take the last part of the uri 'static_metas' and bind it to a create method calling the static_meta controller and its create method.
The reason behind this its to avoid rewriting the CRUD routes n-times changing only the controller and the uri.
Thank you

You can definitely do that, just use for loop.
And also the preferred group syntax is to separate prefix and middleware part into its own function with group having only closure.
$entities = ['email_template', 'review', 'static_metas'];
foreach($entities as $entity) {
Route::prefix("tenant/{$entity}")
->middleware('auth')
->group(function($router) use ($entity) {
$studEntity = \Str::studly($entity);
Route::post("{$entity}/create", "{$studEntity}Controller#create")
->name("{$entity}.create");
});
}
Also you should use Resource controller for consistent CRUD operations. https://laravel.com/docs/8.x/controllers#resource-controllers

Related

Laravel 5 redirect to path with parameters (not route name)

I've been reading everywhere but couldn't find a way to redirect and include parameters in the redirection.
This method is for flash messages only so I can't use this.
return redirect('user/login')->with('message', 'Login Failed');
This method is only for routes with aliases my routes.php doesn't currently use an alias.
return redirect()->route('profile', [1]);
Question 1
Is there a way to use the path without defining the route aliases?
return redirect('schools/edit', compact($id));
When I use this approach I get this error
InvalidArgumentException with message 'The HTTP status code "0" is not valid.'
I have this under my routes:
Route::get('schools/edit/{id}', 'SchoolController#edit');
Edit
Based on the documentation the 2nd parameter is used for http status code which is why I'm getting the error above. I thought it worked like the URL facade wherein URL::to('schools/edit', [$school->id]) works fine.
Question 2
What is the best way to approach this (without using route aliases)? Should I redirect to Controller action instead? Personally I don't like this approach seems too long for me.
I also don't like using aliases because I've already used paths in my entire application and I'm concerned it might affect the existing paths if I add an alias? No?
redirect("schools/edit/$id");
or (if you prefer)
redirect("schools/edit/{$id}");
Just build the path needed.
'Naming' routes isn't going to change any URI's. It will allow you to internally reference a route via its name as opposed to having to use paths everywhere.
Did you watch the class Illuminate\Routing\Redirector?
You can use:
public function route($route, $parameters = [], $status = 302, $headers = [])
It depends on the route you created. If you create in your app\Http\Routes.php like this:
get('schools/edit/{id}', 'SchoolController#edit');
then you can create the route by:
redirect()->action('SchoolController#edit', compact('id'));
If you want to use the route() method you need to name your route:
get('schools/edit/{id}', ['as' => 'schools.edit', 'uses' => 'SchoolController#edit']);
// based on CRUD it would be:
get('schools/{id}/edit', ['as' => 'schools.edit', 'uses' => 'SchoolController#edit']);
This is pretty basic.
PS. If your schools controller is a resource (CRUD) based you can create a resource() and it will create the basic routes:
Route::resource('schools', 'SchoolController');
// or
$router->resource('schools', 'SchoolController');
PS. Don't forget to watch in artisan the routes you created

Using a different controller for GET and POST in Laravel but using the same name

I am writing route and controller rules for a web application. In a number of rules, a problem has emerged, which is that I need to match both GET and POST verbs, and send them to the controller, but different methods.
I considered using Route::controller('tracking', 'TrackingController') for this, but then it requires different names for each internal route, whereas I want to specify one name for both. Besides, I've read nothing but negativity regarding the usage, suggesting that it is not a good idea.
Here's what I have currently:
Route::match(['get', 'post'], '/tracking', [
'as' => 'tracking',
'uses' => 'TrackingController#index'
]);
While implementing this, I have discovered that I need to have two controller methods, index and track. How can I efficiently route GET to index and POST to track, while maintaining the same controller (TrackingController) and the same name (tracking)?
I considered using two separate routes, e.g. Route::get and Route::post, but that doesn't feel very eloquent.
you can use easily Route Controller,like this
Route::controller('tracking', 'TrackingController')
In here if you wanna use same method for both get and post,just use any prefix in method,like
//for both get and post
public function anyUrl();
//only get
public function getUrl();
//only post
public function postUrl();
Or use
Route::any('/url', function () {
return 'Hello World';
});

Add JSON routes for all routes to handle backend requests

I'm using Laravel 5.1 and am building a service that can be seen as JSON or HTML. This approach is already done by sites like reddit.
Example
Normal view: http://www.reddit.com/r/soccer
JSON view: http://www.reddit.com/r/soccer.json
As you can see, they simply add .json to an URL and the user is able to see the exact same content either as HTML or as JSON.
I now wanted to reproduce the same in Laravel, however I'm having multiple issues.
Approach 1 - Optional parameter
The first thing I tried was adding optional parameter to all my routes
Route::get('/{type?}', 'HomeController#index');
Route::get('pages/{type?}', 'PageController#index');
However, the problem I was facing here, is that all routes were caught by the HomeController, meaning /pages/?type=json as well as /pages?type=json were redirected to the HomeController.
Approach 2 - Route Grouping with Namespaces
Next I tried to add route groupings with namespaces, to seperate backend and frontend
Route::get('pages', 'PageController#index');
Route::group(['prefix' => 'json', 'namespace' => 'Backend'], function(){
Route::get('pages', 'PageController#index');
});
However, this doesn't work either. It does work, when using api as prefix, but what I want, is that I can add .json to every URL and get the results as json. How can I achieve that in Laravel?
You can apply regular expressions on your parameters to avoud such catch-all situation as you have for HomeController#index:
Route::get('/pages{type?}', 'PageController#index'->where('type', '\.json'));
This way it type will only match, if it is equal to .json.
Then, to access it in your controller:
class PageController {
public function index($type = null) {
dd($type);
}
}
and go to /pages.json

Laravel 4 routing - the ability to skip a route if conditions are not met

So we have a load of content within the database, let's call these Articles. The paths for the Articles start from the application root and can contain slashes. So we want to search the DB to see if we match an Article, and if not skip the route and give other routes the opportunity to respond.
In Sinatra (which I believe has inspired the routing within Laravel) you have the option to pass to the next route. It might be this that's leading me astray.
Route::get( '{uri}', function( URI $uri ) {
// check database, if we find a record we'll need to pass it to the appropriate controller
// we'll have a class that handles this responsiblity
// pass if we don't find anything
} )->where('uri', '.*');
Route::get( 'other/page', 'OtherController#sayHello' );
The issue Allow skip the route based on conditions #1899 talks about this, although I can't see how filters cater for this, they will simply intercept and give you an opportunity to stop route execution (throw exception, redirect to route specifically etc.), you can't return FALSE; without error. There is an example chaining a condition method to a route, although this method doesn't seem to exist (in 4.2).
Any ideas?
In addition to this, we're also are thinking about containing this logic within a package so it can be shared across applications, and wonder if you can influence the order of execution of routes provided by package?
You can have a group of routes, which you contain within all the routes that match it. If it fails that group then it skips to the next section.
Route::group(array('before' => 'auth'), function()
{
Route::get('/', function()
{
// Has Auth Filter
});
Route::get('user/profile', function()
{
// Has Auth Filter
});
});
http://laravel.com/docs/4.2/routing

Laravel - Change base URL globally?

Let assume, the base URL of my application is - http://www.example.com (I have not set anything in any config file to specify this). There are a lot of hard coded urls in the application.
eg. Contact
Now, if I go though the application using an URL like - http://www.example.com/country, is it possible to assign a global base URL, where when I click on contact it will take me to - http://www.example.com/country/contact.
There are a lot of such hard-coded URL, changing it individually will take a lot of time (like appending it with a global variable). Is there any simpler way to do this or is there any config specific for this in laravel? I am fairly new to laravel. Any help would be appreciated.
You can use the somewhat cumbersome solution of applying a filter, as suggested by #worldask, but I think it would be better to set a named route and change all occurrences using a regular expression (any decent editor allows for that). That way, for the lifetime of your application you only need to change the routes in routes.php, and it will be reflected everywhere.
e.g
Route::get('country/contact', ['as' => 'contact',
'uses' => 'SomeController#someFn'];
Contact
Of course, the same principle applies to adding a prefixed group of routes, so you can wrap the entire routes file with a group prefixed by 'country'.
you can try Route Prefixing
Route::group(array('prefix' => 'country'), function(){
Route::get('Contact', 'HomeController#index');
Route::get('another', 'HomeController#index');
});
edit
try route filter
Route::filter('filtername', function($route, $request, $value)
{
if ($route == 'country') {
return Redirect::to(url);
}
});

Categories