基于Hyperf实现简易消息推送系统代码上线
commit
ef4a9d4688
@ -0,0 +1,17 @@
|
||||
APP_NAME=skeleton
|
||||
APP_ENV=dev
|
||||
|
||||
DB_DRIVER=mysql
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=hyperf
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
DB_CHARSET=utf8mb4
|
||||
DB_COLLATION=utf8mb4_unicode_ci
|
||||
DB_PREFIX=
|
||||
|
||||
REDIS_HOST=localhost
|
||||
REDIS_AUTH=(null)
|
||||
REDIS_PORT=6379
|
||||
REDIS_DB=0
|
@ -0,0 +1,13 @@
|
||||
.buildpath
|
||||
.settings/
|
||||
.project
|
||||
*.patch
|
||||
.idea/
|
||||
.git/
|
||||
runtime/
|
||||
vendor/
|
||||
.phpintel/
|
||||
.env
|
||||
.DS_Store
|
||||
*.lock
|
||||
.phpunit*
|
@ -0,0 +1,60 @@
|
||||
# Default Dockerfile
|
||||
#
|
||||
# @link https://www.hyperf.io
|
||||
# @document https://hyperf.wiki
|
||||
# @contact group@hyperf.io
|
||||
# @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
|
||||
|
||||
FROM hyperf/hyperf:7.4-alpine-v3.11-cli
|
||||
LABEL maintainer="Hyperf Developers <group@hyperf.io>" version="1.0" license="MIT" app.name="Hyperf"
|
||||
|
||||
##
|
||||
# ---------- env settings ----------
|
||||
##
|
||||
# --build-arg timezone=Asia/Shanghai
|
||||
ARG timezone
|
||||
|
||||
ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \
|
||||
COMPOSER_VERSION=1.10.10 \
|
||||
APP_ENV=prod \
|
||||
SCAN_CACHEABLE=(true)
|
||||
|
||||
# update
|
||||
RUN set -ex \
|
||||
# install composer
|
||||
&& cd /tmp \
|
||||
&& wget https://github.com/composer/composer/releases/download/${COMPOSER_VERSION}/composer.phar \
|
||||
&& chmod u+x composer.phar \
|
||||
&& mv composer.phar /usr/local/bin/composer \
|
||||
# show php version and extensions
|
||||
&& php -v \
|
||||
&& php -m \
|
||||
&& php --ri swoole \
|
||||
# ---------- some config ----------
|
||||
&& cd /etc/php7 \
|
||||
# - config PHP
|
||||
&& { \
|
||||
echo "upload_max_filesize=128M"; \
|
||||
echo "post_max_size=128M"; \
|
||||
echo "memory_limit=1G"; \
|
||||
echo "date.timezone=${TIMEZONE}"; \
|
||||
} | tee conf.d/99_overrides.ini \
|
||||
# - config timezone
|
||||
&& ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
|
||||
&& echo "${TIMEZONE}" > /etc/timezone \
|
||||
# ---------- clear works ----------
|
||||
&& rm -rf /var/cache/apk/* /tmp/* /usr/share/man \
|
||||
&& echo -e "\033[42;37m Build Completed :).\033[0m\n"
|
||||
|
||||
WORKDIR /opt/www
|
||||
|
||||
# Composer Cache
|
||||
# COPY ./composer.* /opt/www/
|
||||
# RUN composer install --no-dev --no-scripts
|
||||
|
||||
COPY . /opt/www
|
||||
RUN composer install --no-dev -o && php bin/hyperf.php
|
||||
|
||||
EXPOSE 9501
|
||||
|
||||
ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"]
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Amqp\Consumer;
|
||||
|
||||
use Hyperf\Amqp\Annotation\Consumer;
|
||||
use Hyperf\Amqp\Message\ConsumerMessage;
|
||||
use Hyperf\Amqp\Result;
|
||||
use Hyperf\Server\ServerFactory;
|
||||
|
||||
/**
|
||||
* @Consumer(exchange="hyperf", routingKey="hyperf", queue="hyperf", nums=1)
|
||||
*/
|
||||
class DemoConsumer extends ConsumerMessage
|
||||
{
|
||||
/**
|
||||
* RabbitMQ消费端代码
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
public function consume($data): string
|
||||
{
|
||||
// 获取集合中所有的value
|
||||
$redis = $this->container->get(\Redis::class);
|
||||
$fdList = $redis->sMembers('websocket_sjd_1');
|
||||
|
||||
$server = $this->container->get(ServerFactory::class)->getServer()->getServer();
|
||||
foreach ($fdList as $fd) {
|
||||
if (!empty($fd)) {
|
||||
$server->push((int)$fd, $data);
|
||||
}
|
||||
}
|
||||
|
||||
return Result::ACK;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Amqp\Producer;
|
||||
|
||||
use Hyperf\Amqp\Annotation\Producer;
|
||||
use Hyperf\Amqp\Message\ProducerMessage;
|
||||
|
||||
/**
|
||||
* @Producer(exchange="hyperf", routingKey="hyperf")
|
||||
*/
|
||||
class DemoProducer extends ProducerMessage
|
||||
{
|
||||
public function __construct($data)
|
||||
{
|
||||
// 设置不同 pool
|
||||
$this->poolName = 'default';
|
||||
|
||||
// 具体丢入队列中的信息
|
||||
$this->payload = $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Controller;
|
||||
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
use Hyperf\HttpServer\Contract\ResponseInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
abstract class AbstractController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
* @var RequestInterface
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
* @var ResponseInterface
|
||||
*/
|
||||
protected $response;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Controller;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$user = $this->request->input('user', 'Hyperf');
|
||||
$method = $this->request->getMethod();
|
||||
|
||||
return [
|
||||
'method' => $method,
|
||||
'message' => "Hello {$user}.",
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Amqp\Producer\DemoProducer;
|
||||
use Hyperf\Amqp\Producer;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
|
||||
class MainController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* index
|
||||
* @return array
|
||||
*/
|
||||
public function index() : array
|
||||
{
|
||||
$name = $this->request->input('name', 'Hyperf');
|
||||
$num = $this->request->input('num', 'test12345');
|
||||
$door = $this->request->input('door', '办公室');
|
||||
|
||||
$data = [
|
||||
'code' => 200,
|
||||
'data' => [
|
||||
'userOutName' => $name,
|
||||
'userOutNum' => $num,
|
||||
'recordOutTime' => date('Y-m-d H:i:s'),
|
||||
'doorOutName' => $door
|
||||
]
|
||||
];
|
||||
$data = json_encode($data);
|
||||
// 组装队列消息
|
||||
$message = new DemoProducer($data);
|
||||
// 通过容器获取队列生产者实例
|
||||
$producer = ApplicationContext::getContainer()->get(Producer::class);
|
||||
// 生产消息
|
||||
$result = $producer->produce($message);
|
||||
var_dump($result);
|
||||
|
||||
return [
|
||||
'code' => 200,
|
||||
'msg' => "Push success!",
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Hyperf\Contract\OnCloseInterface;
|
||||
use Hyperf\Contract\OnMessageInterface;
|
||||
use Hyperf\Contract\OnOpenInterface;
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\Websocket\Frame;
|
||||
|
||||
class WebSocketController extends AbstractController implements OnMessageInterface, OnOpenInterface, OnCloseInterface
|
||||
{
|
||||
/**
|
||||
* 发送消息
|
||||
* @param $server
|
||||
* @param Frame $frame
|
||||
*/
|
||||
public function onMessage($server, Frame $frame): void
|
||||
{
|
||||
$redis = $this->container->get(\Redis::class);
|
||||
// 获取所有的客户端id
|
||||
$fdList = $redis->sMembers('websocket_sjd_1');
|
||||
// 如果当前客户端在客户端集合中,就刷新
|
||||
if (in_array($frame->fd, $fdList)) {
|
||||
$redis->sAdd('websocket_sjd_1', $frame->fd);
|
||||
$redis->expire('websocket_sjd_1', 7200);
|
||||
}
|
||||
|
||||
// push消息给客户端
|
||||
$server->push($frame->fd, json_encode(['Recv' => $frame->data]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端失去连接
|
||||
* @param $server
|
||||
* @param int $fd
|
||||
* @param int $reactorId
|
||||
*/
|
||||
public function onClose($server, int $fd, int $reactorId): void
|
||||
{
|
||||
$redis = $this->container->get(\Redis::class);
|
||||
// 移除集合中指定的value
|
||||
$redis->sRem('websocket_sjd_1', $fd);
|
||||
echo 'closed';
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端连接开启
|
||||
* @param $server
|
||||
* @param Request $request
|
||||
*/
|
||||
public function onOpen($server, Request $request): void
|
||||
{
|
||||
$redis = $this->container->get(\Redis::class);
|
||||
// 保存客户端id
|
||||
$resAdd = $redis->sAdd('websocket_sjd_1', $request->fd);
|
||||
var_dump($resAdd);
|
||||
|
||||
$resExp = $redis->expire('websocket_sjd_1', 7200);
|
||||
var_dump($resExp);
|
||||
|
||||
// push消息给客户端
|
||||
$server->push($request->fd, json_encode(['Status' => 'Opened']));
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Exception;
|
||||
|
||||
use App\Constants\ErrorCode;
|
||||
use Hyperf\Server\Exception\ServerException;
|
||||
use Throwable;
|
||||
|
||||
class BusinessException extends ServerException
|
||||
{
|
||||
public function __construct(int $code = 0, string $message = null, Throwable $previous = null)
|
||||
{
|
||||
if (is_null($message)) {
|
||||
$message = ErrorCode::getMessage($code);
|
||||
}
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Exception\Handler;
|
||||
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\ExceptionHandler\ExceptionHandler;
|
||||
use Hyperf\HttpMessage\Stream\SwooleStream;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Throwable;
|
||||
|
||||
class AppExceptionHandler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* @var StdoutLoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct(StdoutLoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function handle(Throwable $throwable, ResponseInterface $response)
|
||||
{
|
||||
$this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
|
||||
$this->logger->error($throwable->getTraceAsString());
|
||||
return $response->withHeader('Server', 'Hyperf')->withStatus(500)->withBody(new SwooleStream('Internal Server Error.'));
|
||||
}
|
||||
|
||||
public function isValid(Throwable $throwable): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Listener;
|
||||
|
||||
use Hyperf\Database\Events\QueryExecuted;
|
||||
use Hyperf\Event\Annotation\Listener;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use Hyperf\Logger\LoggerFactory;
|
||||
use Hyperf\Utils\Arr;
|
||||
use Hyperf\Utils\Str;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @Listener
|
||||
*/
|
||||
class DbQueryExecutedListener implements ListenerInterface
|
||||
{
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->logger = $container->get(LoggerFactory::class)->get('sql');
|
||||
}
|
||||
|
||||
public function listen(): array
|
||||
{
|
||||
return [
|
||||
QueryExecuted::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param QueryExecuted $event
|
||||
*/
|
||||
public function process(object $event)
|
||||
{
|
||||
if ($event instanceof QueryExecuted) {
|
||||
$sql = $event->sql;
|
||||
if (! Arr::isAssoc($event->bindings)) {
|
||||
foreach ($event->bindings as $key => $value) {
|
||||
$sql = Str::replaceFirst('?', "'{$value}'", $sql);
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->info(sprintf('[%s] %s', $event->time, $sql));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Listener;
|
||||
|
||||
use Hyperf\AsyncQueue\Event\AfterHandle;
|
||||
use Hyperf\AsyncQueue\Event\BeforeHandle;
|
||||
use Hyperf\AsyncQueue\Event\Event;
|
||||
use Hyperf\AsyncQueue\Event\FailedHandle;
|
||||
use Hyperf\AsyncQueue\Event\RetryHandle;
|
||||
use Hyperf\Event\Annotation\Listener;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
|
||||
use Hyperf\Logger\LoggerFactory;
|
||||
|
||||
/**
|
||||
* @Listener
|
||||
*/
|
||||
class QueueHandleListener implements ListenerInterface
|
||||
{
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var FormatterInterface
|
||||
*/
|
||||
protected $formatter;
|
||||
|
||||
public function __construct(LoggerFactory $loggerFactory, FormatterInterface $formatter)
|
||||
{
|
||||
$this->logger = $loggerFactory->get('queue');
|
||||
$this->formatter = $formatter;
|
||||
}
|
||||
|
||||
public function listen(): array
|
||||
{
|
||||
return [
|
||||
AfterHandle::class,
|
||||
BeforeHandle::class,
|
||||
FailedHandle::class,
|
||||
RetryHandle::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function process(object $event)
|
||||
{
|
||||
if ($event instanceof Event && $event->message->job()) {
|
||||
$job = $event->message->job();
|
||||
$jobClass = get_class($job);
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
switch (true) {
|
||||
case $event instanceof BeforeHandle:
|
||||
$this->logger->info(sprintf('[%s] Processing %s.', $date, $jobClass));
|
||||
break;
|
||||
case $event instanceof AfterHandle:
|
||||
$this->logger->info(sprintf('[%s] Processed %s.', $date, $jobClass));
|
||||
break;
|
||||
case $event instanceof FailedHandle:
|
||||
$this->logger->error(sprintf('[%s] Failed %s.', $date, $jobClass));
|
||||
$this->logger->error($this->formatter->format($event->getThrowable()));
|
||||
break;
|
||||
case $event instanceof RetryHandle:
|
||||
$this->logger->warning(sprintf('[%s] Retried %s.', $date, $jobClass));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Model;
|
||||
|
||||
use Hyperf\DbConnection\Model\Model as BaseModel;
|
||||
|
||||
abstract class Model extends BaseModel
|
||||
{
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Process;
|
||||
|
||||
use Hyperf\AsyncQueue\Process\ConsumerProcess;
|
||||
use Hyperf\Process\Annotation\Process;
|
||||
|
||||
/**
|
||||
* @Process
|
||||
*/
|
||||
class AsyncQueueConsumer extends ConsumerProcess
|
||||
{
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
ini_set('display_startup_errors', 'on');
|
||||
|
||||
error_reporting(E_ALL);
|
||||
|
||||
! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
|
||||
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
|
||||
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
|
||||
// Self-called anonymous function that creates its own scope and keep the global namespace clean.
|
||||
(function () {
|
||||
Hyperf\Di\ClassLoader::init();
|
||||
/** @var \Psr\Container\ContainerInterface $container */
|
||||
$container = require BASE_PATH . '/config/container.php';
|
||||
|
||||
$application = $container->get(\Hyperf\Contract\ApplicationInterface::class);
|
||||
$application->run();
|
||||
})();
|
@ -0,0 +1,80 @@
|
||||
{
|
||||
"name": "hyperf/hyperf-skeleton",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"php",
|
||||
"swoole",
|
||||
"framework",
|
||||
"hyperf",
|
||||
"microservice",
|
||||
"middleware"
|
||||
],
|
||||
"description": "A coroutine framework that focuses on hyperspeed and flexible, specifically use for build microservices and middlewares.",
|
||||
"license": "Apache-2.0",
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"ext-json": "*",
|
||||
"ext-redis": "*",
|
||||
"ext-swoole": ">=4.5",
|
||||
"hyperf/cache": "~2.0.0",
|
||||
"hyperf/command": "~2.0.0",
|
||||
"hyperf/config": "~2.0.0",
|
||||
"hyperf/db-connection": "~2.0.0",
|
||||
"hyperf/framework": "~2.0.0",
|
||||
"hyperf/guzzle": "~2.0.0",
|
||||
"hyperf/http-server": "~2.0.0",
|
||||
"hyperf/logger": "~2.0.0",
|
||||
"hyperf/memory": "~2.0.0",
|
||||
"hyperf/process": "~2.0.0",
|
||||
"hyperf/redis": "~2.0.0",
|
||||
"hyperf/json-rpc": "~2.0.0",
|
||||
"hyperf/rpc": "~2.0.0",
|
||||
"hyperf/rpc-client": "~2.0.0",
|
||||
"hyperf/rpc-server": "~2.0.0",
|
||||
"hyperf/constants": "~2.0.0",
|
||||
"hyperf/async-queue": "~2.0.0",
|
||||
"hyperf/amqp": "~2.0.0",
|
||||
"hyperf/websocket-server": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"swoole/ide-helper": "^4.5",
|
||||
"friendsofphp/php-cs-fixer": "^2.14",
|
||||
"mockery/mockery": "^1.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"hyperf/devtool": "~2.0.0",
|
||||
"hyperf/testing": "~2.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-openssl": "Required to use HTTPS.",
|
||||
"ext-json": "Required to use JSON.",
|
||||
"ext-pdo": "Required to use MySQL Client.",
|
||||
"ext-pdo_mysql": "Required to use MySQL Client.",
|
||||
"ext-redis": "Required to use Redis Client."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/"
|
||||
},
|
||||
"files": []
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"HyperfTest\\": "./test/"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"extra": [],
|
||||
"scripts": {
|
||||
"post-root-package-install": [
|
||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||
],
|
||||
"post-autoload-dump": [
|
||||
"rm -rf runtime/container"
|
||||
],
|
||||
"test": "co-phpunit -c phpunit.xml --colors=always",
|
||||
"cs-fix": "php-cs-fixer fix $1",
|
||||
"analyse": "phpstan analyse --memory-limit 300M -l 0 -c phpstan.neon ./app ./config",
|
||||
"start": "php ./bin/hyperf.php start"
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'default' => [
|
||||
'host' => 'localhost',
|
||||
'port' => 5672,
|
||||
'user' => 'guest',
|
||||
'password' => 'guest',
|
||||
'vhost' => '/',
|
||||
'pool' => [
|
||||
'min_connections' => 1,
|
||||
'max_connections' => 10,
|
||||
'connect_timeout' => 10.0,
|
||||
'wait_timeout' => 3.0,
|
||||
'heartbeat' => -1,
|
||||
],
|
||||
'params' => [
|
||||
'insist' => false,
|
||||
'login_method' => 'AMQPLAIN',
|
||||
'login_response' => null,
|
||||
'locale' => 'en_US',
|
||||
'connection_timeout' => 3.0,
|
||||
'read_write_timeout' => 6.0,
|
||||
'context' => null,
|
||||
'keepalive' => false,
|
||||
'heartbeat' => 3,
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'scan' => [
|
||||
'paths' => [
|
||||
BASE_PATH . '/app',
|
||||
],
|
||||
'ignore_annotations' => [
|
||||
'mixin',
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
];
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'default' => [
|
||||
'driver' => Hyperf\AsyncQueue\Driver\RedisDriver::class,
|
||||
'channel' => 'queue',
|
||||
'timeout' => 2,
|
||||
'retry_seconds' => 5,
|
||||
'handle_timeout' => 10,
|
||||
'processes' => 1,
|
||||
],
|
||||
];
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'default' => [
|
||||
'driver' => Hyperf\Cache\Driver\RedisDriver::class,
|
||||
'packer' => Hyperf\Utils\Packer\PhpSerializerPacker::class,
|
||||
'prefix' => 'c:',
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
];
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'default' => [
|
||||
'driver' => env('DB_DRIVER', 'mysql'),
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
'database' => env('DB_DATABASE', 'hyperf'),
|
||||
'port' => env('DB_PORT', 3306),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'collation' => env('DB_COLLATION', 'utf8_unicode_ci'),
|
||||
'prefix' => env('DB_PREFIX', ''),
|
||||
'pool' => [
|
||||
'min_connections' => 1,
|
||||
'max_connections' => 10,
|
||||
'connect_timeout' => 10.0,
|
||||
'wait_timeout' => 3.0,
|
||||
'heartbeat' => -1,
|
||||
'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60),
|
||||
],
|
||||
'commands' => [
|
||||
'gen:model' => [
|
||||
'path' => 'app/Model',
|
||||
'force_casts' => true,
|
||||
'inheritance' => 'Model',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
];
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'generator' => [
|
||||
'amqp' => [
|
||||
'consumer' => [
|
||||
'namespace' => 'App\\Amqp\\Consumer',
|
||||
],
|
||||
'producer' => [
|
||||
'namespace' => 'App\\Amqp\\Producer',
|
||||
],
|
||||
],
|
||||
'aspect' => [
|
||||
'namespace' => 'App\\Aspect',
|
||||
],
|
||||
'command' => [
|
||||
'namespace' => 'App\\Command',
|
||||
],
|
||||
'controller' => [
|
||||
'namespace' => 'App\\Controller',
|
||||
],
|
||||
'job' => [
|
||||
'namespace' => 'App\\Job',
|
||||
],
|
||||
'listener' => [
|
||||
'namespace' => 'App\\Listener',
|
||||
],
|
||||
'middleware' => [
|
||||
'namespace' => 'App\\Middleware',
|
||||
],
|
||||
'Process' => [
|
||||
'namespace' => 'App\\Processes',
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'handler' => [
|
||||
'http' => [
|
||||
Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
|
||||
App\Exception\Handler\AppExceptionHandler::class,
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
];
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'default' => [
|
||||
'handler' => [
|
||||
'class' => Monolog\Handler\StreamHandler::class,
|
||||
'constructor' => [
|
||||
'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
|
||||
'level' => Monolog\Logger::DEBUG,
|
||||
],
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [
|
||||
'format' => null,
|
||||
'dateFormat' => 'Y-m-d H:i:s',
|
||||
'allowInlineLineBreaks' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'http' => [
|
||||
],
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
];
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'default' => [
|
||||
'host' => env('REDIS_HOST', 'localhost'),
|
||||
'auth' => env('REDIS_AUTH', null),
|
||||
'port' => (int) env('REDIS_PORT', 6379),
|
||||
'db' => (int) env('REDIS_DB', 0),
|
||||
'pool' => [
|
||||
'min_connections' => 1,
|
||||
'max_connections' => 10,
|
||||
'connect_timeout' => 10.0,
|
||||
'wait_timeout' => 3.0,
|
||||
'heartbeat' => -1,
|
||||
'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60),
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
use Hyperf\Server\Server;
|
||||
use Hyperf\Server\SwooleEvent;
|
||||
|
||||
return [
|
||||
'mode' => SWOOLE_PROCESS,
|
||||
'servers' => [
|
||||
[
|
||||
'name' => 'http',
|
||||
'type' => Server::SERVER_HTTP,
|
||||
'host' => '0.0.0.0',
|
||||
'port' => 9501,
|
||||
'sock_type' => SWOOLE_SOCK_TCP,
|
||||
'callbacks' => [
|
||||
SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'ws',
|
||||
'type' => Server::SERVER_WEBSOCKET,
|
||||
'host' => '0.0.0.0',
|
||||
'port' => 9502,
|
||||
'sock_type' => SWOOLE_SOCK_TCP,
|
||||
'callbacks' => [
|
||||
SwooleEvent::ON_HAND_SHAKE => [Hyperf\WebSocketServer\Server::class, 'onHandShake'],
|
||||
SwooleEvent::ON_MESSAGE => [Hyperf\WebSocketServer\Server::class, 'onMessage'],
|
||||
SwooleEvent::ON_CLOSE => [Hyperf\WebSocketServer\Server::class, 'onClose'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'settings' => [
|
||||
'enable_coroutine' => true,
|
||||
'worker_num' => swoole_cpu_num(),
|
||||
'pid_file' => BASE_PATH . '/runtime/hyperf.pid',
|
||||
'open_tcp_nodelay' => true,
|
||||
'max_coroutine' => 100000,
|
||||
'open_http2_protocol' => true,
|
||||
'max_request' => 100000,
|
||||
'socket_buffer_size' => 2 * 1024 * 1024,
|
||||
'buffer_output_size' => 2 * 1024 * 1024,
|
||||
],
|
||||
'callbacks' => [
|
||||
SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
|
||||
SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
|
||||
SwooleEvent::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
|
||||
],
|
||||
];
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
return [
|
||||
'consumers' => [
|
||||
[
|
||||
// The service name, this name should as same as with the name of service provider.
|
||||
'name' => 'YourServiceName',
|
||||
// The service registry, if `nodes` is missing below, then you should provide this configs.
|
||||
'registry' => [
|
||||
'protocol' => 'consul',
|
||||
'address' => 'Enter the address of service registry',
|
||||
],
|
||||
// If `registry` is missing, then you should provide the nodes configs.
|
||||
'nodes' => [
|
||||
// Provide the host and port of the service provider.
|
||||
// ['host' => 'The host of the service provider', 'port' => 9502]
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
return [
|
||||
'app_name' => env('APP_NAME', 'skeleton'),
|
||||
'app_env' => env('APP_ENV', 'dev'),
|
||||
'scan_cacheable' => env('SCAN_CACHEABLE', false),
|
||||
StdoutLoggerInterface::class => [
|
||||
'log_level' => [
|
||||
LogLevel::ALERT,
|
||||
LogLevel::CRITICAL,
|
||||
LogLevel::DEBUG,
|
||||
LogLevel::EMERGENCY,
|
||||
LogLevel::ERROR,
|
||||
LogLevel::INFO,
|
||||
LogLevel::NOTICE,
|
||||
LogLevel::WARNING,
|
||||
],
|
||||
],
|
||||
];
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* Initialize a dependency injection container that implemented PSR-11 and return the container.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
use Hyperf\Di\Container;
|
||||
use Hyperf\Di\Definition\DefinitionSourceFactory;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
|
||||
$container = new Container((new DefinitionSourceFactory(true))());
|
||||
|
||||
if (! $container instanceof \Psr\Container\ContainerInterface) {
|
||||
throw new RuntimeException('The dependency injection container is invalid.');
|
||||
}
|
||||
return ApplicationContext::setContainer($container);
|
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
use Hyperf\HttpServer\Router\Router;
|
||||
|
||||
Router::addRoute(['GET', 'POST', 'HEAD'], '/', 'App\Controller\IndexController@index');
|
||||
|
||||
Router::get('/favicon.ico', function () {
|
||||
return '';
|
||||
});
|
||||
|
||||
Router::addServer('ws', function () {
|
||||
Router::get('/', 'App\Controller\WebSocketController');
|
||||
});
|
||||
|
||||
Router::addRoute(['GET', 'POST', 'HEAD'],'/main', 'App\Controller\MainController@index');
|
@ -0,0 +1,30 @@
|
||||
version: '3.7'
|
||||
services:
|
||||
hyperf:
|
||||
image: $REGISTRY_URL/$PROJECT_NAME:test
|
||||
environment:
|
||||
- "APP_PROJECT=hyperf"
|
||||
- "APP_ENV=test"
|
||||
ports:
|
||||
- 9501:9501
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
delay: 5s
|
||||
max_attempts: 5
|
||||
update_config:
|
||||
parallelism: 2
|
||||
delay: 5s
|
||||
order: start-first
|
||||
networks:
|
||||
- hyperf_net
|
||||
configs:
|
||||
- source: hyperf_v1.0
|
||||
target: /opt/www/.env
|
||||
configs:
|
||||
hyperf_v1.0:
|
||||
external: true
|
||||
networks:
|
||||
hyperf_net:
|
||||
external: true
|
@ -0,0 +1,10 @@
|
||||
# Magic behaviour with __get, __set, __call and __callStatic is not exactly static analyser-friendly :)
|
||||
# Fortunately, You can ingore it by the following config.
|
||||
#
|
||||
# vendor/bin/phpstan analyse app --memory-limit 200M -l 0
|
||||
#
|
||||
parameters:
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
ignoreErrors:
|
||||
- '#Static call to instance method Hyperf\\HttpServer\\Router\\Router::[a-zA-Z0-9\\_]+\(\)#'
|
||||
- '#Static call to instance method Hyperf\\DbConnection\\Db::[a-zA-Z0-9\\_]+\(\)#'
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="./test/bootstrap.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="Tests">
|
||||
<directory suffix="Test.php">./test</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">./app</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace HyperfTest\Cases;
|
||||
|
||||
use HyperfTest\HttpTestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
class ExampleTest extends HttpTestCase
|
||||
{
|
||||
public function testExample()
|
||||
{
|
||||
$this->assertTrue(true);
|
||||
$this->assertTrue(is_array($this->get('/')));
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace HyperfTest;
|
||||
|
||||
use Hyperf\Testing\Client;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Class HttpTestCase.
|
||||
* @method get($uri, $data = [], $headers = [])
|
||||
* @method post($uri, $data = [], $headers = [])
|
||||
* @method json($uri, $data = [], $headers = [])
|
||||
* @method file($uri, $data = [], $headers = [])
|
||||
* @method request($method, $path, $options = [])
|
||||
*/
|
||||
abstract class HttpTestCase extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
parent::__construct($name, $data, $dataName);
|
||||
$this->client = make(Client::class);
|
||||
}
|
||||
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
return $this->client->{$name}(...$arguments);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
ini_set('display_errors', 'on');
|
||||
ini_set('display_startup_errors', 'on');
|
||||
|
||||
error_reporting(E_ALL);
|
||||
date_default_timezone_set('Asia/Shanghai');
|
||||
|
||||
! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
|
||||
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
|
||||
|
||||
Swoole\Runtime::enableCoroutine(true);
|
||||
|
||||
require BASE_PATH . '/vendor/autoload.php';
|
||||
|
||||
Hyperf\Di\ClassLoader::init();
|
||||
|
||||
$container = require BASE_PATH . '/config/container.php';
|
||||
|
||||
$container->get(Hyperf\Contract\ApplicationInterface::class);
|
Loading…
Reference in New Issue