preface

It’s been almost two years since I became a PHPer, and I’ve developed some ideas about how to write readable, extensible code.

Using a reference

Scenario 1: Iterate through an array to get a new data structure

You might write something like this:

$TMP = []; $TMP = []; Foreach ($arr as $k = > $v) {/ / remove the data you want $TMP [$k] [' youwant to] [' youwant to] = $v; . // get the data you want if (...) { $tmp[$k]['youwantbyjudge'] = 'TIGERB'; }... } / / finally to array $TMP you want -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / may you feel the above writing is not very good, Foreach ($arr as $k => $v) {$arr as $k => $v; {/ / facsimile value is what you want $arr [$k] [' youwantbyjudge] = 'TIGERB'}... Unset ($arr[$k]['youwantdel']); } // Finally we get our target array $arrCopy the code

Next we use the reference value:

Foreach ($arr as &$v) {// if (...) $v[' youWantByJudge '] = 'TIGERB'}... Unset ($v['youwantdel']); } unset($v); // Finally we get our target array $arrCopy the code

Using references doesn’t make our code much cleaner, but it also saves memory compared to the first method, especially when manipulating a large array.

Scenario 2: Passing a value to a function to get a new value

This is basically the same as array traversal, we just need to declare this function as a reference, as follows:

function decorate(&$arr = []) { # code... } $arr = [ .... ] ; // Call the function spring ($arr); // Get the new value $arrCopy the code

Using a try… The catch…

Add the following logic:

class UserModel { public function login($username = '', $password = '') { code... if (...) {// The user does not have return-1; } code... if (...) {// Password error return-2; } code... } } class UserController { public function login($username = '', $password = '') { $model = new UserModel(); $res = $model->login($username, $password); If ($res = = = 1) {return [' code '= >' 404 ', 'message' = > 'user does not exist']. } the if ($res = = = 2) {return [' code '= >' 400 ', 'message' = > 'wrong password']. } code... }}Copy the code

We use the try… The catch… After the rewrite:

class UserModel { public function login($username = '', $password = '') { code... if (...) {// throw new Exception(' user does not exist ', '404'); } code... if (...) Throw new Exception(' password error ', '400'); } code... } } class UserController { public function login($username = '', $password = '') { try { $model = new UserModel(); $res = $model->login($username, $password); $db->commit(); $db->commit(); $db->rollback(); $db->rollback(); return [ 'code' => $e->getCode(), 'message' => $e->getMessage() ] } } }Copy the code

By using try… The catch… To make our code logic clearer, try… In, we only need to pay attention to normal business conditions, and the processing of exceptions is unified in catch. So, when we’re writing upstream code, we just throw exceptions.

Using anonymous functions

Builds a block of code inside a function or method

If we have a piece of logic that we need to format data in a function or method, but the code fragment that formats the data appears several times, if we write directly, we might think like this:

function doSomething(...) {... // Format code snippets... . // Format code snippets [duplicate code]... }Copy the code

I’m sure most people don’t write like this, they probably write like this:

function doSomething(...) {... format(...) ; . format(...) ; . } function format() {function format() {// Format the code segment... }Copy the code

There is nothing wrong with writing this way, minimising our code snippets, but what if the format function or method is just used by doSomething? I usually write down like this. Why? Because I think format is a subset of doSomething in this context.

function doSomething() { ... $package = function (...) use (...) {// Also use arguments can pass references // format code snippets... }; . package(...) ; . package(...) ; . }Copy the code

Implementing lazy loading for classes and least Know for design patterns

Suppose you have the following code:

class One { private $instance; Public function __construct() {$this-> int2 = new Two(); $this-> int2 = new Two(); } public function doSomething() { if (...) $this->instance->do($this->instance->do(...)) ; }... }}... $instance = new One(); $instance->doSomething(); .Copy the code

What’s wrong with the way I wrote it?

  • Not conforming to the least-know principle of design patterns, class One internally relies directly on class Two
  • An instance of class Two is not used in all contexts, so it is a waste of resources. Some people say to make a singleton, but it cannot solve the embarrassment of not using the instantiation

So let’s use anonymous functions to solve the above problem. Let’s rewrite it like this:

class One { private $closure; public function __construct(Closure $closure) { $this->closure = $closure; } public function doSomething() { if (...) $this->closure(); $this->closure(); $instance->do(...) }... }}... $instance = new One(function () {return new Two(); }); $instance->doSomething(); .Copy the code

To reduce the if… The else… The use of

If you run into this type of code, it’s a black hole.

function doSomething() { if (...) { if (...) {... } esle { ... } } else { if (...) {... } esle { ... }}}Copy the code

Early return exception

If you’re careful, you might notice that the above case, probably most of the else code is handling an exception, or more likely the exception code is extremely simple, and I usually do this:

Function doSomething() {if (...)} function doSomething() {if (... {// return... ; } if (...) {// return... ; } // Normal logic... } class One {public function doSomething() {if (...) {public function doSomething() {if (...)} {// throw new Exception(...) ; } if (...) {// throw new Exception(...) ; } // Normal logic... }}Copy the code

Associative arrays to map

If we are making a decision on the client side, we usually decide which strategy to choose in different context, usually using if or switch as follows:

class One { public function doSomething() { if (...) { $instance = new A(); } elseif (...). { $instance = new A(); } else { $instance = new C(); } $instance->doSomething(...) ; . }}Copy the code

The above version usually has a large number of if or switch statements, and I usually use a map to map the different policies, like the following:

Class One {private $map = ['a' => 'namespace\ b', 'c' => 'namespace\ c']; private $map = ['a' => 'namespace\ b', 'c' => 'namespace\ c'] public function doSomething() { ... $instance = new $this->map[$strategy]; / / $strategy is' a 'or' b 'or' c '$instance - > doSomething (...). ; . }}Copy the code

Using an interface

Why use interfaces? For example, to design a preferential system, different commodities just have different preferential behaviors under different preferential strategies. We define an interface of preferential behaviors, and finally program the interface. The pseudo-code is as follows

Interface Promotion { public function promote(...) ; } class OnePromotion implement Promotion { public function doSomething(...) {... } } class TwoPromotion implement Promotion { public function doSomething(...) {... }}Copy the code

The controller rejects direct DB operations

The last thing I want to say is never to operate DB directly in your Controller, why? Most of the operations of our program are basically add, delete, change and search, maybe because the query where conditions and fields are different, so sometimes we can abstract the method of add, delete, change and search to the database into the model, and expose our WHERE and fields conditions through parameters. Often this can greatly improve efficiency and code reuse. For example:

class DemoModel implement Model { public function getMultiDate($where = [], $fields = ['id'], $orderby = 'id asc') { $this->where($where) ->field($fields) ->orderby($orderby) ->get(); }}Copy the code

The last

If there is something wrong, please correct it

Easy PHP: a fast and lightweight PHP full-stack framework