php laravel的API版本管理相关类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php laravel的API版本管理相关类相关的知识,希望对你有一定的参考价值。
# laravel的API版本管理相关类
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2019/5/13
* Time: 16:16
*/
namespace App\Helper\Classes\ApiVersion;
use App\Helper\Traits\Singleton;
/**
* api版本管理
*
* 分服务端版本和客户端版本,服务端版本就是api版本。
*
* 如果没有指定api版本或者提交的api版本低于当前最新api版本,就尝试检查是否有旧版本的代码
*
* 没有指定api版本时,需要后缀为_vEmpty
* 指定版本时,需要后缀_v对应版本,可以指定父级版本
*/
class ApiVersion
{
use Singleton;
// 当前版本
protected $version = '1.1.0';
protected $headerVersionKey = 'api-version';
protected $request;
/**
* 控制器目录名
*
* @var string
*/
protected $controllerDirName = 'Version';
/**
* ApiVersion constructor.
* @param $request
*/
public function __construct($request = null)
{
$this->request = $request??request();
}
/**
* 获取http里header的版本
*
* @return array|string|null
*/
protected function getHeaderVersion()
{
return $this->getRequest()->header($this->headerVersionKey, '');
}
/**
* @param bool $prefix
* @return string
*/
protected function getVersionString($prefix = false): string
{
return ($prefix ? 'v' : '') . str_replace('.', '_', $this->getVersion());
}
/**
* @return string
*/
protected function getVersion(): string
{
return $this->version;
}
/**
* 判断当前版本是否大于客户端请求版本,如果true就访问对应版本的代码
*
* @return mixed
*/
public function ifVersionCode()
{
return version_compare($this->getVersion(), $this->getHeaderVersion(), '>');
}
public function ifEmptyVersion()
{
return empty($this->getHeaderVersion());
}
/**
* 修改为对应版本的控制器和方法
*/
public function handleVersionCode()
{
if ($this->ifEmptyVersion()){ // 没有发送客户端版,就使用特定的空版本代码
$this->handleEmptyVersionCode();
return;
}else if (!$this->ifVersionCode()){
return;
}
$classname = $this->getVersionControllerDefaultNamespace();
$controller = $this->handleControllerVersionCode($classname, $this->getHeaderVersionCodeNameArr($classname));
// 存在要改变的控制器
if ($controller !== false) {
$route = $this->getRoute();
$methodName = $route->getActionMethod();
foreach (array_merge($this->getHeaderVersionCodeNameArr($methodName), [$methodName]) as $codeName) {
if (method_exists($controller, $codeName)) { // 特定版本控制器,最精确匹配
$this->setRouteMethod($controller, $codeName);
continue;
}
}
}
}
/**
* 处理不传api版本
*
* 特定的空控制器和空方法都需要在后面带_empty
*/
protected function handleEmptyVersionCode()
{
$classname = $this->getVersionControllerDefaultNamespace();
$controller = $this->handleControllerVersionCode($classname, [$this->handleEmptyVersionName($classname)]);
// 存在要改变的控制器
if ($controller !== false) {
$route = $this->getRoute();
foreach ([$this->handleEmptyVersionName($route->getActionMethod())] as $codeName) {
if (method_exists($controller, $codeName)) { // 特定版本控制器,最精确匹配
$this->setRouteMethod($controller, $codeName);
continue;
}
}
}
}
protected function handleEmptyVersionName($name)
{
return $name . '_vEmpty';
}
/**
* 通过路由类修改对应的控制器和方法
*
* @param $controllerInstance
* @param $methodName
*/
protected function setRouteMethod($controllerInstance, $methodName)
{
$this->getRoute()->controller = $controllerInstance;
$this->getRoute()->uses(get_class($controllerInstance) . '@' . $methodName);
}
protected function handleControllerVersionCode($classname, $versionArr)
{
$controller = false;
if (class_exists($classname)) { // 旧控制器
$controller = app($classname);
}else{ // 指定版本的控制器
foreach ($versionArr as $codeName) {
if (class_exists($codeName)) { // 特定版本控制器,最精确匹配
$controller = app($codeName);
continue;
}
}
}
return $controller;
}
/**
* 获取控制器对应版本代码的默认命名空间
*
* @return mixed
*/
protected function getVersionControllerDefaultNamespace()
{
$route = $this->getRoute();
$replace = 'Controllers\\' . $this->getControllerDirName() . '\\';
return str_replace('Controllers\\', $replace, get_class($route->getController()));
}
/**
* 获取对接类名或者方法名的对应版本的名称
*
* @param $name
* @return array
*/
protected function getHeaderVersionCodeNameArr($name)
{
if (empty($this->getHeaderVersion())) {
return [];
}
$result = [];
$versionArr = $this->handleVersionStringToArr($this->getHeaderVersion());
$result[] = $this->joinVersionItemToCode($name, $this->handleVersionPrefix($this->joinVersionItemToCode(...$versionArr)));
array_pop($versionArr);
$result[] = $this->joinVersionItemToCode($name, $this->handleVersionPrefix($this->joinVersionItemToCode(...$versionArr)));
array_pop($versionArr);
$result[] = $this->joinVersionItemToCode($name, $this->handleVersionPrefix($this->joinVersionItemToCode(...$versionArr)));
return $result;
}
protected function handleVersionPrefix($version)
{
return 'v' . $version;
}
protected function joinVersionItemToCode(...$args)
{
return join('_', $args);
}
/**
* 将字符串的版本信息改为数组
*
* @param $version
* @return array
*/
protected function handleVersionStringToArr($version)
{
$arr = explode('.', $version);
foreach ($arr as &$item) {
$item = intval($item);
}
return $arr + [0, 0, 0];
}
protected function getControllerDirName()
{
return $this->controllerDirName;
}
/**
* @param string $controllerDirName
* @return ApiVersion
*/
public function setControllerDirName(string $controllerDirName)
{
$this->controllerDirName = $controllerDirName;
return $this;
}
protected function getRequest()
{
return $this->request;
}
protected function getRoute()
{
return $this->getRequest()->route();
}
/**
* @param mixed $request
* @return ApiVersion
*/
public function setRequest($request)
{
$this->request = $request;
return $this;
}
}
<?php
/**
* Created by PhpStorm.
* User: code
* Date: 2019/5/13
* Time: 16:47
*/
namespace App\Helper\Classes\ApiVersion;
class ApiVersionMiddleware
{
public function handle($request, \Closure $next)
{
ApiVersion::instance()
->setRequest($request)
->handleVersionCode();
return $next($request);
}
}
以上是关于php laravel的API版本管理相关类的主要内容,如果未能解决你的问题,请参考以下文章