hretic
hretic

Reputation: 1095

multiple prefix with the same route group

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

Upvotes: 26

Views: 17401

Answers (8)

louisfischer
louisfischer

Reputation: 2084

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");
    });
}

Upvotes: 26

Wreigh
Wreigh

Reputation: 3297

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?

Upvotes: 12

Norris Oduro
Norris Oduro

Reputation: 1039

You can wildcard the route group and specify the preferred prefixes in your RouteServiceProvider

routes.php

Route::group(['prefix'=>'{slug}'],function (){
 Route::get('/news', 'NewsController@index')->name('news_index');
 Route::get('/article', 'ArticleController@index')->name('article_index');
});

RouteServiceProvider boot method

Route::bind('slug',function ($name){
   $prefix = ["math","chemistry","geography"];
    if(!in_array($name,$prefix))
     {
        //handle wrong prefixes
        throw new \Exception("Something went wrong");
     }
 });

use named route

{{route('news_index',['slug'=>'math'])}}

Upvotes: 4

Govind Samrow
Govind Samrow

Reputation: 10187

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')!!}

Upvotes: 10

Don&#39;t Panic
Don&#39;t Panic

Reputation: 14520

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

Upvotes: 4

omitobi
omitobi

Reputation: 7334

Just for Curiosity sake I attempted optional parameter on prefix route grouping in laravel and it worked. Check it out:

Route::group(['prefix' => '{subject?}', 'as'=> 'subject.', where' => ['subject' => 'math|english|geo']],function (){
    Route::get('news', function (){
       return 'This is the news';
    })->name('news');
});

Pretty sure this is the solution you dreamt of.

Well before this would be the correct answer, there might be a little issue. Calling route('subject.news') will give http://example.com/news. To make it happy, you have to pass the optional parameter to route() function i.e. route('subject.news','math'); for example; then you'll have http://example.com/math/news.

PS: This was done on Laravel 5.4.30 PHP 7.1

Upvotes: 2

Desh901
Desh901

Reputation: 2723

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.

Upvotes: 5

Shams Reza
Shams Reza

Reputation: 1097

Instead of grouping you can use route parameters

Route::get('/{prefix}/news', 'NewsController@index')->name('news_index');
Route::get('/{prefix}/article', 'ArticleController@index')->name('article_index');

Upvotes: 0

Related Questions