Reputation: 1095
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
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
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
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
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
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
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
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
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