Awesome tips for PHP.
减少if…else 的使用
if...else
通常是一个糟糕的选择,它导致设计复杂,代码可读性差,并且可能导致重构困难。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function doSomething() { if (...) { if (...) { } esle { } } else { if (...) { } esle { } } }
|
好在可以通过其他方式可以避免对if...else
的过度依赖:
- 提前 return:
1 2 3 4 5 6 7
| public function run($input){ if ($input > 5){ } else { } }
|
只需要删除else
块,即可简化此过程:
1 2 3 4 5 6 7 8
| public function run($input){ if ($input > 5){ return; } }
|
switch...case
也是不错地选择:1 2 3 4 5 6 7 8 9 10 11 12 13
| public function run($input){ switch($input){ case "A": break; case "B": break } }
|
使用try…catch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class UserModel { public function login($username = '', $password = '') { if (...) { return -1; } if (...) { return -2; } } }
class UserController { public function login($username = '', $password = '') { $model = new UserModel(); $res = $model->login($username, $password); if ($res === -1) { return [ 'code' => '404', 'message' => '用户不存在' ]; } if ($res === -2) { return [ 'code' => '400', 'message' => '密码错误' ]; } } }
|
使用try...catch
重写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class UserModel { public function login($username = '', $password = '') { if (...) { throw new Exception('用户不存在', '404'); }
if (...) { throw new Exception('密码错误', '400'); } } }
class UserController { public function login($username = '', $password = '') { try { $model = new UserModel(); $res = $model->login($username, $password); } catch (Exception $e) { } } }
|
通过使用try...catch
重写,使得代码逻辑职责分明、更加清晰。try
只用关心业务正常情况的处理,而所有异常则统一在catch
中处理,上游只需将异常抛出即可。
使用匿名函数
需要在一个方法中,重复处理某个逻辑,这时可能会将其封装成一个函数,即:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function doSomething(...) { format(...); format(...); }
function format() { }
|
上面这段代码并没有什么问题,但是如果这个函数仅仅只在doSomething
中使用呢?更好地做法应该是这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function doSomething() { $format = function (...) use (...) { }; $format(...); $format(...); }
|
简单的策略模式
客户端在做决策时,通常会根据不同的上下文环境选择不同的策略,可能会写成下面这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class One { public function doSomething() { if (...) { $instance = new A(); } elseif (...) { $instance = new B(); } else { $instance = new C(); } $instance->doSomething(...); } }
|
上面这种情况,无论是使用if...else
还是switch...case
当策略增多时,都会出现大量分支逻辑判断,好写的做法是定义一个简单的策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class One { private $map = [ 'a' => 'namespace\A', 'b' => 'namespace\B', 'c' => 'namespace\C' ]; public function doSomething() { $instance = new $this->map[$strategy]; $instance->doSomething(...); } }
|
依赖注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class One { private $instance;
public function __construct() { $this->intance = new Two(); }
public function doSomething() { if (...) { $this->instance->do(...); } ... } }
$instance = new One(); $instance->doSomething();
|
上面这段代码有什么问题?
- 不符合设计模式的最少知道原则,One 类内部直接依赖了Two 类。
使用依赖注入重写此类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class One { private $closure;
public function __construct(Closure $closure) { $this->closure = $closure; }
public function doSomething() { if (...) { $instance = $this->closure(); $instance->do(...) } ... } } ...
$instance = new One(function () { return new Two(); }); $instance->doSomething();
|
isset 语法糖
isset
语法糖:
1 2 3 4 5
| $name = isset($params["name"]) ? isset($params["name"]) : "";
$name = isset($params["name"]) ?: "";
$name = $params["name"] ?? "";
|
原文地址