1. Single Responsibility Principle
- Each class should have only one responsibility
class User extends Model{}
class EmailNotifier {
public function send(User $user, $message) {}
}
// in your controller or service class
$user = User::find($id);
$user->update($request->all());
$emailNotifier = new EmailNotifier();
$emailNotifier->send($user, 'Your information has been updated.');
class EmailNotifier {
public function send(User $user, $message) {}
}
// in your controller or service class
$user = User::find($id);
$user->update($request->all());
$emailNotifier = new EmailNotifier();
$emailNotifier->send($user, 'Your information has been updated.');
2. Open/Closed Principle
- A class should be open for extension but closed for modification
interface PaymentGatewayInterface { public function processPayment($amount);}
class PayPalGateway implements PaymentGatewayInterface {
public function processPayment($amount) {}
}
class StripeGateway implements PaymentGatewayInterface{
public function processPayment($amount) {}
}
class PaymentController extends Controller{
public function process(Request $request, PaymentGatewayInterface $gateway) {}
}
class PayPalGateway implements PaymentGatewayInterface {
public function processPayment($amount) {}
}
class StripeGateway implements PaymentGatewayInterface{
public function processPayment($amount) {}
}
class PaymentController extends Controller{
public function process(Request $request, PaymentGatewayInterface $gateway) {}
}
3. Liskov Substitution principle
- Each base class can be replaced by its subclasses
abstract class EmailProvider {
abstract public function addSubscriber(User $user): array;
abstract public function sendEmail(User $user): void;
}
class MailChimp extends EmailProvider {
public function addSubscriber(User $user): array {}
public function sendEmail(User $user): void {}
}
class ConvertKit extends EmailProvider{
public function addSubscriber(User $user): array {}
public function sendEmail(User $user): void {}
}
// you can using baseclass
class AuthController {
public function register(RegisterRequest $request, EmailProvider $emailProvider) {}
}
// or using subclasses
public function register(RegisterRequest $request, ConvertKit $emailProvider) {}
abstract public function addSubscriber(User $user): array;
abstract public function sendEmail(User $user): void;
}
class MailChimp extends EmailProvider {
public function addSubscriber(User $user): array {}
public function sendEmail(User $user): void {}
}
class ConvertKit extends EmailProvider{
public function addSubscriber(User $user): array {}
public function sendEmail(User $user): void {}
}
// you can using baseclass
class AuthController {
public function register(RegisterRequest $request, EmailProvider $emailProvider) {}
}
// or using subclasses
public function register(RegisterRequest $request, ConvertKit $emailProvider) {}
* apply: use type, hints and return types, use default values for parameters => to would be immediately flag the error when wrong types
4. Interface Segregation Principle
- Should have many small interfaces instead of a few huge ones
// not do like this
interface ProductType{
public function calculatePrice(Product $product): float;
public function decreaseInventory(Product $product): void;
public function calculateTaxes(Product $product): TaxData;
}
// apply Interface Segregation Principle
interface ProductPriceType{
public function calculatePrice(Product $product): float;
}
interface ProductInventoryHandler{
public function decreaseInventory(Product $product): void;
}
interface ProductTaxType{
public function calculateTaxes(Product $product): TaxData;
}
interface ProductType{
public function calculatePrice(Product $product): float;
public function decreaseInventory(Product $product): void;
public function calculateTaxes(Product $product): TaxData;
}
// apply Interface Segregation Principle
interface ProductPriceType{
public function calculatePrice(Product $product): float;
}
interface ProductInventoryHandler{
public function decreaseInventory(Product $product): void;
}
interface ProductTaxType{
public function calculateTaxes(Product $product): TaxData;
}
5. Dependency Inversion Principle
- Depend on abstraction, not detail
abstract class MarketDataProvider{
abstract public function getPrice(string $ticker): float;
}
class IexCloud extends MarketDataProvider{
public function getPrice(string $ticker): float {}
}
class Finnhub extends MarketDataProvider {
public function getPrice(string $ticker): float {}
}
// using MarketDataProvider
class CompanyController {
public function show( Company $company, MarketDataProvider $marketDataProvider) {}
}
abstract public function getPrice(string $ticker): float;
}
class IexCloud extends MarketDataProvider{
public function getPrice(string $ticker): float {}
}
class Finnhub extends MarketDataProvider {
public function getPrice(string $ticker): float {}
}
// using MarketDataProvider
class CompanyController {
public function show( Company $company, MarketDataProvider $marketDataProvider) {}
}
Thank you.
References
- https://martinjoo.dev/solid-principles-with-laravel

No comments:
Post a Comment