©Sergey Emelyanov 2025 | Alle Rechte vorbehalten
Die Kopplung zwischen Modulen ist eine der größten Herausforderungen in komplexen Laravel-Projekten. In diesem Artikel zeige ich, wie Sie mithilfe des Porto-Architekturpatterns Domänen klar trennen und über Facades und Dependency Provider kommunizieren lassen – ohne direkte Abhängigkeiten.
Das Porto-Pattern (inspiriert von Domain-Driven Design) bietet:
src/
├── Domains/
│ ├── Category/
│ │ ├── Actions/ # Geschäftslogik (z. B. Kategorie erstellen)
│ │ ├── Repositories/ # Datenbank-Interaktionen
│ │ ├── Providers/ # Dependency Injection
│ │ └── Facades/ # Öffentliche Schnittstelle für andere Module
│ └── Product/ # Analog für Produkte
└── Parents/ # Gemeinsame Basisklassen
// src/Domains/Category/Repositories/Eloquent/CategoryRepository.php
namespace Domains\Category\Repositories\Eloquent;
use Domains\Category\Models\Category;
class CategoryRepository implements CategoryRepositoryInterface {
public function getBySlug(string $slug): Category {
return Category::where('slug', $slug)->firstOrFail();
}
}
// src/Domains/Category/Actions/GetCategoryBySlug.php
namespace Domains\Category\Actions;
use Domains\Category\Repositories\CategoryRepositoryInterface;
class GetCategoryBySlug {
public function __construct(
private CategoryRepositoryInterface $repository
) {}
public function execute(string $slug): Category {
return $this->repository->getBySlug($slug);
}
}
// src/Domains/Category/Facades/CategoryFacade.php
namespace Domains\Category\Facades;
use Domains\Category\Actions\GetCategoryBySlug;
class CategoryFacade {
public function getBySlug(string $slug): Category {
return GetCategoryBySlug::execute($slug);
}
}
Schlechte Lösung: Direkter Aufruf der Kategorie-Action → enge Kopplung.
Bessere Lösung:
// src/Domains/Product/Providers/ProductDependencyProvider.php
namespace Domains\Product\Providers;
use Domains\Category\Facades\CategoryFacade;
class ProductDependencyProvider {
public function getCategoryFacade(): CategoryFacade {
return app(CategoryFacade::class);
}
}
// src/Domains/Product/Actions/GetProductDetails.php
namespace Domains\Product\Actions;
use Domains\Product\Providers\ProductDependencyProvider;
class GetProductDetails {
public function __construct(
private ProductDependencyProvider $dependencies
) {}
public function execute(int $productId): array {
$category = $this->dependencies->getCategoryFacade()->getBySlug('electronics');
// Business-Logik mit Kategorie-Daten
}
}
// src/Domains/Category/Contracts/CategoryRepositoryInterface.php
interface CategoryRepositoryInterface {
public function getBySlug(string $slug): Category;
}
// src/Domains/Category/Providers/CategoryServiceProvider.php
public function register(): void {
$this->app->bind(
CategoryRepositoryInterface::class,
CategoryRepository::class
);
}
Szenario | Empfehlung |
---|---|
Kleine Projekte | Übertrieben – einfache MVC-Struktur reicht. |
Mittlere/große Apps | Unverzichtbar – Wartbarkeit zahlt sich aus. |
Microservices | Ideal – klare Modulgrenzen. |
Indem Sie Domänen über Facades und Dependency Provider entkoppeln, machen Sie Ihr Laravel-Projekt:
Weiterführend:
Haben Sie Fragen? Stellen Sie sie in den Kommentaren! 🚀
„Software-Architektur ist wie Städteplanung – je klarer die Bezirke (Module) abgegrenzt sind, desto reibungsloser fließt der Verkehr (Daten).“
©Sergey Emelyanov 2025 | Alle Rechte vorbehalten