作为一个 PHPer 一直思考 PHP 怎么做高性能(个人基础比较弱),怎么微服务,之前真不知道,不是概念而是怎么落地,谈概念有用但是不落地有点扯
Swoole 没有实际项目用过,swoole 相关框架也没了解过也不知道,获取知道了可能对于之前的问题就可能有一些答案了
Hyperf 的出现简直就是太及时了,文档清晰,框架灵活等等等,简直不要太好
虽然 Hyperf 已经这么好了,但是还是希望把它稍微按照自己喜欢的规范改造一下,这里就把多有对它的改造都定义为自己的开发规范,如果大家觉得有道理可以沿用
感谢 swoole 团队(韩老师等……),感谢 Hyperf 团队(黄老师等……)
看完文章是否可以点个赞!!!!
工欲善其事,必先利其器,它有个名字HyperfCMS
开整(2)
- 操作
- 统一出口`App\Core\Response`,构造api的返回格式
- 利用中间件,给每一次请求打上qid,记录每一次的请求日志
- 贴代码
namespace App\Middleware;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Hyperf\Utils\Context;
/**
* RequestMiddleware
* 接到客户端请求,通过该中间件进行一些调整
* @package App\Middleware
* User:YM
* Date:2019/12/16
* Time:上午12:13
*/
class RequestMiddleware implements MiddlewareInterface
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var ServerRequestInterface
*/
protected $request;
public function __construct(ContainerInterface $container,ServerRequestInterface $request)
{
$this->container = $container;
$this->request = $request;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// 为每一个请求增加一个qid
$request = Context::override(ServerRequestInterface::class, function (ServerRequestInterface $request) {
$request = $request->withAddedHeader('qid', $this->getRequestId());
return $request;
});
// 利用协程上下文存储请求开始的时间,用来计算程序执行时间
Context::set('request_start_time',microtime(true));
$response = $handler->handle($request);
return $response;
}
/**
* getRequestId
* 唯一请求id
* User:YM
* Date:2019/11/18
* Time:下午7:53
* @return string
*/
protected function getRequestId()
{
$tmp = $this->request->getServerParams();
$name = strtoupper(substr(md5(gethostname()), 12, 8));
$remote = strtoupper(substr(md5($tmp['remote_addr']),12,8));
$ip = strtoupper(substr(md5(getServerLocalIp()), 14, 4));
return uniqid(). '-' . $remote. '-'.$ip.'-'. $name;
}
}
namespace App\Core;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\HttpMessage\Cookie\Cookie;
use App\Constants\StatusCode;
use Hyperf\Utils\Context;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
use Hyperf\Utils\Coroutine;
use App\Core\Facade\Log;
use Hyperf\Contract\StdoutLoggerInterface;
/**
* ReqResponse
* 请求响应结果
* @package App\Container
* User:YM
* Date:2019/11/15
* Time:下午5:35
*/
class Response
{
/**
* @var StdoutLoggerInterface
*/
protected $logger;
/**
* @Inject
* @var RequestInterface
*/
protected $request;
/**
* @Inject
* @var ResponseInterface
*/
protected $response;
/**
* success
* 成功返回请求结果
* User:YM
* Date:2019/11/19
* Time:上午11:04
* @param array $data
* @param string|null $msg
* @return \Psr\Http\Message\ResponseInterface
*/
public function success(array $data = [], string $msg = null)
{
$msg = $msg ?? StatusCode::getMessage(StatusCode::SUCCESS);;
$data = [
'qid' => $this->request->getHeaderLine('qid'),
'code' => StatusCode::SUCCESS,
'msg'=> $msg,
'data' => $data
];
$response = $this->response->json($data);
$executionTime = microtime(true) - Context::get('request_start_time');
$rbs = strlen($response->getBody()->getContents());
// 获取日志实例,记录日志
$this->logger = Log::get(requestEntry(Coroutine::getBackTrace()));
$this->logger->info($msg,getLogArguments($executionTime,$rbs));
return $response;
}
/**
* error
* 业务相关错误结果返回
* User:YM
* Date:2019/11/20
* Time:上午10:04
* @param int $code
* @param string|null $msg
* @return \Psr\Http\Message\ResponseInterface
*/
public function error(int $code = StatusCode::ERR_EXCEPTION, string $msg = null)
{
$msg = $msg ?? StatusCode::getMessage($code);;
$data = [
'qid' => $this->request->getHeaderLine('qid'),
'code' => $code,
'msg'=> $msg,
];
return $this->response->json($data);
}
/**
* json
* 直接返回数据
* User:YM
* Date:2019/12/16
* Time:下午4:22
* @param $data
* @return \Psr\Http\Message\ResponseInterface
*/
public function json(array $data)
{
return $this->response->json($data);
}
/**
* xml
* 返回xml数据
* User:YM
* Date:2019/12/16
* Time:下午4:58
* @param $data
* @return \Psr\Http\Message\ResponseInterface
*/
public function xml(array $data)
{
return $this->response->xml($data);
}
/**
* redirect
* 重定向
* User:YM
* Date:2019/12/16
* Time:下午5:00
* @param string $url
* @param string $schema
* @param int $status
* @return \Psr\Http\Message\ResponseInterface
*/
public function redirect(string $url,string $schema = 'http', int $status = 302 )
{
return $this->response->redirect($url,$status,$schema);
}
/**
* download
* 下载文件
* User:YM
* Date:2019/12/16
* Time:下午5:04
* @param string $file
* @param string $name
* @return \Psr\Http\Message\ResponseInterface
*/
public function download(string $file, string $name = '')
{
return $this->response->redirect($file,$name);
}
/**
* cookie
* 设置cookie
* User:YM
* Date:2019/12/16
* Time:下午10:17
* @param string $name
* @param string $value
* @param int $expire
* @param string $path
* @param string $domain
* @param bool $secure
* @param bool $httpOnly
* @param bool $raw
* @param null|string $sameSite
*/
public function cookie(string $name,string $value = '', $expire = 0, string $path = '/', string $domain = '', bool $secure = false, bool $httpOnly = true, bool $raw = false, ?string $sameSite = null)
{
// convert expiration time to a Unix timestamp
if ($expire instanceof \DateTimeInterface) {
$expire = $expire->format('U');
} elseif (! is_numeric($expire)) {
$expire = strtotime($expire);
if ($expire === false) {
throw new \RuntimeException('The cookie expiration time is not valid.');
}
}
$cookie = new Cookie($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite);
$response = $this->response->withCookie($cookie);
Context::set(PsrResponseInterface::class, $response);
return;
}
}