multiple prefix with the same route group

12,114

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])
Share:
12,114

Related videos on Youtube

hretic
Author by

hretic

Updated on June 04, 2022

Comments

  • hretic
    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
      Govind Samrow over 6 years
      Name of route is same for all , Use URL::to for for generating route.
  • hretic
    hretic over 6 years
    it's very good but all my links change to last prefix (geography in this example ) ... pleas see the update on my question
  • Govind Samrow
    Govind Samrow over 6 years
    Your 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
    Desh901 over 6 years
    BTW, i agree with @Wreigh about the structure. But you should still be able to do that as i described above.
  • hretic
    hretic over 6 years
    thanx , 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
    Oluwatobi Samuel Omisakin over 6 years
    Just 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
    louisfischer over 6 years
    In 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
    bynicolas over 5 years
    This 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
    louisfischer over 5 years
    You 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
    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
    Hossein Piri over 3 years
    Unfortunately, this is the only way. Otherwise it is not a good way
  • louisfischer
    louisfischer over 3 years
    @HosseinPiri I don't understand what you mean and why the downvote. Can you elaborate please?