How can I make a router like this
Route::any("/{controller}/{method}/{param}", "$controller#$method");
So that instead of specifing every single method in the routes file, I would be able to define a route for most cases for the convention http://example.com/controller/method/param
In Laravel 4.2 you can use [implicit controller][1].
Laravel allows you to easily define a single route to handle every action in a controller. First, define the route using the Route::controller method:
Route::controller('users', 'UserController');
The controller method accepts two arguments. The first is the base URI the controller handles, while the second is the class name of the controller. Next, just add methods to your controller, prefixed with the HTTP verb they respond to:
class UserController extends BaseController {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
}
https://laravel.com/docs/4.2/controllers#implicit-controllers
Like this:
Route::any('{controller}/{method}/{param}', function ($controller, $method, $param) {
return call_user_func_array($controller.'::'.$method, $param);
});
Related
I am using api throttle in my routes/api.php (as you can see in the code) but I am wondering if I can use it in the controller on methods.
Route::resource('/user/{user}/post', 'UserPostController')->middleware(['auth:api', 'throttle:5,1']);
Better to use the routes to specify the middleware for the routes. Still you think to use / specify inside your controller you can define __construct() menthod in your controller like:
public function __construct()
{
$this->middleware('throttle:5,1')->only('index');
}
This will work on the index action of your controller only.
For more details check the documentation Controller Middlewares
you can override route for example
Route::resource('/user/{user}/post', 'UserPostController')->middleware(['auth:api', 'throttle:5,1']);
//add route after resource
Route::get('/user/create', 'UserPostController#create')->middleware(['auth:api', 'throttle:5,1']);
second way add condition in controller
public function __construct()
{
$this->middleware('auth:api');
$this->middleware('throttle:10,1')->only('create');
}
With Slim I group my controllers and generally have an abstract BaseController I extend for each group. I use class based routing:
/* SLIM 2.0 */
// Users API - extends BaseApiController
$app->post('/users/insert/' , 'Controller\Api\UserApiController:insert');
.
.
// Campaigns - extends BaseAdminController
$app->get('/campaigns/', 'Controller\CampaignController:index')->name('campaigns');
and needed to password protect some routes, at other times I needed to have a slightly different configuration. BaseApiController, BaseAdminController... etc. There were times I needed to know which route I was in so I could execute a certain behavior for just that route. In those cases I would have a helper function like so:
/* SLIM 2.0 */
// returns the current route's name
function getRouteName()
{
return Slim\Slim::getInstance()->router()->getCurrentRoute()->getName();
}
This would give me the route name that is currently being used. So I could do something like...
namespace Controller;
abstract class BaseController
{
public function __construct()
{
/* SLIM 2.0 */
// Do not force to login page if in the following routes
if(!in_array(getRouteName(), ['login', 'register', 'sign-out']))
{
header('Location: ' . urlFor('login'));
}
}
}
I cannot find a way to access the route name being executed. I found this link
Slim 3 get current route in middleware
but I get NULL when I try
$request->getAttribute('routeInfo');
I have also tried the suggested:
'determineRouteBeforeAppMiddleware' => true
I've inspected every Slim3 object for properties and methods, I can't seem to find the equivalent for Slim3, or get access to the named route. It doesn't appear that Slim3 even keeps track of what route it executed, it just... executes it.
These are the following methods the router class has and where I suspect this value would be:
//get_class_methods($container->get('router'));
setBasePath
map
dispatch
setDispatcher
getRoutes
getNamedRoute
pushGroup
popGroup
lookupRoute
relativePathFor
pathFor
urlFor
I was hoping someone has done something similar. Sure, there are other hacky ways I could do this ( some I'm already contemplating now ) but I'd prefer using Slim to give me this data. Any Ideas?
NOTE: I'm aware you can do this with middleware, however I'm looking for a solution that will not require middleware. Something that I can use inside the class thats being instantiated by the triggered route. It was possible with Slim2, was hoping that Slim3 had a similar feature.
It's available via the request object, like this:
$request->getAttribute('route')->getName();
Some more details available here
The methods in your controller will all accept request and response as parameters - slim will pass them through for you, so for example in your insert() method:
use \Psr\Http\Message\ServerRequestInterface as request;
class UserApiController {
public function insert( request $request ) {
// handle request here, or pass it on to a getRouteName() method
}
}
After playing around I found a way to do it. It may not be the most efficient way but it works, and although it uses Middleware to accomplish this I think there are other applications for sharing data in the Middleware with controller classes.
First you create a middleware but you use a "Class:Method" string just like you would in a route. Name it whatever you like.
//Middleware to get route name
$app->add('\Middleware\RouteMiddleware:getName');
Then your middleware:
// RouteMiddleware.php
namespace Middleware;
class RouteMiddleware
{
protected $c; // container
public function __construct($c)
{
$this->c = $c; // store the instance as a property
}
public function getName($request, $response, $next)
{
// create a new property in the container to hold the route name
// for later use in ANY controller constructor being
// instantiated by the router
$this->c['currentRoute'] = $request->getAttribute('route')->getName();
return $next($request, $response);
}
}
Then in your routes you create a route with a route name, in this case I'll use "homePage" as the name
// routes.php
$app->get('/home/', 'Controller\HomeController:index')->setName('homePage');
And in your class controller
// HomeController.php
namespace Controller;
class HomeController
{
public function __construct($c)
{
$c->get('currentRoute'); // will give you "homePage"
}
}
This would allow you to do much more then just get a route name, you can also pass values from the middleware to your class constructors.
If anyone else has a better solution please share!
$app->getCurrentRoute()->getName();
$request->getAttribute('route')->getName();
i want to call the controller => function without specifying in route in Laravel 5.1.
such as controller / function
Example: admin/delete
so i want to call the above controller's function without specifying in routes is their any way to do that?
Also, if it is possible then how to pass parameters to that function?
I think you are looking for RESTful Controllers.
So in your route file you only have:
Route::controller('admin', 'AdminController');
and in your controller:
class AdminController extends BaseController {
public function show($adminId)
{
//
}
public function destroy($adminId)
{
//
}
}
In my routes files I have a bunch or routes for testing purposes:
/** testing controllers */
Route::get('viewemail', 'TestController#viewemail');
Route::get('restore', 'TestController#restore');
Route::get('sendemail', 'TestController#send_email');
Route::get('socket', 'TestController#socket');
Route::get('colors', 'TestController#colors');
Route::get('view', 'TestController#view_test');
Route::get('numbers', 'TestController#numbers');
Route::get('ncf', 'TestController#ncf');
Route::get('dates', 'TestController#dates');
Route::get('print', 'TestController#printer');
Route::get('{variable}', 'TestController#execute');
/** End of testing controllers */
I want to eliminate all those routes and simple use the name of the given URL to call and return the method:
I have accomplished that in this way:
Route::get('{variable}', 'TestController#execute');
And in my testing controller:
public function execute($method){
return $this->$method();
}
Basically what I want to know if Laravel has a built in solution to do this, I was reading the documentation but couldn't find any way to accomplish this.
From official documentation:
http://laravel.com/docs/5.1/controllers#implicit-controllers
Laravel allows you to easily define a single route to handle every
action in a controller class. First, define the route using the
Route::controller method. The controller method accepts two
arguments. The first is the base URI the controller handles, while the
second is the class name of the controller:
Route::controller('users', 'UserController');
Next, just add methods to your controller. The method names should begin with the
HTTP verb they respond to followed by the title case version of the
URI:
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
/**
* Responds to requests to GET /users
*/
public function getIndex()
{
//
}
/**
* Responds to requests to GET /users/show/1
*/
public function getShow($id)
{
//
}
/**
* Responds to requests to GET /users/admin-profile
*/
public function getAdminProfile()
{
//
}
/**
* Responds to requests to POST /users/profile
*/
public function postProfile()
{
//
}
}
As you can see in the example above, index methods will respond to the
root URI handled by the controller, which, in this case, is users.
You could add a route pattern for the endpoints you want to listen for. Route them to a controller action, and then inspect the request:
class TestController extends Controller
{
public function handle(Request $request)
{
$method = $request->segment(1); // Gets first segment of URI
// Do something…
}
}
And in your route service provider:
$router->pattern('{variable}', 'foo|bar|qux|baz');
I know i can do this
Route::get('foo/bar', array('before' => 'filter', 'uses' => 'Controller#bar'));
to apply routes some filter. I am aware of Route::group() method too. Anyway, if i want to define a controller in this way
Route::controller('foo/{id}/bar', 'Controller');
i can not pass an array as the 2nd argument.
The question: how to apply filters to the following route?
Route::controller('foo/{id}/bar', 'Controller');
=== EDIT
I want to code this in my route.php, not inside a controller constructor.
In the constructor of your controller you may use
public function __construct()
{
$this->beforeFilter('auth');
}
Also, you can use
Route::group(array('before' => 'auth'), function() {
Route::controller(...);
});
Blockquote The controller method accepts two arguments. The first is the base URI the controller handles, while the second is the class name of the controller. Next, just add methods to your controller, prefixed with the HTTP verb they respond to.
The Route::controller is responsible of creating a group of route using REST naming conventions. Is thought for creating RESTFull services.
Blockquote Filters may be specified on controller routes similar to "regular" routes:
Because this function only allows two params, you can apply controller filters in the constructor. For example:
class RoutedController extends Controller
{
public function __construct()
{
//Apply Auth filter to all controller methods
$this->filter('before', 'auth');
}
}
You can read about the controller filters in the Laravel docs: http://laravel.com/docs/controllers#controller-filters