Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the principles of SOLID in PHP

2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

Editor to share with you what are the principles of SOLID in PHP, I believe most people do not know much about it, so share this article for your reference, I hope you can learn a lot after reading this article, let's go to know it!

SOLID is a memorable acronym recommended by Michael Feathers, which represents the five most important object coding design principles of Robert Martin naming:

S: single responsibility principle (SRP)

O: open-close principle (OCP)

L: Richter substitution principle (LSP)

I: interface isolation principle (ISP)

D: dependency inversion principle (DIP)

Single responsibility principle Single Responsibility Principle (SRP)

A class should be modified for only one reason. It is always easy to fill a class with a bunch of methods, just as we can only carry one suitcase on a plane. The problem with this is that such a class is not conceptually highly cohesive and leaves a lot of reasons to modify it. It is important to minimize the number of times you need to modify the class. This is because when there are many methods in the class, modify one of them, it is difficult to know which dependent modules in the code base will be affected.

Bad:

Class UserSettings {private $user; public function _ _ construct ($user) {$this- > user = $user } public function changeSettings ($settings) {if ($this- > verifyCredentials ()) {/ /...}} private function verifyCredentials () {/ /...}}

Good:

Class UserAuth {private $user; public function _ _ construct ($user) {$this- > user = $user;} public function verifyCredentials () {/ /...}} class UserSettings {private $user; private $auth; public function _ _ construct ($user) {$this- > user = $user; $this- > auth = new UserAuth ($user) } public function changeSettings ($settings) {if ($this- > auth- > verifyCredentials ()) {/ /...}

Opening and closing principle Open/Closed Principle (OCP)

As Bertrand Meyer said, "the entities of the software (classes, modules, functions, etc.) should be open to extensions and closed to modifications." This principle states that users should be allowed to add new features without changing existing code.

Bad:

Abstract class Adapter {protected $name; public function getName () {return $this- > name;}} class AjaxAdapter extends Adapter {public function _ construct () {parent::__construct (); $this- > name = 'ajaxAdapter';}} class NodeAdapter extends Adapter {public function _ construct () {parent::__construct (); $this- > name =' nodeAdapter' }} class HttpRequester {private $adapter; public function _ construct ($adapter) {$this- > adapter = $adapter;} public function fetch ($url) {$adapterName = $this- > adapter- > getName (); if ($adapterName = 'ajaxAdapter') {return $this- > makeAjaxCall ($url) } elseif ($adapterName = = 'httpNodeAdapter') {return $this- > makeHttpCall ($url);}} private function makeAjaxCall ($url) {/ / request and return promise} private function makeHttpCall ($url) {/ / request and return promise}}

In the above code, for the fetch method in the HttpRequester class, if I add a new xxxAdapter class and want to use it in the fetch method, I need to modify the class in the HttpRequester class (such as adding an elseif judgment), and through the following code, this problem can be well solved. The following code is a good example of how to add new features without changing the original code.

Good:

Interface Adapter {public function request ($url);} class AjaxAdapter implements Adapter {public function request ($url) {/ / request and return promise}} class NodeAdapter implements Adapter {public function request ($url) {/ / request and return promise}} class HttpRequester {private $adapter; public function _ construct (Adapter $adapter) {$this- > adapter = $adapter } public function fetch ($url) {return $this- > adapter- > request ($url);}}

Richter substitution principle Liskov Substitution Principle (LSP)

The explanation for this concept is that if you have a parent class and a subclass, the parent class and subclass can be interchangeable without changing the correctness of the original result. This sounds a little confusing, so let's look at a classic square-rectangle example. Mathematically, a square is a rectangle, but when your model uses the "is-a" relationship through inheritance, it is wrong.

Bad:

Class Rectangle {protected $width = 0; protected $height = 0; public function render ($area) {/ /...} public function setWidth ($width) {$this- > width = $width;} public function setHeight ($height) {$this- > height = $height;} public function getArea () {return $this- > width * $this- > height }} class Square extends Rectangle {public function setWidth ($width) {$this- > width = $this- > height = $width;} public function setHeight (height) {$this- > width = $this- > height = $height;}} function renderLargeRectangles ($rectangles) {foreach ($rectangles as $rectangle) {$rectangle- > setWidth (4); $rectangle- > setHeight (5) $area = $rectangle- > getArea (); / / BAD: Will return 25 for Square. Should be 20. $rectangle- > render ($area);}} $rectangles = [new Rectangle (), new Rectangle (), new Square ()]; renderLargeRectangles ($rectangles)

Good:

Abstract class Shape {protected $width = 0; protected $height = 0; abstract public function getArea (); public function render ($area) {/ /...}} class Rectangle extends Shape {public function setWidth ($width) {$this- > width = $width;} public function setHeight ($height) {$this- > height = $height } public function getArea () {return $this- > width * $this- > height;}} class Square extends Shape {private $length = 0; public function setLength ($length) {$this- > length = $length;} public function getArea () {return pow ($this- > length, 2) } function renderLargeRectangles ($rectangles) {foreach ($rectangles as $rectangle) {if ($rectangle instanceof Square) {$rectangle- > setLength (5);} elseif ($rectangle instanceof Rectangle) {$rectangle- > setWidth (4); $rectangle- > setHeight (5);} $area = $rectangle- > getArea (); $rectangle- > render ($area) }} $shapes = [new Rectangle (), new Rectangle (), new Square ()]; renderLargeRectangles ($shapes)

Interface isolation principle

Interface isolation principle: "the client should not be forced to implement on interfaces it does not need".

There is a clear example to demonstrate this principle. When a class requires a large number of settings, the client will not be required to set a large number of options for convenience, because usually they do not need all the settings. Making the settings optional helps us avoid creating a "fat interface"

Bad:

Interface Employee {public function work (); public function eat ();} class Human implements Employee {public function work () {/ /.... working} public function eat () {/ /. Eating in lunch break}} class Robot implements Employee {public function work () {/ /.... Working much more} public function eat () {/ /.... Robot can't eat, but it must implement this method}}

In the above code, the Robot class does not need the eat () method, but implements the Emplyee interface, so it can only implement all the methods, which allows Robot to implement methods it does not need. Therefore, the Emplyee interface should be split here. The correct code is as follows:

Good:

Interface Workable {public function work ();} interface Feedable {public function eat ();} interface Employee extends Feedable, Workable {} class Human implements Employee {public function work () {/.... working} public function eat () {/ /.... Eating in lunch break}} / / robot can only work class Robot implements Workable {public function work () {/ /.... working}}

Dependency inversion principle Dependency Inversion Principle (DIP)

This principle illustrates two basic points:

Higher-level modules should not rely on lower-level modules, they should all rely on abstraction

Abstraction should not depend on implementation, implementation should depend on abstraction

This may seem a bit obscure at first, but if you have used php frameworks (such as Symfony), you should have seen dependency injection (DI) implement this concept. Although they are not exactly the same concepts, the inversion principle separates the implementation details and creation of high-level modules from those of low-level modules. It can be implemented using dependency injection (DI). The more advantage is that it decouples the modules. Coupling can make it difficult for you to refactoring, which is a very bad development model.

Bad:

Class Employee {public function work () {/ /.... working}} class Robot extends Employee {public function work () {/ /.... Working much more}} class Manager {private $employee; public function _ construct (Employee $employee) {$this- > employee = $employee;} public function manage () {$this- > employee- > work ();}}

Good:

Interface Employee {public function work ();} class Human implements Employee {public function work () {/ /.... working}} class Robot implements Employee {public function work () {/ /.... Working much more}} class Manager {private $employee; public function _ construct (Employee $employee) {$this- > employee = $employee;} public function manage () {$this- > employee- > work ();}}

Don't write duplicate code (DRY)

Everyone should be familiar with this principle.

Try your best to avoid copying code, which is a very bad behavior, and copying code usually means that you need to change more than one place when you need to change some logic.

Bad:

Function showDeveloperList ($developers) {foreach ($developers as $developer) {$expectedSalary = $developer- > calculateExpectedSalary (); $experience = $developer- > getExperience (); $githubLink = $developer- > getGithubLink (); $data = [$expectedSalary, $experience, $githubLink]; render ($data);} function showManagerList ($managers) {foreach ($managers as $manager) {$expectedSalary = $manager- > calculateExpectedSalary () $experience = $manager- > getExperience (); $githubLink = $manager- > getGithubLink (); $data = [$expectedSalary, $experience, $githubLink]; render ($data);}}

Good:

Function showList ($employees) {foreach ($employees as $employee) {$expectedSalary = $employee- > calculateExpectedSalary (); $experience = $employee- > getExperience (); $githubLink = $employee- > getGithubLink (); $data = [$expectedSalary, $experience, $githubLink]; render ($data);}}

Very good:

Function showList ($employees) {foreach ($employees as $employee) {render ([$employee- > calculateExpectedSalary (), $employee- > getExperience (), $employee- > getGithubLink ()]);}} these are all the contents of this article entitled "what are the SOLID principles in PHP?" Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report