I am trying to use a method to implement accept/reject since I will be updating the same model with just little difference.
How can I pass a parameter to a controller method directly from Laravel Routes (i.e. instead of being supplied via url).
E.g. something like:
Route::put('/friends/{friend}/reject', ['as' => 'friends.reject', 'uses' => 'FriendsController#accept', 'accept' => false]);
Route::put('/friends/{friend}/accept', ['as' => 'friends.reject', 'uses' => 'FriendsController#accept']);
My controller code looks like:
public function accept($friend, $accept = true)
{
...
Is it possible to define the $accept parameter inside the Routes config file?
I have an improvement over the answer you found yourself. By adding a route constraint you make sure that only the two verbs are allowed.
Also I changed the naming to make more sense. If it doesn't, just change it ;)
Route::put('/friends/{friend}/{verb}',
['as' => 'friends.respond-to-request',
'uses' => 'FriendsController#respondToRequest']
)->where('verb', '(accept|reject)');
You can use this solution:
Route::put('/friends/{friend}/reject',array('as' => 'friends.reject',function($friend){
$accept = false;
$app = app();
$controller = $app->make('FriendsController');
$controller->callAction($app, $app['router'], 'accept', $parameters = array($friend, $accept));
}));
This code uses a Closure. In this closure the controller will be dispatched by laravel's router.
I finally resorted to:
Route::put('/friends/{friend}/{verb}', ['as' => 'friends.reject', 'uses' => 'FriendsController#accept']);
public function accept($friend, $verb = 'accept')
{
...//check if `verb` is 'accept' or 'reject' here..
I am not sure this is an ideal solution though, maybe it's better to implement with integer but it's possible Laravel processes both the same way.
Related
Hi I have the following Lumen Route
$router->get('/end', function (\Illuminate\Http\Request $request) use ($router) {
$controller = $router->app->make('App\Http\Controllers\Legacy\EndLegacyController');
return $controller->index($request);
});
I am trying to give it a route name so that I can use redirect to redirect to this route like redirect()->route('name_of_route')
so far I have tried
})->namedRoute['end'] = '/end'; // No Effect
})->name('end') //Undefined function
but it didn't work
here's a list of present routes
Edit
Because of my certain requirement, I can't use ['as' => 'end', 'uses'=> 'ControllerName#Action']
you can use the following syntax: $router->get('/end', ['as'=>'name_here', function()]);
I have following 2 routes :
Route1:
Route::get(config('api.basepath') . '{username}/{hash}/{object_id}', [
'action' => 'getObject',
'uses' => 'ObjectController#getObject',
]);
and
Route2:
Route::get(config('api.basepath') . 'object-boxes/{object_id}/boxes', function () {
if (Input::get('action') == 'filter') {
return App::call('App\Http\Controllers\FilterController#getFilteredContents');
} else {
return App::call('App\Http\Controllers\ObjectBoxController#show');
}
});
Now,
Route 1 is available with or without Auth middleware, while Route2 is under Auth middleware.
But, In either call, execution control is going to ObjectController#getObject
When I move Route1 below Route2, then everytime the call goes to ObjectBoxController#show.
I tried Preceed but nothing changed.
How should I fix this
Your first and second route are similar,
First Route
config('api.basepath') . '{username}/{hash}/{object_id}'
Second Route
config('api.basepath') . 'object-boxes/{object_id}/boxes'
when you have second route case, it has been treated as former one and takes username as object-boxes and object_id as boxes. So same function is called for both cases. So, try with something different route pattern for these two routes.
You should define what the variables in the routes are going to be, not the where at the end of each route:
Route::get(config('api.basepath') . '{username}/{hash}/{object_id}', [
'action' => 'getObject',
'uses' => 'ObjectController#getObject',
])->where('object_id', '[0-9]+');
Route::get(config('api.basepath') . 'object-boxes/{object_id}/boxes', function () {
if (Input::get('action') == 'filter') {
return App::call('App\Http\Controllers\FilterController#getFilteredContents');
} else {
return App::call('App\Http\Controllers\ObjectBoxController#show');
}
})->where('object_id', '[0-9]+');
You may constrain the format of your route parameters using the where method on a route instance. The where method accepts the name of the parameter and a regular expression defining how the parameter should be constrained:
Read the documentation here
I want to add multilanguage functionality to existing laravel project. Currently I have the following route:
$user_route = function() {
....
};
Route::group([
'prefix' => ''
], $user_route
);
Route::group([
'prefix' => '{language}',
'middleware' => 'set.lang'
], $user_route
);
Each anchor uses route() helper from Laravel. Since I have route with 'language' prefix, I need to pass $language from every route(). There are lot of route() and I don't think updating every route to route('name', ['language' => \App::getLocale()]) is a good option. The project already have Helper class and I plan to override route() method from Illuminate\Routing\UrlGenerator with my custom method. This is what I have tried :
Functions.php
use Illuminate\Routing\UrlGenerator as Url;
....
function route($name, $parameters = [], $absolute = true)
{
$parameters = array_add($parameters, 'language', \App::getLocale());
$url = new Url();
return $url->route($name, $parameters, $absolute);
}
Which obviously return error :
FatalErrorException in Functions.php line 158:
Cannot redeclare route() (previously declared in
C:\...\vendor\laravel\framework\src\Illuminate\Foundation\helpers.php:693)
I read about Service Container but as far as my understanding, only used to manage class dependencies and performing dependency injection. How to handle this correctly? Thank you very much for your help.
So the title describes my problem pretty well I think, but let me explain why I want to do this as theremight be an other solution to my problem that I haven't thought about.
Let's say that I have a route specifying the class of the object it will patch:
Route::patch('{class}/{id}', array(
'as' => 'object.update',
function ($class, $id) {
$response = ...;
// here I want to call the update action of the right controller which will
// be named for instance CarController if $class is set to "car")
return $response;
}
));
This is something pretty easy to do with $app->make($controllerClass)->callAction($action, $parameters); but doing it this way won't call the filters set on the controller.
I was able to do it with laravel 4.0 with the callAction method, passing the app and its router, but the method has changed now and the filters are called in the ControllerDispatcher class instead of the Controller class.
If you have routes declared for your classes then you may use something like this:
$request = Request::create('car/update', 'POST', array('id' => 10));
return Route::dispatch($request)->getContent();
In this case you have to declare this in routes.php file:
Route::post('car/update/{id}', 'CarController#update');
If you Use this approach then filters will be executed automatically.
Also you may call any filter like this (not tested but should work IMO):
$response = Route::callRouteFilter('filtername', 'filter parameter array', Route::current(), Request::instance());
If your filter returns any response then $response will contain that, here filter parameter array is the parameter for the filter (if there is any used) for example:
Route::filter('aFilter', function($route, $request, $param){
// ...
});
If you have a route like this:
Route::get('someurl', array('before' => 'aFilter:a_parameter', 'uses' => 'someClass'));
Then the a_parameter will be available in the $param variable in your aFilter filter's action.
So I might have found a solution to my problem, it might not be the best solution but it works. Don't hesitate to propose a better solution!
Route::patch('{class}/{id}', array(
'as' => 'object.update',
function ($class, $id) {
$router = app()['router']; // get router
$route = $router->current(); // get current route
$request = Request::instance(); // get http request
$controller = camel_case($class) . 'Controller'; // generate controller name
$action = 'update'; // action is update
$dispatcher = $router->getControllerDispatcher(); // get the dispatcher
// now we can call the dispatch method from the dispatcher which returns the
// controller action's response executing the filters
return $dispatcher->dispatch($route, $request, $controller, $action);
}
));
I'm unit testing my application and I get a NotFoundHttpException when trying to call controller actions with TestCase::callSecure() and the route() helper.
For those tests (only a few) I have also enabled filters with Route::enableFilters.
My filters.php:
App::before(
function ($request) {
// force ssl
if (!$request->isSecure())
{
return Redirect::secure($request->getRequestUri());
}
}
);
// some authentication
Route::filter('auth.api', 'Authentication');
My routes.php:
Route::post('login', array('as' => 'login', 'uses' => 'AuthenticationController#login'));
Route::post('register', array('as' => 'register', 'uses' => 'AuthenticationController#register'));
Example Test where i get the exception:
$credentials = [
// ...
];
$response = $this->callSecure('POST', route('login'), $credentials);
When i call those actions by their path, it works fine.
$credentials = [
// ...
];
$response = $this->callSecure('POST', '/login', $credentials);
Is this intended or a bug?
The route() helper will generate a URL (including the relevant protocol, i.e. http/s) for the given named route. In your case, it'll return something like:
https://example.com/login
Which isn't what you want. This is useful when you want to perform a redirect, for example:
Redirect::route('login');
So what you're doing in your last example, is the correct way to be doing what you want; as you don't want to pass the full URL as a parameter to your callSecure() function.
$response = $this->callSecure('POST', '/login', $credentials);
And as dave has mentioned, you can generate a relative URL by using URL::route and pass an $absolute parameter which defaults to true. For example, when using named routes you can use the following:
$route = URL::route('profile', array(), false);
Which will generate a relative URL like /profile
The route() helper does not create relative URLs, which is what you really want.
To generate a relative URL, you can use URL::route as it allows you to pass a $absolute parameter which defaults to true. So to get your relative url using a named route, you could do
$credentials = [
// ...
];
$route = URL::route('login', array(), false);
$response = $this->callSecure('POST', $route, $credentials);
While the '/login' method is correct, it defeats the purpose of using named routes if you still have to hunt down all the places where you have that URL if/when you decide to change it.