I have a single domain/subdomain project. In order to see the event by slug, I made this route:
Route::prefix('events')->namespace('Content\Controller')->group(function () {
Route::get('/', 'EventController#getIndex')->name('event.index');
Route::get('{slug}', 'EventController#getView')->name('event.show');
Route::get('{slug}/edit', 'EventController#getEdit')->name('event.edit');
Route::post('load-more-ajax/{region?}', 'EventController#postLoadMoreAjax');
Route::any('sorted-ajax/{region?}', 'EventController#anySortedAjax');
Route::get('category/{category_slug}/{subcategory_slug?}', 'EventController#getCategory');
});
After my page didn't load correctly, I did a dump in the controller:
public function getView($slug)
{
return $slug;
}
To get to the route I am using this URL: https://example.com/events/slug-example.
The problem is that the route is being hit as I see the response when I change it, but I am not getting the slug, instead I am getting Region object back.
If I do this:
public function getView($region, $slug)
{
return $slug;
}
Then I get the slug back. But I have no idea how is this possible, and how could I do it (I came as another dev on the existing project).
I tried commenting out all the middleware and it is still the same. How can I even make something fill the method if I didn't explicitly say it?
EDIT
I noticed there is binding going on in routes file:
Route::bind('region', function ($value) {
...
});
Now if I dd($value) I get the variable back. How is this value filled? From where could it be forwarded?
Looking quickly it should work, but maybe you was verifying other url.
Make sure you put:
Route::get('{slug}', 'EventController#getView')->name('event.show');
Route::get('{slug}/edit', 'EventController#getEdit')->name('event.edit');
routes at the end of routes you showed.
EDIT
If you think that's not the case and you don't have your routes cached you should run:
php artisan route:list
to verify your routes.
EDIT2
After explaining by OPs in comment, domain used for accessing site is:
{region}.example.com
So having $region in controller as 1st parameter is correct behaviour because of route model binding and other route parameters will be 2nd, 3rd and so on.
Instead of
Route::prefix('events')->namespace('Content\Controller')->group(function () {
Route::get('/', 'EventController#getIndex')->name('event.index');
Route::get('{slug}', 'EventController#getView')->name('event.show');
Route::get('{slug}/edit', 'EventController#getEdit')->name('event.edit');
Route::post('load-more-ajax/{region?}', 'EventController#postLoadMoreAjax');
Route::any('sorted-ajax/{region?}', 'EventController#anySortedAjax');
Route::get('category/{category_slug}/{subcategory_slug?}', 'EventController#getCategory');
});
try
Route::prefix('events')->namespace('Content\Controller')->group(function () {
Route::get('/', 'EventController#getIndex')->name('event.index');
Route::post('load-more-ajax/{region?}', 'EventController#postLoadMoreAjax');
Route::any('sorted-ajax/{region?}', 'EventController#anySortedAjax');
Route::get('category/{category_slug}/{subcategory_slug?}', 'EventController#getCategory');
Route::get('{slug}', 'EventController#getView')->name('event.show');
Route::get('{slug}/edit', 'EventController#getEdit')->name('event.edit');
});
Related
Below is an example of the route definition in my routes/web.php file.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\WidgetController;
Route::controller(WidgetController::class)->name('widgets.')->prefix('widgets')->group(function () {
Route::get('{id}/{slug}', 'show')->name('show');
Route::get('create', 'create')->name('create')->middleware('auth');
Route::post('store', 'store')->name('store')->middleware('auth');
Route::get('{id}/edit', 'edit')->name('edit')->middleware('auth');
Route::post('update', 'update')->name('update')->middleware('auth');
});
All the routes listed work fine except for one.
Route::get('{id}/edit', 'edit')->name('edit')->middleware('auth');
For whatever reason, it works completely fine when it's written like this:
Route::get('{id}', 'edit')->name('edit')->middleware('auth');
or this:
Route::get('{id}//edit', 'edit')->name('edit')->middleware('auth');
With "Route::resource", the default would be the first "edit" route. However, I get a 404 when defining it like that. My associated controller method is written like this:
public function edit($id)
{
// Rest of code here
}
Could it be that Laravel is mistaking "edit" as a second parameter? But that doesn't really make much sense considering it's the default for the resource method.
Try putting
Route::get('{id}/edit', 'edit')->nam
Above
Route::get('{id}/{slug}'
Since {slug} could be anything it's more then likely getting executed first. I would suggest putting that last.
Any help why this is not working ,I am using Laravel 5.5.23 version ,this is are my routes :
<?php
Route::get('/', function () {
return view('welcome');
});
Route::resource('threads','ThreadController');
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::get('threads','ThreadController#index');
Route::get('threads/{channel}','ThreadController#index');
Route::get('threads/create','ThreadController#create');
Route::get('threads/{channel}/{thread}','ThreadController#show');
Route::post('threads','ThreadController#store');
Route::post('/threads/{channel}/{thread}/replies','ReplyController#store');
Route::get('/logout' , 'Auth\LoginController#logout');
This is the ThreadController ,just the relevant methods actually :
public function __construct()
{
$this->middleware('auth')->except(['index','show']);
}
public function index($channel = null)
{
if($channel){
//do something
}
else{
$threads=Thread::latest()->get();
}
return view('threads.index',compact('threads'));
}
The problem is when I try to access /threads/someChannel it returns not found ,so this is the problematic route : Route::get('threads/{channel}','ThreadController#index'); ,all other routes are working ,any idea why this one is not working ?
The Route::resource('threads','ThreadController') call is defining 7 routes with the prefix threads. Some of the routes you are defining yourself are being masked by this. Check php artisan route:list to see what routes the Route::resource call registers for you first. First come first serve when it comes to matching routes.
/threads/someChannel is going to match the route defined by the resource call:
GET /threads/{thread} ThreadController#show
Since you don't have the definition for show which is relevant to have, I would assume you have Implicit Model Binding happening. It is trying to bind that model to that parameter and it can't find it in the database by that ID and is causing a 404 because of it.
I have this code in api.php routes file for laravel 5.4
Route::get('/lectures/{id}', function ()
{
dd("lecture route");
});
Route::get('/lectures/send-request', function ()
{
dd("send-request route");
});
the problem is that when I visit localhost:8000/api/lectures/send-request the output is 'lecture route' which is for this url localhost:8000/api/lectures/{id}
but when I change the orders of routes it will work properly
Route::get('/lectures/send-request', function ()
{
dd("send-request route");
});
Route::get('/lectures/{id}', function ()
{
dd("lecture route");
});
now when I visit localhost:8000/api/lectures/send-request the output is 'send-request route'
so what is wrong ? why this is happening ?
The routes are working exactly as intended. The routes take precedence the same way they're defined.
GET /lectures/{id}
GET /lectures/send-request
You've defined two routes where the second route is basically one of options of the first route. When you access /lectures/send-request it satisfies the condition for the route /lectures/{id} with id set to send-request.
You can switch the order of routes based on your preference, or you could change one of the route.
This is because Laravel matches routes top-down. This means that the first route to match is the one being used. /lectures/send-request matches '/lectures/{id}' and sets $id to 'send-request'.
Let's say I am defining the following route in Laravel 5.3:
Route::resource('bands', 'BandController');
The default route example coming when you start a new Laravel project has the following:
Route::get('/', function () {
return view('welcome');
});
How do I make bands route to be the default one when no controller is called instead of welcome? Meaning /?
I did read docs here but didn't found anything. Any?
Place that block inside laravel/app/routes.php instead of a Controller (4.x)
Place that block inside laravel/app/Http/routes.php instead of a Controller (5.1)
Place that block inside laravel/app/routes/web.php instead of a Controller (5.3)
Route::get('/', function()
{
return view('welcome');
});
You can redirect default to anywhere you want, i.e.:
Route::get('/', function()
{
return Redirect::to( '/bands');
// OR: return Redirect::intended('/bands'); // if using authentication
});
As #Patrick mentioned, you can simply redirect to the /bands route. However, I have to warn you that the redirect will actually change the URL in the navigation pane of the web browser. I would have suggested that you just ask the home route to use the index method of your BandController as follows:
Route::get('/', ['uses'=>'BandController#index']);
I have a middleware that detects if a user owns a tournament.
So, if user want to edit a tournament he doesn't own, he will get a 403.
Thing is I can't make difference between laravel.dev/tournament/1/edit, and laravel.devl/tournament/1
Off course, I could check the "edit" word in URL, but I would prefer other better param...
I tried method param in Request Object, but it is giving me GET for both, so I can't make difference...
Any Idea???
In your case, you can do like this:
$request->route()->getName();
Now you can do your logic based on this.
What about using a different HTTP method for edit, e.g PATCH or PUT and declaring two different routes, something like:
Route::get('laravel.devl/tournament/1', 'TournamentController#showTournament');
Route::put('laravel.dev/tournament/1/edit', 'TournamentController#editTournament');
Then in the TournamentController you can check if the user has rights to edit.
It sounds like you should just use route specific middleware instead of global middleware. See https://laravel.com/docs/master/middleware#assigning-middleware-to-routes. Then you can just do:
Route::get('/tournament/{id}/edit', ['middleware' => ['tournamentOwner'], function () {
//
}]);
Route::get('/tournament/{id}', ['middleware' => [], function () {
//
}]);
If it's a RESTful route, you can just do:
public function __construct()
{
$this->middleware('tournamentOwner', ['only' => ['edit']]);
}