SOLID Principles Overview
Single Responsibility Principles :
.A Class should have only one(single) reason to change.
.A Class should only have one(single) responsibility and be focused on doing only one(single) thing well.
***Single Class should contain Single Responsibility***
example :
<?php
//user class
class User{
public function register($data){
//register method
}
public function login($data){
// login method
}
public function profile($data){
//user basic profile data
}
}
//one(single) class many different types of responsibility such as
// register-user , login-user , get-user-profile-data
//Time to move Single Class - Single responsibility Example
//UserRegister Class
class UserRegister{
public function register($data){
//user register method
}
}
//UserLogin Class
class UserLogin{
public function login($data){
//user login method
}
}
//UserProfile Class
class UserProfile{
public function profile($data){
//user profile method
}
}
?>
Open Closed Principle:
.A Class should be Open for extension and Closed for modification
.Classes should be designed in a way that allows new functionality to be added without changing existing code.
example for general and open-closed principle
<?php
//payment class
Class Payment{
//methods for payment class
public function payWithCreditCard()
{
//codes
}
public function payWithPaypal()
{
//codes
}
public function payWithWireTransfar()
{
//codes
}
}
function pay(Request $request , $type){
$payment = new Payment() ;
//returning payment method based on condition
if($type == 'credit'){
return $payment->payWithCreditCard() ;
}
else if($type == 'paypal'){
return $payment->payWithPaypal() ;
}
else{
return $payment->payWithWireTransfar() ;
}
}
// Appling open closed principles
// we are defining an interface and a method pay
interface PayableInterface{
public function pay() ;
}
// now we extends PayableInterface with CreditCardPayment Class
class CreditCardPayment implements PayableInterface{
public function pay(){
//credit card logic here
}
}
class PaypalPayment implements PayableInterface{
public function pay(){
//credit card logic here
}
}
class WirePayment implements PayableInterface{
public function pay(){
//credit card logic here
}
}
Class PaymentFactory{
// returning total class instance based on condition
public function initPayment($type){
if($type == 'credit'){
return new CreditCardPayment() ;
}
else if($type == 'paypal'){
return new PaypalPayment() ;
}
else if($type == 'wire'){
return new WirePayment() ;
}
}
}
?>
liskov substitution principle (for inheritance)
.substitution(replacement) , we have a super class or parent class object and a sub or child class object. child class have all behaviour of parent class ,if we use child class instance instead of parent class , application behaviour will remain same.children instance may have more extra behavior methods with parent class behaviours and methods.
example
<?php
class Duck{
public function quack(){
}
public function fly(){
}
public function swim(){
}
}
class RubberDuck extends Duck{
public function quack(){
}
public function swim(){
}
}
// this is violate lsp , because rubber duck can not fly
// parent class Duck fly behaviour is missing in child class RubberDuck
//to solve this problem
interface Quackable {
public function quack() ;
}
interface Flyable {
public function fly() ;
}
interface Swimable {
public function swim() ;
}
class RubberDuck implements Quackable , Swimable{
public function quack(){
}
public function swim(){
}
}
?>
interface segregation principle
interface segregation principle for interface similar to srp of interface
.A class should never be force to implement interface that doesn't use
.A class should never be force to depend on method they don't use
example
<?php
interface EmployeeInterface{
public function takeOrder();
public function washDishes();
public function cookFood();
}
class waiter implements EmployeeInterface{
public function takeOrder() {
echo "take order.";
}
public function washDish() {
echo "not my job.";
}
public function cookFood() {
echo "not my job.";
}
}
//that's violates interface segregation principle
interface WaiterInterface {
public function takeOrder();
}
interface ChefInterface {
public function cookFood();
}
interface DishWasherInterface {
public function washDish();
}
//classes
class Waiter implements WaiterInterface {
public function takeOrder() {
echo "take order.";
}
}
class Chef implements ChefInterface {
public function cookFood() {
echo "cook food.";
}
}
class DishWasher implements DishWasherInterface {
public function washDish() {
echo "wash dish.";
}
}
?>
Dependency inversion principle
.Entities should depend on abstractions and not on concretions
One should depend upon abstractions. Do not depend upon concretions
example
interface IPaymentProcess {
public function charge(int $price);
}
class Store {
public function __construct(
private IPaymentProcess $paymentProcess
) {
//
}
public function buy(int $price) {
$this->paymentProcess->charge($price);
}
}
class Stripe implements IPaymentProcess {
private $card;
public function __construct($card) {
$this->card = $card;
}
public function charge(int $price) {
echo "successfully charged by stripe.";
}
}
class Paypal implements IPaymentProcess {
private $card;
public function __construct($card) {
$this->card = $card;
}
public function charge(int $price) {
echo "successfully charged by paypal.";
}
}
$stripe = new Stripe("123456");
$foo = new Store($stripe);
$foo->buy(1200);
$paypal = new Paypal("789456");
$foo = new Store($paypal);
$foo->buy(1500);