skip to Main Content

There are two groups of routes: for subdomains and the main domain:

Route::middleware(['language'])->group(function () {
    Route::domain('{subdomain}.vizit.loc')->group(function () {
        Route::controller(FrontSightController::class)->group(function () {
            Route::get('/sights', 'index')->name('subdomain.main.sights.index');
            Route::get('/sights/category/{category_slug}', 'showByCategory')->name('subdomain.main.sights.category.index');
        });
    });
});

Route::middleware(['language'])->group(function () {
    Route::domain('vizit.loc')->group(function () 
        Route::controller(FrontSightController::class)->group(function () {
            Route::get('/sights', 'index')->name('main.sights.index');
            Route::get('/sights/category/{category_slug}', 'showByCategory')->name('main.sights.category.index');
        });
    });
});

In the index method, I pass the $subdomain parameter, and everything works fine for both groups:

public function index(Request $request, $subdomain = null)

However, in the showByCategory method, there is an additional $category_slug parameter:

public function showByCategory(Request $request, $category_slug, $subdomain = null)
    {
        $subdomain = $request->route('subdomain');
        $region_id = $this->regionService->getRegionIdByDomain($subdomain);
        $categories = Category::whereNull('category_id')->get(['id', 'name', 'slug']);
        $regions = Region::with('districts')->get(['id', 'name', 'slug']);
        $services = Service::get(['id', 'name', 'slug', 'icon']);
        $category_id = Category::where('slug', $category_slug)->value('id');
        $sights = Sight::where('category_id', $category_id)->filter($request)->where('region_id', $region_id)->latest()->paginate(20);
        dd($subdomain, $region_id, $category_slug, $sights);
        if (is_null($region_id)) {
            $sights = Sight::where('category_id', $category_id)->filter($request)->latest()->paginate(20);
        }
        return view('main.sights.index', compact('sights', 'categories', 'regions', 'services'));
    }

When I click on links for subdomains, the method behaves incorrectly because the values of $subdomain and $category_slug are the same in the blade template:

@if(!is_null($subdomain))
                        <a href="{{ route('subdomain.main.sights.category.index', [$subdomain, $sight->category->slug]) }}" class="btn btn-outline-weldonBlue">
                            {{ $sight->category->name[app()->getLocale()] }}
                        </a>
                    @else
                        <a href="{{ route('main.sights.category.index', $sight->category->slug) }}" class="btn btn-outline-weldonBlue">
                            {{ $sight->category->name[app()->getLocale()] }}
                        </a>
                    @endif

If I make $subdomain and $category_slug optional parameters in the showByCategory method, then the links for the main domain will not work.

In the Route::domain(‘{subdomain}.vizit.loc’) setting, {subdomain} cannot be an optional parameter.

Is there a way to solve this issue without duplicating identical methods for subdomains and the main domain?

2

Answers


  1. Maybe this will help, in Laravel document about subdomain. The $subdomain is placed before $id

    But in your showByCategory, you put $subdomain behind. This will make Laravel put the value of {subdomain} into your $category_slug.

    Further, I can see you set

    $subdomain = $request->route('subdomain');
    

    Maybe because when you debug, you see the value of $subdomain is incorrect. This line will assign {subdomain} to your $subdomain, which accidentally identical to $category_slug. Try to swap $subdomain and $category_slug positions.

    Hope this suggest will help you.


    I have a little test that might help. I’ve try this little block of code here

    Route::get('/{user}/category/{group}', function (Request $request, $group, $user) {
      dd($user);
    });
    

    When you access this link /user/category/group. The above code will return "group" instead of "user"

    Why? Because Laravel will just put your route parameter sequentially. What come first will be put first. So in your case,

    {subdomain} => $category_slug
    {category_slug} => $subdomain
    

    So you should try to remove this line

    public function showByCategory(Request $request, $category_slug, $subdomain = null)
        {
            // $subdomain = $request->route('subdomain'); -------------------
            $region_id = $this->regionService->getRegionIdByDomain($subdomain);
            $categories = Category::whereNull('category_id')->get(['id', 'name', 'slug']);
            $regions = Region::with('districts')->get(['id', 'name', 'slug']);
            $services = Service::get(['id', 'name', 'slug', 'icon']);
            $category_id = Category::where('slug', $category_slug)->value('id');
            $sights = Sight::where('category_id', $category_id)->filter($request)->where('region_id', $region_id)->latest()->paginate(20);
            dd($subdomain, $region_id, $category_slug, $sights);
            if (is_null($region_id)) {
                $sights = Sight::where('category_id', $category_id)->filter($request)->latest()->paginate(20);
            }
            return view('main.sights.index', compact('sights', 'categories', 'regions', 'services'));
        }
    

    Or try something like this

    public function showByCategory(Request $request, $category_slug, $subdomain = null)
        {
            if (is_null($subdomain)) {
              // This means you've access your main domain
              $subdomain = $category_slug;
              $category_slug = null;
            } else {
              // Else, swap their positions
              $category_slug = $subdomain;
              $subdomain = $request->route('subdomain');
            }
    
            $region_id = $this->regionService->getRegionIdByDomain($subdomain);
            $categories = Category::whereNull('category_id')->get(['id', 'name', 'slug']);
            $regions = Region::with('districts')->get(['id', 'name', 'slug']);
            $services = Service::get(['id', 'name', 'slug', 'icon']);
            $category_id = Category::where('slug', $category_slug)->value('id');
            $sights = Sight::where('category_id', $category_id)->filter($request)->where('region_id', $region_id)->latest()->paginate(20);
            dd($subdomain, $region_id, $category_slug, $sights);
            if (is_null($region_id)) {
                $sights = Sight::where('category_id', $category_id)->filter($request)->latest()->paginate(20);
            }
            return view('main.sights.index', compact('sights', 'categories', 'regions', 'services'));
        }
    
    Login or Signup to reply.
  2. Made a little adjustment to the ‘showByCategory’ route for the main domain by allowing the {category_slug?} parameter to be optional. This way, we can use one controller method for both subdomains and the main domain

    Route::middleware(['language'])->group(function () {
        Route::domain('{subdomain}.vizit.loc')->group(function () {
            Route::controller(FrontSightController::class)->group(function () {
                Route::get('/sights', 'index')->name('subdomain.main.sights.index');
                Route::get('/sights/category/{category_slug}', 'showByCategory')->name('subdomain.main.sights.category.index');
            });
        });
    });
    
    Route::middleware(['language'])->group(function () {
        Route::domain('vizit.loc')->group(function () {
            Route::controller(FrontSightController::class)->group(function () {
                Route::get('/sights', 'index')->name('main.sights.index');
                Route::get('/sights/category/{category_slug?}', 'showByCategory')->name('main.sights.category.index');
            });
        });
    });
    

    Now, in your controller method, you can handle the logic accordingly:

    public function showByCategory(Request $request, $category_slug = null, $subdomain = null)
    {
        // The rest of your logic remains unchanged
    }
    

    With this setup you can use the same controller method for both subdomains and the main domain. in your Blade template you can adjust the link generation :

    @if (!is_null($subdomain))
        <a href="{{ route('subdomain.main.sights.category.index', [$subdomain, $sight->category->slug]) }}" class="btn btn-outline-weldonBlue">
            {{ $sight->category->name[app()->getLocale()] }}
        </a>
    @else
        <a href="{{ route('main.sights.category.index', $sight->category->slug) }}" class="btn btn-outline-weldonBlue">
            {{ $sight->category->name[app()->getLocale()] }}
        </a>
    @endif
    

    Hope this helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search