multiple prefix with the same route group
Solution 1
Why not do it this way:
$subjects = [
'chemistry', 'geography', 'math'
];
foreach ($subjects as $subject) {
Route::prefix($subject)->group(function () {
Route::get('news', 'NewsController@index')->name('news_index');
Route::get('article', 'ArticleController@index')->name('article_index');
});
}
I know this is an elementary way do to it. Yet you can easily add subjects, it is clear and effortless to understand.
Update
As pointed in the comments it could be convenient to name the route as per subject, here is how to do this:
$subjects = [
'chemistry', 'geography', 'math'
];
foreach ($subjects as $subject) {
Route::prefix($subject)->group(function () use ($subject) {
Route::get('news', 'NewsController@index')->name("{$subject}_news_index");
Route::get('article', 'ArticleController@index')->name("{$subject}_article_index");
});
}
Solution 2
I think it's better to do:
Route::get('/news/{group}', 'NewsController@index')->name('news_index')->where('group', 'math|geography|chemistry');
And then just put condition on the controller function whether it is geography/math/chemistry/etc.
Don't you think?
Solution 3
You can try following:
$myroutes = function () {
Route::get('/news', 'NewsController@index')->name('news_index');
Route::get('/article', 'ArticleController@index')->name('article_index');
};
Route::group(['prefix' => 'chemistry'], $myroutes);
Route::group(['prefix' => 'math'], $myroutes);
Route::group(['prefix' => 'geography'], $myroutes);
Use as following:
{!!URL::to('chemistry/news')!!}
{!!URL::to('geography/news')!!}
{!!URL::to('math/news')!!}
Solution 4
You could try to use the as
option within your groups to tell the Router to prepend a string to every route name within that group. To do so try the following:
Route::group(['prefix' => 'chemistry', 'as' => 'chemistry.'], $myroutes);
Route::group(['prefix' => 'math', 'as' => 'math.'], $myroutes);
Route::group(['prefix' => 'geography', 'as' => 'geography.'], $myroutes);
So what you will be able to do should be:
<a href="{{route('chemistry.article_index')}}"> link to article </a>
<a href="{{route('math.article_index')}}"> link to article </a>
<a href="{{route('geography.article_index'}})"> link to article </a>
Hope it helps.
Solution 5
There are several good answers here already, it is probably just a matter of personal preference or deeper project specifics which one suits. Here's another option for the pile.
I am not sure why @Shams answer was downvoted, it seems like the cleanest approach to me - but only if the prefixes are constrained so that only valid subjects are accepted. Something like:
// Only 1 place to update if you add subjects
$subjectRegex = 'math|geography|chemistry';
// Only 1 route per 'group'
Route::get('{subject}/news', 'NewsController@index')->name('news_index')->where('subject', $subjectRegex);
Route::get('{subject}/article', 'ArticleController@index')->name('article_index')->where('subject', $subjectRegex);
As a bonus you have $subject
available in your Controller methods, which seems like it might be useful, for example you can use it to generate routes within the current subject:
route('article_index', ['subject' => $subject])
Related videos on Youtube
hretic
Updated on June 04, 2022Comments
-
hretic almost 2 years
im writing a fairly simple website for a school ... this website has news , articles , video clips ... etc
the way it works is in the home page we present visitor with some lessons like
>math >geography >chemistry
user selects 1 on these and website contents changes based on the user selection
for example if user selects math he will see news , article , videos about math and so on ... right now this is what im doing (pleas ignore syntax errors)
Route::group(['prefix'=>'math'], function () { Route::get('/news', 'NewsController@index')->name('news_index'); Route::get('/article', 'ArticleController@index')->name('article_index'); }); Route::group(['prefix'=>'geography'], function () { Route::get('/news', 'NewsController@index')->name('news_index'); Route::get('/article', 'ArticleController@index')->name('article_index'); }); Route::group(['prefix'=>'chemistry'], function () { Route::get('/news', 'NewsController@index')->name('news_index'); Route::get('/article', 'ArticleController@index')->name('article_index'); });
basically repeating all links for each prefix .... but as the links grow it will become more and more unmanageable ... is there any better way to do this ? something like
Route::group(['prefix'=>['chemistry','math' , 'geography' ], function () { Route::get('/news', 'NewsController@index')->name('news_index'); Route::get('/article', 'ArticleController@index')->name('article_index'); });
------------------------- update -------------
i've tried this
$myroutes = function () { Route::get('/news', 'NewsController@index')->name('news_index'); Route::get('/article', 'ArticleController@index')->name('article_index'); }; Route::group(['prefix' => 'chemistry'], $myroutes); Route::group(['prefix' => 'math'], $myroutes); Route::group(['prefix' => 'geography'], $myroutes);
and it works fine , the problem is the last prefix gets attached to all the internal links
for example if i click on math
my links will be
site.com/math/news
but all the links on the loaded page like
<a href="{{route('article_index')"> link to article </a>
look like
site.com/geography/article
basically link get the last mentioned prefix regardless of currently selected one
-
Govind Samrow over 6 yearsName of route is same for all , Use URL::to for for generating route.
-
-
hretic over 6 yearsit's very good but all my links change to last prefix (geography in this example ) ... pleas see the update on my question
-
Govind Samrow over 6 yearsYour doing it wrong way , its all ways return last because you are calling the via name because the name is same for all that why it return last one. I've updated my answer try this
-
Desh901 over 6 yearsBTW, i agree with @Wreigh about the structure. But you should still be able to do that as i described above.
-
hretic over 6 yearsthanx , i'll try this but i have to say since all the routes are using same controllers/views the argument in
route('subject.news','math')
should be dynamically set to the current one ... i guess i can use a middleware to read the current prefix from route and make it available in the view -
Oluwatobi Samuel Omisakin over 6 yearsJust give it a try... the only time you will have to set that route is if you want to generate a url for any of them...so you can specify which one you want to generate...
-
louisfischer over 6 yearsIn this case, it could be good to add some constraints like this:
Route::get('/news/{group}', 'NewsController@index')->name('news_index')->where('group', 'math|geography|chemistry');
-
bynicolas over 5 yearsThis is a great answer, but the name of the route is the same for every subject, you won't be able to call the correct route when rendering/calling the route with
{{ route( 'news_index
) }} (you want news for which subject?) in your template (or anywhere else within your code) . Maybe add a discriminator in front of the route name like so->name( $subject . '.news_index' );
This will allow calling{{ route( 'math.news_index' ) }}
-
louisfischer over 5 yearsYou are completely right @bynicolas. I did not take care of this in my answer because it was not a requirement of the question. It is good to point this out though. As you said it is very convenient to generate URLs by their name, whether it is from a Blade template or in an API resource class.
-
Biniyam Asnake about 4 years@bynicolas By the way, it is not possible to append the the $subject to the route parameter as the variable is not available once in the group expression. Try it.
-
Hossein Piri over 3 yearsUnfortunately, this is the only way. Otherwise it is not a good way
-
louisfischer over 3 years@HosseinPiri I don't understand what you mean and why the downvote. Can you elaborate please?