php使用Result类优雅的处理业务逻辑返回值
所属分类:php | 发布于 2023-05-02 14:01:55
怎么处理业务逻辑的返回值,一直是困扰自己的一个问题,我们来分析一下。
直到在学习iOS开发过程中,发现在Swift中是使用Result<Data, Error>来处理返回值的,当时就感觉这思想是真的好。后来又在网上看到了,原来在2015的时,就有人出了类似的php版本,真是相见恨晚。
在php中,一般将业务逻辑写在Model中,我们拿一个登录逻辑来举例。
在登录过程中,用户输入用户名和密码,业务逻辑处理登录逻辑,登录过程中,可能发生用户不存在和用户密码错误情况。当登录成功时返回当前的用户信息。
我们来看看处理业务逻辑的三种方法。
第一种方法,登录成功返回用户信息,登录失败返回false
use think\Model;
class User extends Model
{
public function login($username, $password) {
if (!$user = User::where('username', $username)->find()) {
// 用户不存在
return false;
}
if (!password_verify($password, $user['password'])) {
// 用户密码错误
return fasle;
}
return $user;
}
}
用这种方法处理业务逻辑,在控制器无法区分出登录失败的具体原因,抛弃掉。
第二种方法,使用编码来区分业务逻辑
use think\Model;
class User extends Model
{
public function loginWithCode($username, $password) {
$result['code'] = 0;
if (!$user = User::where('username', $username)->find()) {
// 用户不存在
$result['code'] = 101;
$result['message'] = '用户不存在';
return $result;
}
if (!password_verify($password, $user['password'])) {
// 用户密码错误
$result['code'] = 102;
$result['message'] = '密码错误';
return result;
}
$result['user'] = $user;
return $result;
}
}
使用这种方法,返回值是一个包含code字段的数组,当code=0时表示成功,其它情况则表示失败,当失败时,返回message字段,来标记错误原因。
其实这种处理方法,已经基本满足了各种要求,算是处理返回值的一种比较好的方法。
第三种方法,使用Result类来处理业务逻辑返回值
这种方法其实算是第二种方法的改进版。
1、先引入Result类
/**
* 返回结果类
* 可用于各种业务逻辑处理
*/
namespace app\extendLibs;
class Result
{
const SUCCESS = 'success';
const FAIL = 'fail';
protected $resultStatus = ''; // 状态码: success-成功,fail-失败
protected $resultCode = null; // 业务编码: 根据业务需要而定
protected $resultMessage = null; // 业务消息: 根据业务需要而定
protected $data = []; // 返回数据
// 静态实例
private static $instance = null;
// 单例获取方法
public static function getInstance()
{
if (self::$instance == null) {
self::$instance = new self();
}
return self::$instance;
}
// 禁止被实例化
private function __construct()
{
}
// 禁止clone
private function __clone()
{
}
/**
* 设置状态
* @param $code
* @return $this
*/
public function setCode($code = null)
{
!is_null($code) && ($this->resultCode = $code);
return $this;
}
/**
* 获取code
* @return null
*/
public function getCode()
{
return $this->resultCode;
}
/**
* 设置消息
* @param $message
* @return $this
*/
public function setMessage($message = null)
{
!is_null($message) && ($this->resultMessage = $message);
return $this;
}
/**
* 获取message
* @return null
*/
public function getMessage()
{
return $this->resultMessage;
}
public function data($data = null)
{
!is_null($data) && ($this->data = $data);
return $this;
}
/**
* 获取data
* @return array
*/
public function getData()
{
return $this->data;
}
public function success($data = null)
{
$this->resultStatus = self::SUCCESS;
!is_null($data) && ($this->data = $data);
return $this;
}
public function fail($message = null, $code = null)
{
$this->resultStatus = self::FAIL;
$this->resultCode = $code;
$this->resultMessage = $message;
return $this;
}
public function isSuccess() {
return $this->resultStatus == self::SUCCESS;
}
public function isFail() {
return $this->resultStatus == self::FAIL ? true : false;
}
}
2、Result说明
2.1 Result类提供success()和fai()两个方法,用来在Model层返回业务逻辑。
2.2 Result类提供isSuccess()和isFail()两个方法,用来在Controller层判断业务逻辑结果。
2.3 Result类提供了message和code两个可选变量,可以根据需要选择。
3、Model层使用Result类返回业务逻辑
use think\Model;
use app\extendLibs\Result;
class User extends Model
{
public function loginWithResult($username, $password) {
$result = Result::getInstance();
if (!$user = User::where('username', $username)->find()) {
// 用户不存在
return $result->fail("用户不存在", 101);
}
if (!password_verify($password, $user['password'])) {
// 用户密码错误
return $result->fail('密码错误', 102);
}
return $result->success($user);
}
}
4、Controller层处理业务逻辑结果
class UserController extends BaseController
{
protected $user;
protected function initialize()
{
parent::initialize();
$this->user = new User();
}
public function login()
{
$username = input('post.username');
$password = input('post.password');
$result = $this->user->login($username, $password);
if ($result->isSuccess()) {
$data = $result->getData();
// .... 返回结果
return json();
} else {
$code = 100; // 这里可以是系统定义状态码
// $message = '****'; 这里也可以是系统统一的提示信息
$message = $result->getMessage();
$sub_code = $result->getCode(); // 这里是业务状态码,可选择返回与否
// 返回结果
return json();
}
}
}
示例结束,基本上是达到了想要的效果,终于能优雅的处理业务逻辑的返回值了。