tabuna/breadcrumbs

multi tenancy app

netwrkx opened this issue · 5 comments

Multi-tenancy is the ability to provide your service to multiple users (tenants) from a single hosted instance of the application. This is contrasted with deploying the application separately for each user.

i got this error Breadcrumbs have already been defined for route [admin.dashboard]. while integrating the package to my multi tenancy app. there seems to be a compatibility issue with multi tenancy package. can you take a look at it

Hey @netwrkx . There are several points that can help me.
This message appears when breadcrumbs are declared twice for the same route name.
Does this show up when you announce them on routes or through a facade? In both cases, is this a message?

@tabuna this is the message i got when i log into the dashboard

Exception
Breadcrumbs have already been defined for route [admin.dashboard].
http://saas.test/admin/dashboard
Route 
<?php

use App\Domains\Auth\Http\Controllers\Backend\DashboardController;
use Tabuna\Breadcrumbs\Trail;

Route::group(['prefix' => 'admin', 'as' => 'admin.', 'middleware' => 'admin'], function () {
    Route::redirect('/', '/admin/dashboard', 301);
    Route::get('dashboard', [DashboardController::class, 'index'])
        ->name('dashboard')
        ->breadcrumbs(function (Trail $trail) {
            $trail->push(__('Home'), route('admin.dashboard'));
        });
    
});
this is how my RouteServiceProvider.php looks like

<?php

namespace App\Providers;

use App\Domains\Backup\Models\Backup;
use App\Domains\Auth\Models\User;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Route;

/**
 * Class RouteServiceProvider.
 */
class RouteServiceProvider extends ServiceProvider
{
    /**
     * This namespace is applied to your controller routes.
     *
     * In addition, it is set as the URL generator's root namespace.
     *
     * @var string
     */
    protected $namespace = 'App\Http\Controllers';

    /**
     * The path to the "home" route for your application.
     *
     * @var string
     */
    public const HOME = '/';

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */
    public function boot()
    {
        // To be able to restore a user, since the default binding is a find and would result in a 404
        Route::bind('deletedUser', function ($id) {
            return User::onlyTrashed()->find($id);
        });

        Route::bind('deletedBackup', function ($id) {
            return Backup::onlyTrashed()->find($id);
        });

        parent::boot();
    }

    /**
     * Define the routes for the application.
     *
     * @return void
     */
    public function map()
    {
        $this->mapApiRoutes();

        $this->mapWebRoutes();

        //
    }

    /**
     * Define the "web" routes for the application.
     *
     * These routes all receive session state, CSRF protection, etc.
     *
     * @return void
     */
    protected function mapWebRoutes()
    {
        foreach ($this->centralDomains() as $domain) {
            Route::middleware('web')
                ->domain($domain)
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));
        } 
    }

    /**
     * Define the "api" routes for the application.
     *
     * These routes are typically stateless.
     *
     * @return void
     */
    protected function mapApiRoutes()
    {
        foreach ($this->centralDomains() as $domain) {
            Route::prefix('api')
                ->domain($domain)
                ->middleware('api')
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));
        }
    }

    protected function centralDomains(): array
    {
        return config('tenancy.central_domains');
    }
}

centralDomains() loops through domain

    'central_domains' => [
        '127.0.0.1',
        'localhost',
        'saas.test',
    ],

It turned out to be obvious. It's all about this part of the code.

    protected function mapApiRoutes()
    {
        foreach ($this->centralDomains() as $domain) {
            Route::prefix('api')
                ->domain($domain)
                ->middleware('api')
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));
        }
    }

The same name was declared for each domain.
Now you can get around this using the following approach: https://github.com/tabuna/breadcrumbs#like-to-use-a-separate-route-file This will register the name with the service provider only once.
In general, I think we should add domain support so that this does not happen in the future.

@netwrkx Just released a new release where this message has been removed.
I also added a test to be sure that this will not happen in the future.
You can add bread crumbs without any problems. Let me know if this is not the case.

it works, thanks