Laravel routing to wrong controller method - php

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

Related

How do I give route name to a closure route in Lumen?

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()]);

Laravel: Print the current route, with a different parameter

Considering the following route group in Laravel 5:
Route::prefix('{locale}')->group(function () {
// ... Other routes here
});
All routes that are nested within this route group have views that extend a certain layout.
Somewhere in this layout I loop all available locales in my application, and I put links to change to this locale. What would be the easiest way to print these links in my view, keeping the current route and possibly the other route parameters but changing only the {locale} parameter?
Had this problem and came up with this:
app('url')->toRoute(
request()->route(),
array_merge(request()->route()->parameters(), ['locale' => $otherLocale]),
true
);
You could turn it into a helper like route:
function current_route($params = [], $absolute = true)
{
return app('url')->toRoute(
request()->route(),
array_merge(request()->route()->parameters(), $params),
$absolute
);
}
and call it with current_route(['locale' => 'sv'])
Maybe just Type-hint the request and pass the prefix into your view through your controller and use it in your links:
public function ControllerWithLocaleLinks(Request $request)
{
$currentLocale = $request->route()->getPrefix();
return view('locale', compact('currentLocale'));
}

Call to a member function name() on null in laravel 5.4

When pressing my send button it's giving error like this-
Here is my routes web.php bellow-
Route::group(['prefix'=>'ajax', 'as'=>'ajax::'], function() {
Route::resource('message/send', 'MessageController#ajaxSendMessage')->name('message.new');
Route::delete('message/delete/{id}', 'MessageController#ajaxDeleteMessage')->name('message.delete');
});
Here is my controller MessageController.php bellow:
public function ajaxSendMessage(Request $request)
{
if ($request->ajax()) {
$rules = [
'message-data'=>'required',
'_id'=>'required'
];
$this->validate($request, $rules);
$body = $request->input('message-data');
$userId = $request->input('_id');
if ($message = Talk::sendMessageByUserId($userId, $body)) {
$html = view('ajax.newMessageHtml', compact('message'))->render();
return response()->json(['status'=>'success', 'html'=>$html], 200);
}
}
}
Resource routes should be named differently:
Route::prefix('ajax')->group(function () {
Route::resource('messages', 'MessageController', ['names' => [
'create' => 'message.new',
'destroy' => 'message.destroy',
]]);
});
Resource routes also point to a controller, instead of a specific method. In MessageController, you should add create and destroy methods.
More info at https://laravel.com/docs/5.4/controllers#restful-naming-resource-routes
You can't name a resource. Laravel by default name it, if you want to name all routes you must specify each one explicitly. It should be like this:
Route::group(['prefix'=>'ajax', 'as'=>'ajax::'], function() {
Route::get('message/send', 'MessageController#ajaxSendMessage')->name('message.new');
Route::delete('message/delete/{id}', 'MessageController#ajaxDeleteMessage')->name('message.delete');
});
Update
Another mistake of yours was trying to resource a single method. A Route::resource() is used to map all basic CRUD routes in Laravel by default. Therefore, you have to pass the base route and the class i.e:
<?php
Route::resource('message', 'MessageController');
Look at web.php line 28.
Whatever object you think has a name() method, hasn't been set, therefore you try and call a method on null.
Look before that line and see where it is (supposed to be) defined, and make sure it is set to what it should be!

Laravel, same URI, different route name, different middleware causes over loop

In laravel I've simply done this:
Route::group(["middleware" => "admin"], function() {
Route::get("/", "UserController#index")->name("user_index");
});
Route::group(["middleware" => "user", "as" => "User::"], function() {
Route::get("/", "DocumentController#index")->name("user_index");
});
The problem is when I am logged in as my Admin auth middleware, when going to "/" my browser returns too many redirects and stops. I'm guessing because the second route is removing this as when I print out php artisan route:list there is only one result for "/" and that's with the user middle's parameters so it's defo overriding the previous route.
What I don't understand is why would it do this is both have a separate middleware?
Both middlewares are extremely simple. Below is my admin
public function handle($request, Closure $next)
{
if ( Auth::check() && Auth::user()->hasRole("customer_service") )
{
return $next($request);
}
return redirect("/");
}
And my user's middleware is exactly alike except the role is different
This is probably wrong but this is what I did to fix this particular issue with the above.
public function index() {
return \Auth::user()->hasRole("trainer") ? \App::call("App\Http\Controllers\Trainer\UserController#index")
: \App::call("App\Http\Controllers\User\UserController#index");
}

How to pass parameter to Controller method referenced in Laravel Routes?

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.

Categories