SOLID in PHP
Tags: php, solid, oop, laravel
Published: 2020-09-25 07:29:36

---
title: SOLID in PHP
published: true
description: Explanation of SOLID principles in PHP and why they are so important
tags: php, solid, oop, Laravel
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/na8tzr13xs9kganpt486.png
---

# What is SOLID? 🙄

It is a set of principles to have good software design practices compiled by [Uncle Bob](https://blog.cleancoder.com/). 

# Why should I use them?
- Software design principles or conventions.
- Widely accepted in the industry.
- Help make code more maintainable and tolerant to changes.
- Applicable in terms of class design (micro-design), and also at the software architecture level.

**If you don't use SOLID, you probably code STUPID¹ without knowing it**

¹: **STUPID stands for**: Singleton, Tight Coupling, Untestability, Premature Optimization, Indescriptive Naming, Duplication

# What does SOLID stands for
[SOLID](https://en.wikipedia.org/wiki/SOLID) is an acronym that stands for:

- ***S***ingle responsibility principle
- ***O***pen/closed principle
- ***L***iskov substitution principle
- ***I***nterface segregation principle
- ***D***ependency inversion principle

# What do we do 

# S - Single Responsibility Principle(SRP)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3p6o25r0usnupk59xjcp.jpg)

> 💡 A class should only have one reason to change, which means it should only have one responsibility.

- How to accomplish
    - Small classes with limited objectives
- Purpose or gain:
    - High cohesion and robustness
    - Allow class composition (inject collaborators)
    - Avoid code duplication

## Example

Let's imagine we have a class that represents a text document, said document has a title and content. This document must be able to be exported to HTML and PDF.

### Violation of the SRP 👎

> ⚠️ Code coupled with more than one responsibility

```php
class Document
{
    protected $title;
    protected $content;
 
    public function __construct(string $title, string $content)
    {
        $this->title = $title;
        $this->content= $content;
    }
 
    public function getTitle(): string
    {
        return $this->title;
    }
 
    public function getContent(): string
    {
        return $this->content;
    }

		public function exportHtml() {
				echo "DOCUMENT EXPORTED TO HTML".PHP_EOL;
        echo "Title: ".$this->getTitle().PHP_EOL;
        echo "Content: ".$this->getContent().PHP_EOL.PHP_EOL;
		}

		public function exportPdf() {
				echo "DOCUMENT EXPORTED TO PDF".PHP_EOL;
        echo "Title: ".$this->getTitle().PHP_EOL;
        echo "Content: ".$this->getContent().PHP_EOL.PHP_EOL;
		}
}
```

As you may see  the methods or functions that we expose as APIs for other programmers to use, include the `getTitle()` and the `getContent()` but these methods are being used within the behavior of the same class.

This breaks the [Tell-Don't-Ask principle](https://martinfowler.com/bliki/TellDontAsk.html#:~:text=Tell%2DDon't%2DAsk,an%20object%20what%20to%20do.):

> 💬 Tell-Don't-Ask is a principle that helps people remember that object-orientation is about bundling data with the functions that operate on that data. It reminds us that rather than asking an object for data and acting on that data, we should instead tell an object what to do.

Finally, we also see that the class that must represent a document not only has the responsibility of representing it, but also of exporting it in different formats.

### Following the SRP Principle 👍

Once we have identified that the `Document` class should not have anything other than the representation of a "document", the next thing we have to establish is the API through which we want to communicate with the export.

For the export we will need to create an `interface` that receives a document.

```php
interface ExportableDocumentInterface
{
    public function export(Document $document);
}
```

The next thing we have to do is extract the logic that does not belong to the class.

```php
class HtmlExportableDocument implements ExportableDocumentInterface
{
    public function export(Document $document)
    {
        echo "DOCUMENT EXPORTED TO HTML".PHP_EOL;
        echo "Title: ".$document->getTitle().PHP_EOL;
        echo "Content: ".$document->getContent().PHP_EOL.PHP_EOL;
    }
}
```
```php
class PdfExportableDocument implements ExportableDocumentInterface
{
    public function export(Document $document)
    {
        echo "DOCUMENT EXPORTED TO PDF".PHP_EOL;
        echo "Title: ".$document->getTitle().PHP_EOL;
        echo "Content: ".$document->getContent().PHP_EOL.PHP_EOL;
    }
}
```
Leaving the class implementation something like this
```php
class Document
{
    protected $title;
    protected $content;

    public function __construct(string $title, string $content)
    {
        $this->title = $title;
        $this->content= $content;
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function getContent(): string
    {
        return $this->content;
    }
}
```
This makes it easier for both the exports and the documentation class to be better tested.

# O - Open-Closed Principle(OCP)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/nltkvxp7g3bf4n29x74w.jpg)

> 💡 Objects or entities should be open for extension, but closed for modification.

- How to accomplish
    - Avoiding depending on specific implementations, making use of abstract classes or interfaces.
- Purpose or gain:
    - Makes it easy to add new use cases to our application

## Examples
Let's imagine that we need to implement a login system. Initially to authenticate our user we need a username and a password (Main use case), so far so good, but what happens if we require or from business require that the user authenticate through Twitter or Gmail?

To begin with, if a situation like this arises, it is important to understand that what is being asked of us is a **new feature** and not that we modify the current one. And that the case of Twitter would be one use case and that of Gmail another totally different.

### Third Party API Login - OCP Violation 👎

```php
class LoginService
{
    public function login($user)
    {
        if ($user instanceof User) {
            $this->authenticateUser($user);
        } else if ($user instanceOf ThirdPartyUser) {
            $this->authenticateThirdPartyUser($user);
        }
    }
}
```
### Login with third party API - Following OCP 👍

The first thing we should do is create an interface that complies with what we want to do and that fits the specific use case.

```php
interface LoginInterface
{
    public function authenticateUser(UserInterface $user);
}
```

Now we should decouple the logic that we had already created for our use case and implement it in a class that implements our interface.

```php
class UserAuthentication implements LoginInterface
{
    public function authenticateUser(UserInterface $user)
    {
        // TODO: Implement authenticateUser() method.
    }
}
```

```php
class ThirdPartyUserAuthentication implements LoginInterface
{
    public function authenticateUser(UserInterface $user)
    {
        // TODO: Implement authenticateUser() method.
    }
}
```
```php
class LoginService
{
    public function login(LoginInterface $loginService, UserInterface $user)
    {
        $loginService->authenticateUser($user);
    }
}
```

As you can see, the `LoginService` class is agnostic of which authentication method (via web, via google or twitter, etc).

### Payments API implemented with a switch - OCP Violation 👎

A very common case is when we have a `switch()`, where each case performs a different action and there is the possibility that in the future we will continue adding more cases to the switch. Let's look at the following example.

Here we have a controller with a `pay()` method, which is responsible for receiving the type of payment through the request and, depending on that type, the payment will be processed through one or another method found in the Payment class.

```php
public function pay(Request $request)
{
    $payment = new Payment();

    switch ($request->type) {
        case 'credit':
            $payment->payWithCreditCard();
            break;
        case 'paypal':
            $payment->payWithPaypal();
            break;
        default:
            // Exception
            break;
    }
}
```
```php
class PaymentRequest
{
    public function payWithCreditCard()
    {
        // Logic to pay with a credit card...
    }

    public function payWithPaypal()
    {
        // Logic to pay with paypal...
    }
}
```
This code has 2 big problems:
 - We should add one more case for each new payment that we accept or delete a case in the event that we do not accept more payments through PayPal.
 - All the methods that process the different types of payments are found in a single class, the Payment class. Therefore, when we add a new payment type or remove one, we should edit the Payment class, and as the `Open / Closed principle` says, this is not ideal. Like it is also violating the principle of `Single Responsibility`.

This violation it's also related to a code smell call [Switch Statements Smell](https://wiki.c2.com/?SwitchStatementsSmell) if you want to know more about refactors or examples go into [refactoring guru](https://refactoring.guru/es/smells/switch-statements)

### Payments API implemented with a switch - Following OCP 👍

The first thing we could do to try to comply with the OCP is to create an interface with the `pay()` method.

```php
interface PayableInterface
{
    public function pay();
}
```
Now we will proceed to create the classes that should implement these interfaces.

```php
class CreditCardPayment implements PayableInterface
{
    public function pay()
    {
        // Logic to pay with a credit card...
    }
}
```
```php
class PaypalPayment implements PayableInterface
{
    public function pay()
    {
        // Logic to pay with paypal...
    }
}
```

The next step would be to refactor our `pay()` method.

```php
public function pay(Request $request)
{
    $paymentFactory = new PaymentFactory();
    $payment = $paymentFactory->initialize($request->type);
    
    return $payment->pay();
}
```

> 👁 As you can see, we have replaced the switch with a factory.

```php
class PaymentFactory
{
    public function initialize(string $type): PayableInterface
    {
        switch ($type) {
            case 'credit':
                return new CreditCardPayment();
            case 'paypal':
                return new PayPalPayment();
            default:
                throw new \Exception("Payment method not supported");
                break;
        }
    }
}
```

## Benefits of the Open / Closed Principle
- Extend the functionalities of the system, without touching the core of the system.
- We prevent breaking parts of the system by adding new functionalities.
- Ease of testing.
- Separation of the different logics.

## 🎨 Design patterns that we can find useful for OCP
- [Factory](https://refactoring.guru/design-patterns/factory-method/php/example) - [Video](https://youtu.be/EcFVTgRHJLM)
- [Adapter](https://refactoring.guru/design-patterns/adapter) - [Video](https://youtu.be/v-GiuMmsXj4)

# L - Liskov Substitution Principle(LSP)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9z77tu54vo3wc9acmckn.jpg)


This principle was introduced by the guru and the first woman in America to earn a Ph.D. in Computer Science, Barbara Liskov. And it is a very interesting principle.

> According to Wikipedia. Liskov's Substitution Principle says that each class that inherits from another can be used as its parent without having to know the differences between them.

- Concepts:
    - If **S** is a subtype of **T**, instances of **T** should be substitutable for instances of S without altering the program properties, That is, by having a hierarchy it means that we are establishing a contract in the father, so ensuring that this contract is maintained in the child will allow us to replace the father and the application will continue to work perfectly.
- How to accomplish:
    -  The behavior of the sub-classes must respect the contract established in the super-class.
    -  Maintain functional [correctness](https://en.wikipedia.org/wiki/Correctness_(computer_science)) to be able to apply OCP.

There are 3 important points that we have to keep in mind in order not to violate the **Liskov** principle:
- Not to strengthen the pre-conditions and not to weaken the post-conditions of the parent class ([defensive programming](https://en.wikipedia.org/wiki/Defensive_programming)).
- The invariants set in the base class must be kept in the subclasses.
- Cannot be a method in the subclass that goes against a behavior of the base class. This is called **Historical Constraint**.

## Example

### Shipping calculation
Let's say we have a Shipping class that is going to calculate the shipping cost of a product given its weight and destination.

```php
class Shipping
{
    public function calculateShippingCost($weightOfPackageKg, $destiny)
    {
        // Pre-condition:
        if ($weightOfPackageKg <= 0) {
            throw new \Exception('Package weight cannot be less than or equal to zero');
        }

        // We calculate the shipping cost by
        $shippingCost = rand(5, 15);

        // Post-condition
        if ($shippingCost <= 0) {
            throw new \Exception('Shipping price cannot be less than or equal to zero');
        }

        return $shippingCost;
    }
}
```

### Shipping calculation - LSP violation due to behavior change in daughter class 👎

```php
class WorldWideShipping extends Shipping
{
    public function calculateShippingCost($weightOfPackageKg, $destiny)
    {
        // Pre-condition
        if ($weightOfPackageKg <= 0) {
            throw new \Exception('Package weight cannot be less than or equal to zero');
        }

        // We strengthen the pre-conditions
        if (empty($destiny)) {
            throw new \Exception('Destiny cannot be empty');
        }

        // We calculate the shipping cost by
        $shippingCost = rand(5, 15);

        // By changing the post-conditions we allow there to be cases
        // in which the shipping is 0
        if ('Spain' === $destiny) {
            $shippingCost = 0;
        }

        return $shippingCost;
    }
}
```
The problem is that we generate with a class like the previous one is that we are exposing a similar API for programmers, but that has a different implementation.

This class will be the parent class of our example where its method to calculate the shipping price has a pre and a post condition (this way of programming using the pre and post conditions is called Defensive Programming).

For example, a programmer on our team is sure that the `calculateShippingCost()` method, of the `Shipping` class, allows `null` destination and shipping costs greater than zero, so by wanting to use the `WorldWideShipping` class, it could cause the system to burst, for example, if you want to use the result of `calculateShippingCost()` in a slice or by giving it a `null` destiny.

Therefore, the WorldWideShipping class is violating the Liskov substitution principle.

### Shipping calculation - LSP violation due to change of invariants from child class 👎

> The [invariants](https://en.wikipedia.org/wiki/Class_invariant) are values ​​of the parent class that cannot be modified by the child classes.

Let's say we want to modify the `Shipping` class that we had before and we want to make the limit of the weight per kilos be 0 but that it is in a variable.

```php
class Shipping
{
    protected $weightGreaterThan = 0;

    public function calculateShippingCost($weightOfPackageKg, $destiny)
    {
        // Pre-condition:
        if ($weightOfPackageKg <= $this->weightGreaterThan) {
            throw new \Exception("Package weight cannot be less than or equal to {$this->weightGreaterThan}");
        }

        // We calculate the shipping cost by
        $shippingCost = rand(5, 15);

        // Post-condition
        if ($shippingCost <= 0) {
            throw new \Exception('Shipping price cannot be less than or equal to zero');
        }

        return $shippingCost;
    }
}
```
```php
class WorldWideShipping extends Shipping
{
    public function calculateShippingCost($weightOfPackageKg, $destiny)
    {
	// We modify the value of the parent class
        $this->weightGreaterThan = 10;

        // Pre-condition
        if ($weightOfPackageKg <= $this->weightGreaterThan) {
            throw new \Exception("Package weight cannot be less than or equal to {$this->weightGreaterThan}");
        }
	// Previous code...
    }
}
```
### Shipping calculation - Following LSP by change of invariants from child class 👍

The easiest way to avoid this would be to simply create the variable `$weightOfPackageKg` as a private constant if our version of **PHP (7.1.0)** allows it but by creating that private variable.

## Historical Restrictions
Historical restrictions say that there cannot be a method in the child class that goes against a behavior of its parent class.

That is, if in the parent class there is the `FixedTax()` method, then the `ModifyTax()` method cannot exist in the child class. Or didn't they teach you not to disobey your parents? 😆.

For a method of the subclass to modify the value of a property of the base class is a violation of the **Liskov** principle because classes must be able to change the value of their properties only (**Encapsulation**).

## The easiest way not to break the LSP
The best way not to break LSP is by using Interfaces. Instead of extending our child classes from a parent class.

```php
interface CalculabeShippingCost
{
    public function calculateShippingCost($weightOfPackageKg, $destiny);
}
```
```php
class WorldWideShipping implements CalculabeShippingCost
{
    public function calculateShippingCost($weightOfPackageKg, $destiny)
    {
        // Implementation of logic
    }
}
```

By using interfaces you can implement methods that various classes have in common, but each method will have its own implementation, its own pre and post conditions, its own invariants, etc. We are not tied to a parent class.

> ⚠️ This does not mean that we start using interfaces everywhere, although they are very good. But sometimes it is better to use base classes and other times interfaces. It all depends on the situation.

## Interfaces 🆚 Abstract Class

- Interface benefits
    - Does not modify the hierarchy tree
    - Allows to implement N Interfaces
- Benefits of Abstract Class
    - It allows to develop the `Template Method`¹ pattern by pushing the logic to the model.
     Problem: Difficulty tracing who the actors are and when capturing errors
    - Private getters ([Tell-Don't-Ask principle](https://martinfowler.com/bliki/TellDontAsk.html#:~:text=Tell%2DDon't%2DAsk,an%20object%20what%20to%20do.))

¹. Design pattern Template Method: It states that in the abstract class we would define a method body that defines what operation we are going to perform, but we would be calling some methods defined as abstract (delegating the implementation to the children). But beware! 👀 this implies a loss of traceability of our code.

### Conclusion of Interfaces 🆚 Abstract Class
- When do we use Interfaces?: When we are going to decouple between layers.

- When do we use Abstract?: In certain cases for Domain Models ([Domain models](https://en.wikipedia.org/wiki/Domain_model) not ORM models, to avoid [anemic domain models](https://www.martinfowler.com/bliki/AnemicDomainModel.html))

## 🎨 Design patterns that can be useful to us in the LSP
- [Template method](https://refactoring.guru/design-patterns/template-method) - [Video](https://youtu.be/7ocpwK9uesw)
- [Composite](https://refactoring.guru/design-patterns/composite) - [Video](https://youtu.be/EWDmWbJ4wRA)
- [Strategy](https://refactoring.guru/design-patterns/strategy) - [Video](https://youtu.be/v9ejT8FO-7I)
- [State](https://refactoring.guru/design-patterns/state) - [Viedo](https://youtu.be/N12L5D78MAA)

# I - Interface Segregation Principle (ISP)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c76op7uhgdgovx29b506.jpg)

> 💡 A client should only know the methods they are going to use and not those that they are not going to use.

Basically, what this principle refers to is that we should not create classes with thousands of methods where it ends up being a huge file. Since we are generating a monster class, where most of the time we will only use some of its methods each time. And for that it refers to the need for interfaces, it is also important to understand that this helps a lot at the **Single Responsibility Principle(SRP)**.

- How to accomplish
    - Define interface contracts based on the clients that use them and not on the implementations that we could have (The interfaces belong to the clients).
    - Avoid *Header Interfaces* by promoting *Role Interfaces*
- Purpose or gain:
    - High cohesion and low structural coupling

## Header Interfaces
Martin fowler in the article [HeaderInterface](https://martinfowler.com/bliki/HeaderInterface.html) sustain.

> 💬 A header interface is an explicit interface that mimics the implicit public interface of a class. Essentially you take all the public methods of a class and declare them in an interface. You can then supply an alternative implementation for the class. This is the opposite of a RoleInterface - I discuss more details and the pros and cons there.

## Role Interfaces
Martin fowler in the article [RoleInterface](https://martinfowler.com/bliki/RoleInterface.html#:~:text=A%20role%20interface%20is%20defined,only%20have%20a%20single%20interface.) sustain.

> 💬 A role interface is defined by looking at a specific interaction between suppliers and consumers. A supplier component will usually implement several role interfaces, one for each of these patterns of interaction. This contrasts to a HeaderInterface, where the supplier will only have a single interface.

## Examples

### Simple Example
We want to be able to send notifications via email, Slack, or txt file. What signature will the interface have? 📨
- a) $notifier($content) ✔️
- b) $notifier($slackChannel, $messageTitle, $messageContent, $messageStatus) ❌
- c) $notifier($recieverEmail, $emailSubject, $emailContent) ❌
- d) $notifier($destination, $subject, $content) ❌
- e) $notifier($filename, $tag, $description) ❌

We can rule out that options B, C and E, since Header Interface would be based on the implementation (for Slack, email and file respectively).

In the case of option D, we could consider it invalid given that the type `$destination` It does not offer us any specificity (we do not know if it is an email, a channel ...).

Finally, in option A, we would only be sending the content, so the particularities of each of the types of notification would have to be given in the constructor (depending on the use case you could not always).

> 👁 The interfaces belong to the clients and not to those who implement them.

### Example Developer | QA | PM - ISP violation due to excess responsibilities and poor abstraction 👎
A simple example would be the following situation. Let's imagine that we have developers, a QA team and a project manager who have to determine whether to program.

Let's say the programmer can program and test, while the QA can only test.


```php
interface Workable
{
    public function canCode();
    public function code();
    public function test();
}
```
```php
class Developer implements Workable
{
    public function canCode()
    {
        return true;
    }
    public function code()
    {
        return 'coding';
    }
    public function test()
    {
        return 'testing in localhost';
    }
}
```
```php
class Tester implements Workable
{
    public function canCode()
    {
        return false;
    }
    public function code()
    {
        // El QA no puede programar
         throw new Exception('Opps! I can not code');
    }
    public function test()
    {
        return 'testing in test server';
    }
}
```
```php
class ProjectManagement
{
    public function processCode(Workable $member)
    {
        if ($member->canCode()) {
            $member->code();
        }
    }
}
```

If we pay attention we will see that the `Tester` class has a method that does not correspond to it since it is not called and if it is called it would give us an `Exception`.

So we should make a small refactor to be able to comply with the principle of segregation of interfaces.

### Example Developer | QA | PM - Following ISP 👍
The first thing is to identify what actions we have to perform, design the interfaces and assign these interfaces to the corresponding actors depending on the use case.

```php
interface Codeable
{
    public function code();
}
```

```php
interface Testable
{
    public function test();
}
```
```php
class Programmer implements Codeable, Testable
{
    public function code()
    {
        return 'coding';
    }
    public function test()
    {
        return 'testing in localhost';
    }
}
```
```php
class Tester implements Testable
{
    public function test()
    {
        return 'testing in test server';
    }
}
```
```php
class ProjectManagement
{
    public function processCode(Codeable $member)
    {
        $member->code();
    }
}
```
This code does comply with the principle of segregation of interfaces. As with the previous principles.

## 🎨 Design patterns that can be useful to us in the ISP
- [Chain of Responsibility](https://refactoring.guru/design-patterns/chain-of-responsibility)
- [Strategy](https://refactoring.guru/design-patterns/strategy) - [Video](https://youtu.be/v9ejT8FO-7I)
- [State](https://refactoring.guru/design-patterns/state) - [Viedo](https://youtu.be/N12L5D78MAA)

# D - Dependency Inversion Principle (DIP)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vb1rzyh9pkg927y3rqtu.jpg)

I must first make it clear that Dependency Injection is NOT the same as Dependency Inversion. Dependency inversion is a principle, while dependency injection is a design pattern.

> 💡 High-level modules should not depend on low-level ones. Both should depend on abstractions

- How to accomplish
    - Inject dependencies (parameters received in constructor).
    - Rely on the interfaces (contracts) of these dependencies and not on specific implementations.
    - LSP as a premise.
- Purpose or gain:
    - Facilitate the modification and replacement of implementations.
    - Better class testability

The principle of dependency injection tries to maintain a low coupling.

## Laravel controller example
Let's say we have a `UserController`. What in its `index` method what it does is return a `JSON` list of users with the users created the previous day.

### Laravel controller - DIP Violation 👎
```php
public function index()
    {
        $users = new User();
        $users = $users->where('created_at', Carbon::yesterday())->get();

        return response()->json(['users' => $users]);
    }
}
```
This code wouldn't be bad, because it would clearly work. But at the same time it would generate the following problems:

- **We cannot reuse the code** as we are tied to Eloquent.
- **It is difficult to test** the methods that instantiate one or several objects (high coupling), since it is difficult to verify that it is failing.
- **It breaks the principle of single responsibility**, because, in addition to the method doing its job, it also has to create the objects in order to do its job.


### Laravel controller - Following the DIP 👍

```php
interface UserRepositoryInterface
{
    // 👁 I am returning an array
    // but it should return Domain Models
    public function getUserFromYesterday(DateInterface $date): array;
}
```
```php
class UserEloquentRepository implements UserRepositoryInterface
{
    public function getUserFromYesterday(DateInterface $date): array
    {
        return User::where('created_at', '>', $date)
            ->get()
            ->toArray();
    }
}
```
```php
class UserSqlRepository implements UserRepositoryInterface
{
    public function getUserFromYesterday(DateInterface $date): array
    {
        return \DB::table('users')
            ->where('created_at', '>', $date)
            ->get()
            ->toArray();
    }
}
```
```php
class UserCsvRepository implements UserRepositoryInterface
{
    public function getUserFromYesterday(DateInterface $date): array
    {
        // 👁 I am accessing the infrastructure
        // from the same method maybe not the best
        $fileName = "users_created_{$date}.csv";
        $fileHandle = fopen($fileName, 'r');

        while (($users[] = fgetscsv($fileHandle, 0, ","))  !== false) {
        }

        fclose($fileHandle);

        return $users;
    }
}
```

As we can see, all classes implement the `UserRespositoryInterface` interface. And this gives us the freedom to get the users either from `Eloquent`, from` SQL` or from a `CSV` 👏😲 file.

This is fine and would work in a normal application, but how do we make the Laravel controller receive that repository in its index method?

The answer is registering the interface with which class it has **by default**.

```php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;


class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(
            'App\Repositories\Contracts\UserRepositoryInterface',
            'App\Repositories\UserCsvRepository'
        );
    }
}
```
In other frameworks like Symfony it can be done using [PHP DI](https://php-di.org/).

# Conclusions

In order to make a more maintainable, reusable and testable code we should try to implement these principles. Like we should know the design patterns that could be useful when we use these principles.

# Webgraphy
🇪🇸
- [Francisco](https://www.franciscougalde.com/2019/07/26/patrones-de-diseno-en-php-solid/) - [Twitter](https://twitter.com/fjugaldev)
- [Por qué NO usar getters y setters | Tell don't ask](https://youtu.be/Be-ULOIGAZk) - [Twitter](https://twitter.com/CodelyTV) - [Youtube](https://www.youtube.com/CodelyTV) - [Courses](https://codely.tv/pro/cursos?utm_source=youtube&utm_medium=social&utm_campaign=dev.to-emmanuel-valverde-ramos&utm_content=Cursos)
- [Errores comunes al diseñar Interfaces - #SOLID - ISP](https://youtu.be/mDAQLkdNGHU) - [Twitter](https://twitter.com/CodelyTV) - [Youtube](https://www.youtube.com/CodelyTV) - [Courses](https://codely.tv/pro/cursos?utm_source=youtube&utm_medium=social&utm_campaign=dev.to-emmanuel-valverde-ramos&utm_content=Cursos)
- [Principio de Segregación de Interfaces - SOLID](https://youtu.be/EzUIbMdxJTk) - [Twitter](https://twitter.com/CodelyTV) - [Youtube](https://www.youtube.com/CodelyTV) - [Courses](https://codely.tv/pro/cursos?utm_source=youtube&utm_medium=social&utm_campaign=dev.to-emmanuel-valverde-ramos&utm_content=Cursos)
- [Herminio Heredia Santos - domina la inyeccion de dependencias de laravel](https://herminioheredia.com.mx/2019/06/19/domina-la-inyeccion-de-dependencias-de-laravel/) - [Twitter](https://twitter.com/HerminioHeredia) - [LinkedLn](https://www.linkedin.com/in/herminio-heredia-santos-477aab19/)
- [Laravel tip - Desacoplando Laravel de tu aplicación](https://www.laraveltip.com/desacoplando-laravel-de-tu-aplicacion/)

(🇬🇧/🇺🇸)
- [Design Patterns in Object Oriented Programming](https://www.youtube.com/playlist?list=PLrhzvIcii6GNjpARdnO4ueTUAVR9eMBpc)