I am using laravel framework. I've setup couple of routes that take a parameter like example.com/route/{dir_name}. When I pass in a dir which has childrens it considers it as another route. Is there a way to bypass it?
I'm using this code:
Route::get('/route/something/{path}',array('as'=>'something',function($path){
return $path;
}));
When I use /route/something/home/user/dev it throws a Symfony\Component\HttpKernel\ Exception\NotFoundHttpException exception.
You can try using constraints on the route parameter with a regular expression.
Route::any('/route/{dir_name}', function ($dir_name) {
return $dir_name;
})->where('dir_name', '.*');
See the docs section about route parameters, specifically the "Regular Expression Route Constraints" part.
You have example.com/route/{dir_name}
I assume your route defined in routes.php
Route::get('/route/{dir_name}', [
'as' => 'someRoute',
'uses' => 'SomeController#index'
]);
In your SomeController.php file you would have this method that takes in the {dir_name}
public function index($dir_name) {
return $dir_name;
}
Instead you have the Route
Route::get('/route/something/{path}',array('as'=>'something',function($path){
return $path;
}));
/route/something/{path}
If you want something in your URL then it has to be in the Route. This is why you're getting the NotFoundHttpException
Related
I started creating a REST API using the lumen framework and wanted to set up a particular behaviour for my GET /user route. Behaviour is the following:
If the request come from an authenticated user (using auth middleware), the method getAllFields from UserController is called and return all the data from the user
If it's not the case, the method get from UserController is called and return some of the data from the user
It seems logic to me to just write it like that in my web.php using a simple middleware:
<?php
$router->group(['middleware' => 'auth'], function () use ($router) {
$router->get('/user/{id}', [
'uses' => 'UserController#getAllFields'
]);
});
$router->get('/user/{id}', [
'uses' => 'UserController#get'
]);
But for some reason, even if the middleware is correct, I always get the response of the second route declaration (that call get()). I precise that if I remove the second route declaration, the one in the middleware work as expected.
Have someone an idea how I can achieve something similar that work?
Router will check if your request matches to any declared route. Middleware will run AFTER that match, so You cannot just return to router and try to find another match.
To fallow Laravel and Routes pattern - You should have single route that will point to method inside controller. Then inside that You can check if user is logged or not and execute getAllFields() from that controller. It will be not much to rewrite since You are currently using UserController in both routes anyway.
web.php
$router->get('/user/{id}', 'UserController#get');
UserController.php
public function get()
{
return auth()->check() ? YourMethodForLogged() : YourMethodForNotLogged();
}
Or if there is not much logic You can keep this in single method.
Also it is good idea to fallow Laravels REST standards (so use show instead of get, "users" instead of "user" etc - read more https://laravel.com/docs/7.x/controllers)
web.php
$router->get('/users/{user}', 'UserController#show');
UserController.php
public function show(User $user)
{
if (auth()->check()) {
//
} else {
//
}
}
To summary - for your needs use Auth inside controller instead of middleware.
To check if user is logged You can use Facade Auth::check() or helper auth()->check(), or opposite Auth::guest() or auth()->guest().
If you are actually using Lumen instead of full Laravel then there is not auth helper by default (You can make own or use package like lumen-helpers) or just keep it simple and use just Facades instead (if You have then enabled in Lumen).
Read more https://laravel.com/docs/7.x/authentication and https://lumen.laravel.com/docs/7.x/authentication
This pattern is against the idea of Laravel's routing. Each route should be defined once.
You can define your route without auth middleware enabled and then define your logic in the controller.
I have a PagesController with one action: view.
This action accepts a page argument.
What I want to achieve:
Have a routes example.com/about and example.com/foobar.
When one of this routes is triggered, pass a value predefined in routes file to PagesController#view.
In my routes file:
Route::get('about', function () {
return App::make('App\Http\Controllers\PagesController')->view('about');
})->name('aboutPage');
Route::get('foobar', function () {
return App::make('App\Http\Controllers\PagesController')->view('foobar');
})->name('foobarPage');
It works as expected, but I want to know is there a better and more proper way to achieve the same functionality?
Pass your pages as route parameter:
Route::get('{page}', 'PagesController#view');
//controller
public function view($page)
{
//$page is your value passed by route;
return view($page);
}
So you just want an argument to your action. You can use optional parameters if that argument can be empty. You can read more about it here.
Route::get('{argument?}', 'PagesController#view')->name('page');
And in your PagesController:
public function view($argument = 'default') {
// Your logic
}
The accepted answer is what you want based on what you are doing.
If you really wanted a hardcoded value you can use the 'actions' array part of the route if you wanted.
Route::get('something', ['uses' => 'Controller#page', 'page' => 'something']);
public function page(Request $request)
{
$page = $request->route()->getAction()['page'];
...
}
asklagbox - blog - random tips and tricks
If you don't need the names of the routes like in your example
->name('foobarPage');
you can use something like this
Route::get('{page_name}','PagesController#view')->where('page_name', '(about)|(foobar)');
This will accept only the values passed in the regular expression for the page_name parameter. Other routes will throw a 404 error. I should mention that this technique seems to be valid for applications with one level of url nesting only and should NOT be used as a pattern.
From what I can see above if all you are doing is showing the correct view I would go for
Route::get('{page}', function($page)
{
if (view()->exists($page)) {
return view($page);
}
return abort(404);
});
This prevents you even needing a method in your controller.
I am building a RESTful API using Laravel 5.1.
The default route would be api. The user is allowed to create a url service using as many as parameters as she wants let's say .../api/p1/p2/.../pn.
How do I make a single route to point to a single Controller, so the service will be handled in a single controller?
Note : At first the application just needs to know whether the service exists or not by comparing the url with stored service in the database. As for the service itself, it can be queried into the database later.
I read that we can use * in Laravel 4, how about Laravel 5.1 ?
I have tried :
Route::resource('/api/*', 'APIServiceController'); but it does not work for unlimited parameters
or is it possible to do it like this
Route::group(['prefix' => 'api'], function () {
//what should I put in the closure, how can I redirect it to a single controller
});
Write your route as below:-
Route::group(['prefix' => 'api'], function () {
// this route will basically catch everything that starts with api/routeName
Route::get('routeName/{params?}', function($params= null){
return $params;
})->where('params', '(.*)');
});
Redirect to controller,
Route::group(['prefix' => 'api'], function () {
Route::get('routeName/{params?}', 'YourController#action')->where('params', '(.*)');
});
If you want to make routeName dynamic then just write it in curly bracket as below:-
Route::get('{routeName}/{params?}', 'YourController#action')->where('params', '(.*)');
Hope it will help you :-)
You can try this trick
Route::get('{pageLink}/{otherParams?}', 'IndexController#get')->where('otherParams', '(.*)');
You should put it on the end of routes.php file as it is like a 'catch all' route.
class IndexController extends BaseController {
public function get($pageLink, $otherParams = null)
{
if($otherParams)
{
$otherParams = explode('/', $otherParams);
}
}
}
I'm trying to create a route in Laravel 5.1 that will search the records base on "keyword". I like to include a ? in my url for more readability. The problem is that when I'm including the ? and test the route with postman it returns nothing. But when I remove the ? and replaced it with / and test it with postman again it will return the value of keyword. Does Laravel route supports ??
//Routes.php
Route::get('/search?keyword={keyword}', [
'as' => 'getAllSearchPublications',
'uses' => 'PublicationController#index'
]);
//Publication Controller
public function index($keyword)
{
return $keyword;
}
I've been searching the internet for hours now and I've read the Laravel documentation, But I can't find the answer. Thank you.
I believe you are talking about query strings. To accept query parameters, you don't pass it as an argument. So, for example, your route should look more plain like this:
Route::get('/search', [
'as' => 'getAllSearchPublications',
'uses' => 'PublicationController#index'
]);
Note: I dropped ?keyword={keyword}.
Then, in your controller method, you can grab the query parameter by calling the query method on your Request object.
public function index(Request $request)
{
return $request->query('keyword');
}
If you didn't already, you will need to import use Illuminate\Http\Request; to use the Request class.
Use
$resquest
Parameter in your controller action to get the query parameter. Instead of using "?" to create in your route.
At first it seems that the same routes. But in first route not working middleware that I ordered in the constructor.
How to fix that?
Route::get('/cars.get', function() {
return App::make('App\Http\Controllers\CarsController')->{'get'}();
});
Route::get('/cars.get', 'CarsController#get');
sorry for my English =)
Edit
I was wrong about callAction() it does nothing else than call the method.
Unfortunately there doesn't seem to be a simple API to call middleware manually. A solution to this would just be to define the middleware on the route:
Route::get('/cars.get', ['middleware' => 'auth', function() {
return App::make('App\Http\Controllers\CarsController')->{'get'}();
}]);
original answer:
By directly calling the get() method you skip middleware defined in the controller. You should use callAction() instead:
return App::make('App\Http\Controllers\CarsController')->callAction('get');
Also note that you can use app() as a shortcut for App::make():
return app('App\Http\Controllers\CarsController')->callAction('get');