aslan-asilon31/aslan-solid-package
Laravel package showcasing SOLID principles with a clean, modular structure. Provides example abstractions and patterns to organize services, keep dependencies decoupled, and improve maintainability in real-world apps.
Installation
composer require aslan-asilon31/aslan-solid-package
Add the service provider to config/app.php under providers:
Aslan\SolidPackage\SolidServiceProvider::class,
First Use Case: Dependency Inversion
Use the built-in Contract and Implementation classes to enforce SOLID principles.
Example:
use Aslan\SolidPackage\Contracts\LoggerContract;
use Aslan\SolidPackage\Implementations\FileLogger;
// Define a contract
class LoggerContract extends \Aslan\SolidPackage\Contracts\BaseContract {
public function log(string $message);
}
// Bind the contract to an implementation
app()->bind(LoggerContract::class, function ($app) {
return new FileLogger($app->make('path.log'));
});
// Usage
$logger = app()->make(LoggerContract::class);
$logger->log("Test message");
Where to Look First
vendor/aslan-asilon31/aslan-solid-package/src/Contracts/vendor/aslan-asilon31/aslan-solid-package/src/Implementations/README.md for basic examples and usage.Pattern: Use contracts to define interfaces and bind them to implementations in the service container.
// Define a contract
class PaymentProcessorContract extends \Aslan\SolidPackage\Contracts\BaseContract {
public function processPayment(float $amount);
}
// Bind to a specific implementation
app()->bind(PaymentProcessorContract::class, StripePaymentProcessor::class);
Workflow:
AppServiceProvider or a dedicated config file.Pattern: Use the package’s Service and Repository classes to encapsulate logic.
use Aslan\SolidPackage\Services\BaseService;
class UserService extends BaseService {
public function registerUser(array $data) {
// Only handle user registration logic
$this->repository->create($data);
}
}
Integration Tips:
Pattern: Extend existing contracts or implementations without modifying them.
// Extend a base implementation
class CustomLogger extends \Aslan\SolidPackage\Implementations\BaseLogger {
public function log(string $message) {
// Custom logic
parent::log($message);
}
}
Tip: Use traits or inheritance to add functionality while keeping the base class closed.
Pattern: Ensure implementations adhere to contract signatures.
class InvalidLogger implements LoggerContract {
public function log(string $message) {
// This violates LSP if the contract expects a return value
}
}
Tip: Use PHPStan or Psalm to enforce type safety and contract compliance.
// Instead of one monolithic contract
class MonolithicContract extends \Aslan\SolidPackage\Contracts\BaseContract {
public function log(string $message);
public function sendEmail(string $to);
}
// Split into smaller contracts
class LoggerContract extends \Aslan\SolidPackage\Contracts\BaseContract {
public function log(string $message);
}
class EmailSenderContract extends \Aslan\SolidPackage\Contracts\BaseContract {
public function sendEmail(string $to);
}
Over-Engineering Contracts
Tight Coupling in Bindings
Ignoring the Service Container
app()->make() or constructor injection.Missing Abstract Classes
Aslan\SolidPackage\BaseService or Aslan\SolidPackage\BaseRepository for consistency.Contract Not Found Errors
BaseContract.php artisan container:list to verify bindings.Implementation Not Resolvable
app()->has(Implementation::class) to test resolution.AppServiceProvider.solid.php config file for centralized bindings:
return [
'bindings' => [
LoggerContract::class => FileLogger::class,
// Add more bindings here
],
];
Then load it in AppServiceProvider:
$this->app->bind(config('solid.bindings')[LoggerContract::class] ?? null);
Custom Contracts
Aslan\SolidPackage\Contracts\BaseContract to create domain-specific contracts.namespace App\Contracts;
use Aslan\SolidPackage\Contracts\BaseContract;
class CacheContract extends BaseContract {
public function get(string $key);
public function set(string $key, $value);
}
Middleware for Contracts
$kernel->pushMiddleware(function ($request, $next) {
if ($request->wantsJson() && app()->bound(LoggerContract::class)) {
$logger = app()->make(LoggerContract::class);
if (!$logger instanceof \Aslan\SolidPackage\Implementations\BaseLogger) {
abort(500, "Invalid logger implementation");
}
}
return $next($request);
});
Testing Contracts
$this->mock(LoggerContract::class)->shouldReceive('log')->once();
How can I help you explore Laravel packages today?