├── .env.example ├── .gitignore ├── .gitlab-ci.yml ├── .php_cs ├── .phpstorm.meta.php ├── Dockerfile ├── README.md ├── app ├── Constants │ └── ErrorCode.php ├── Controller │ ├── Controller.php │ └── IndexController.php ├── Exception │ ├── BusinessException.php │ └── Handler │ │ └── BusinessExceptionHandler.php ├── Kernel │ ├── Functions.php │ ├── Http │ │ └── Response.php │ └── Log │ │ ├── AppendRequestIdProcessor.php │ │ └── LoggerFactory.php ├── Listener │ ├── DbQueryExecutedListener.php │ └── QueueHandleListener.php └── Model │ └── Model.php ├── bin └── hyperf.php ├── composer.json ├── config ├── autoload │ ├── annotations.php │ ├── aspects.php │ ├── async_queue.php │ ├── cache.php │ ├── commands.php │ ├── databases.php │ ├── dependencies.php │ ├── devtool.php │ ├── exceptions.php │ ├── listeners.php │ ├── logger.php │ ├── middlewares.php │ ├── processes.php │ ├── redis.php │ └── server.php ├── config.php ├── container.php └── routes.php ├── deploy.test.yml ├── phpstan.neon ├── phpunit.xml └── test ├── Cases └── ExampleTest.php ├── HttpTestCase.php └── bootstrap.php /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=biz-skeleton 2 | 3 | # Mysql 4 | DB_DRIVER=mysql 5 | DB_HOST=localhost 6 | DB_PORT=3306 7 | DB_DATABASE=hyperf 8 | DB_USERNAME=root 9 | DB_PASSWORD= 10 | DB_CHARSET=utf8mb4 11 | DB_COLLATION=utf8mb4_unicode_ci 12 | DB_PREFIX= 13 | 14 | # Redis 15 | REDIS_HOST=localhost 16 | REDIS_AUTH=(null) 17 | REDIS_PORT=6379 18 | REDIS_DB=0 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .settings/ 3 | .project 4 | *.patch 5 | .idea/ 6 | .git/ 7 | runtime/ 8 | vendor/ 9 | .phpintel/ 10 | .env 11 | .DS_Store 12 | *.lock -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # usermod -aG docker gitlab-runner 2 | 3 | stages: 4 | - build 5 | - deploy 6 | 7 | variables: 8 | PROJECT_NAME: hyperf 9 | REGISTRY_URL: registry-docker.org 10 | 11 | build_test_docker: 12 | stage: build 13 | before_script: 14 | # - git submodule sync --recursive 15 | # - git submodule update --init --recursive 16 | script: 17 | - docker build . -t $PROJECT_NAME 18 | - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:test 19 | - docker push $REGISTRY_URL/$PROJECT_NAME:test 20 | only: 21 | - test 22 | tags: 23 | - builder 24 | 25 | deploy_test_docker: 26 | stage: deploy 27 | script: 28 | - docker stack deploy -c deploy.test.yml --with-registry-auth $PROJECT_NAME 29 | only: 30 | - test 31 | tags: 32 | - test 33 | 34 | build_docker: 35 | stage: build 36 | before_script: 37 | # - git submodule sync --recursive 38 | # - git submodule update --init --recursive 39 | script: 40 | - docker build . -t $PROJECT_NAME 41 | - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:$CI_COMMIT_REF_NAME 42 | - docker tag $PROJECT_NAME $REGISTRY_URL/$PROJECT_NAME:latest 43 | - docker push $REGISTRY_URL/$PROJECT_NAME:$CI_COMMIT_REF_NAME 44 | - docker push $REGISTRY_URL/$PROJECT_NAME:latest 45 | only: 46 | - tags 47 | tags: 48 | - builder 49 | 50 | deploy_docker: 51 | stage: deploy 52 | script: 53 | - echo SUCCESS 54 | only: 55 | - tags 56 | tags: 57 | - builder 58 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | setRiskyAllowed(true) 14 | ->setRules([ 15 | '@PSR2' => true, 16 | '@Symfony' => true, 17 | '@DoctrineAnnotation' => true, 18 | '@PhpCsFixer' => true, 19 | 'header_comment' => [ 20 | 'commentType' => 'PHPDoc', 21 | 'header' => $header, 22 | 'separate' => 'none', 23 | 'location' => 'after_declare_strict', 24 | ], 25 | 'array_syntax' => [ 26 | 'syntax' => 'short' 27 | ], 28 | 'list_syntax' => [ 29 | 'syntax' => 'short' 30 | ], 31 | 'concat_space' => [ 32 | 'spacing' => 'one' 33 | ], 34 | 'blank_line_before_statement' => [ 35 | 'statements' => [ 36 | 'declare', 37 | ], 38 | ], 39 | 'general_phpdoc_annotation_remove' => [ 40 | 'annotations' => [ 41 | 'author' 42 | ], 43 | ], 44 | 'ordered_imports' => [ 45 | 'imports_order' => [ 46 | 'class', 'function', 'const', 47 | ], 48 | 'sort_algorithm' => 'alpha', 49 | ], 50 | 'single_line_comment_style' => [ 51 | 'comment_types' => [ 52 | ], 53 | ], 54 | 'yoda_style' => [ 55 | 'always_move_variable' => false, 56 | 'equal' => false, 57 | 'identical' => false, 58 | ], 59 | 'phpdoc_align' => [ 60 | 'align' => 'left', 61 | ], 62 | 'multiline_whitespace_before_semicolons' => [ 63 | 'strategy' => 'no_multi_line', 64 | ], 65 | 'class_attributes_separation' => true, 66 | 'combine_consecutive_unsets' => true, 67 | 'declare_strict_types' => true, 68 | 'linebreak_after_opening_tag' => true, 69 | 'lowercase_constants' => true, 70 | 'lowercase_static_reference' => true, 71 | 'no_useless_else' => true, 72 | 'no_unused_imports' => true, 73 | 'not_operator_with_successor_space' => true, 74 | 'not_operator_with_space' => false, 75 | 'ordered_class_elements' => true, 76 | 'php_unit_strict' => false, 77 | 'phpdoc_separation' => false, 78 | 'single_quote' => true, 79 | 'standardize_not_equals' => true, 80 | 'multiline_comment_opening_closing' => true, 81 | ]) 82 | ->setFinder( 83 | PhpCsFixer\Finder::create() 84 | ->exclude('public') 85 | ->exclude('runtime') 86 | ->exclude('vendor') 87 | ->in(__DIR__) 88 | ) 89 | ->setUsingCache(false); 90 | -------------------------------------------------------------------------------- /.phpstorm.meta.php: -------------------------------------------------------------------------------- 1 | " version="1.0" license="MIT" 10 | 11 | ## 12 | # ---------- env settings ---------- 13 | ## 14 | # --build-arg timezone=Asia/Shanghai 15 | ARG timezone 16 | 17 | ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \ 18 | APP_ENV=prod 19 | 20 | # update 21 | RUN set -ex \ 22 | && apk update \ 23 | # install composer 24 | && cd /tmp \ 25 | && wget https://mirrors.aliyun.com/composer/composer.phar \ 26 | && chmod u+x composer.phar \ 27 | && mv composer.phar /usr/local/bin/composer \ 28 | # show php version and extensions 29 | && php -v \ 30 | && php -m \ 31 | && php --ri swoole \ 32 | # ---------- some config ---------- 33 | && cd /etc/php7 \ 34 | # - config PHP 35 | && { \ 36 | echo "upload_max_filesize=100M"; \ 37 | echo "post_max_size=108M"; \ 38 | echo "memory_limit=1024M"; \ 39 | echo "date.timezone=${TIMEZONE}"; \ 40 | } | tee conf.d/99_overrides.ini \ 41 | # - config timezone 42 | && ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \ 43 | && echo "${TIMEZONE}" > /etc/timezone \ 44 | # ---------- clear works ---------- 45 | && rm -rf /var/cache/apk/* /tmp/* /usr/share/man \ 46 | && echo -e "\033[42;37m Build Completed :).\033[0m\n" 47 | 48 | WORKDIR /opt/www 49 | 50 | # Composer Cache 51 | # COPY ./composer.* /opt/www/ 52 | # RUN composer install --no-dev --no-scripts 53 | 54 | COPY . /opt/www 55 | RUN composer install --no-dev -o 56 | 57 | EXPOSE 9501 58 | 59 | ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"] 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 介绍 2 | 3 | Hyperf 是基于 `Swoole 4.3+` 实现的高性能、高灵活性的 PHP 持久化框架,内置协程服务器及大量常用的组件,性能较传统基于 `PHP-FPM` 的框架有质的提升,提供超高性能的同时,也保持着极其灵活的可扩展性,标准组件均以最新的 [PSR 标准](https://www.php-fig.org/psr) 实现,基于强大的依赖注入设计可确保框架内的绝大部分组件或类都是可替换的。 4 | 5 | 框架组件库除了常见的协程版的 `MySQL 客户端`、`Redis 客户端`,还为您准备了协程版的 `Eloquent ORM`、`GRPC 服务端及客户端`、`Zipkin (OpenTracing) 客户端`、`Guzzle HTTP 客户端`、`Elasticsearch 客户端`、`Consul 客户端`、`ETCD 客户端`、`AMQP 组件`、`Apollo 配置中心`、`基于令牌桶算法的限流器`、`通用连接池` 等组件的提供也省去了自己去实现对应协程版本的麻烦,并提供了 `依赖注入`、`注解`、`AOP 面向切面编程`、`中间件`、`自定义进程`、`事件管理器`、`简易的 Redis 消息队列和全功能的 RabbitMQ 消息队列` 等非常便捷的功能,满足丰富的技术场景和业务场景,开箱即用。 6 | 7 | # 框架初衷 8 | 9 | 尽管现在基于 PHP 语言开发的框架处于一个百花争鸣的时代,但仍旧没能看到一个优雅的设计与超高性能的共存的完美框架,亦没有看到一个真正为 PHP 微服务铺路的框架,此为 Hyperf 及其团队成员的初衷,我们将持续投入并为此付出努力,也欢迎你加入我们参与开源建设。 10 | 11 | # 设计理念 12 | 13 | `Hyperspeed + Flexibility = Hyperf`,从名字上我们就将 `超高速` 和 `灵活性` 作为 Hyperf 的基因。 14 | 15 | - 对于超高速,我们基于 Swoole 协程并在框架设计上进行大量的优化以确保超高性能的输出。 16 | - 对于灵活性,我们基于 Hyperf 强大的依赖注入组件,组件均基于 [PSR 标准](https://www.php-fig.org/psr) 的契约和由 Hyperf 定义的契约实现,达到框架内的绝大部分的组件或类都是可替换的。 17 | 18 | 基于以上的特点,Hyperf 将存在丰富的可能性,如实现 Web 服务,网关服务,分布式中间件,微服务架构,游戏服务器,物联网(IOT)等。 19 | 20 | # 文档 21 | 22 | [https://doc.hyperf.io/](https://doc.hyperf.io/) -------------------------------------------------------------------------------- /app/Constants/ErrorCode.php: -------------------------------------------------------------------------------- 1 | container = $container; 38 | $this->response = $container->get(Response::class); 39 | $this->request = $container->get(RequestInterface::class); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Controller/IndexController.php: -------------------------------------------------------------------------------- 1 | request->input('user', 'Hyperf'); 19 | $method = $this->request->getMethod(); 20 | return $this->response->success([ 21 | 'user' => $user, 22 | 'method' => $method, 23 | 'message' => 'Hello Hyperf.', 24 | ]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Exception/BusinessException.php: -------------------------------------------------------------------------------- 1 | container = $container; 43 | $this->response = $container->get(Response::class); 44 | $this->logger = $container->get(StdoutLoggerInterface::class); 45 | } 46 | 47 | public function handle(Throwable $throwable, ResponseInterface $response) 48 | { 49 | if ($throwable instanceof BusinessException) { 50 | $this->logger->warning(format_throwable($throwable)); 51 | 52 | return $this->response->fail($throwable->getCode(), $throwable->getMessage()); 53 | } 54 | 55 | $this->logger->error(format_throwable($throwable)); 56 | 57 | return $this->response->fail(ErrorCode::SERVER_ERROR, 'Server Error'); 58 | } 59 | 60 | public function isValid(Throwable $throwable): bool 61 | { 62 | return true; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/Kernel/Functions.php: -------------------------------------------------------------------------------- 1 | get($id); 30 | } 31 | 32 | return $container; 33 | } 34 | } 35 | 36 | if (! function_exists('format_throwable')) { 37 | /** 38 | * Format a throwable to string. 39 | */ 40 | function format_throwable(Throwable $throwable): string 41 | { 42 | return di()->get(FormatterInterface::class)->format($throwable); 43 | } 44 | } 45 | 46 | if (! function_exists('queue_push')) { 47 | /** 48 | * Push a job to async queue. 49 | */ 50 | function queue_push(JobInterface $job, int $delay = 0, string $key = 'default'): bool 51 | { 52 | $driver = di()->get(DriverFactory::class)->get($key); 53 | return $driver->push($job, $delay); 54 | } 55 | } 56 | 57 | if (! function_exists('amqp_produce')) { 58 | /** 59 | * Produce a amqp message. 60 | */ 61 | function amqp_produce(ProducerMessageInterface $message): bool 62 | { 63 | return di()->get(Producer::class)->produce($message, true); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/Kernel/Http/Response.php: -------------------------------------------------------------------------------- 1 | container = $container; 35 | $this->response = $container->get(ResponseInterface::class); 36 | } 37 | 38 | public function success($data = []) 39 | { 40 | return $this->response->json([ 41 | 'code' => 0, 42 | 'data' => $data, 43 | ]); 44 | } 45 | 46 | public function fail($code, $message = '') 47 | { 48 | return $this->response->json([ 49 | 'code' => $code, 50 | 'message' => $message, 51 | ]); 52 | } 53 | 54 | public function redirect($url, $status = 302) 55 | { 56 | return $this->response() 57 | ->withAddedHeader('Location', (string) $url) 58 | ->withStatus($status); 59 | } 60 | 61 | public function cookie(Cookie $cookie) 62 | { 63 | $response = $this->response()->withCookie($cookie); 64 | Context::set(PsrResponseInterface::class, $response); 65 | return $this; 66 | } 67 | 68 | /** 69 | * @return \Hyperf\HttpMessage\Server\Response 70 | */ 71 | public function response() 72 | { 73 | return Context::get(PsrResponseInterface::class); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/Kernel/Log/AppendRequestIdProcessor.php: -------------------------------------------------------------------------------- 1 | get(HyperfLoggerFactory::class)->make(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Listener/DbQueryExecutedListener.php: -------------------------------------------------------------------------------- 1 | logger = $container->get(LoggerFactory::class)->get('sql'); 36 | } 37 | 38 | public function listen(): array 39 | { 40 | return [ 41 | QueryExecuted::class, 42 | ]; 43 | } 44 | 45 | /** 46 | * @param QueryExecuted $event 47 | */ 48 | public function process(object $event) 49 | { 50 | if ($event instanceof QueryExecuted) { 51 | $sql = $event->sql; 52 | if (! Arr::isAssoc($event->bindings)) { 53 | foreach ($event->bindings as $key => $value) { 54 | $sql = Str::replaceFirst('?', "'{$value}'", $sql); 55 | } 56 | } 57 | 58 | $this->logger->info(sprintf('[%s:%s] %s', $event->connectionName, $event->time, $sql)); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/Listener/QueueHandleListener.php: -------------------------------------------------------------------------------- 1 | logger = $container->get(LoggerFactory::class)->get('queue'); 35 | } 36 | 37 | public function listen(): array 38 | { 39 | return [ 40 | AfterHandle::class, 41 | BeforeHandle::class, 42 | FailedHandle::class, 43 | RetryHandle::class, 44 | ]; 45 | } 46 | 47 | public function process(object $event) 48 | { 49 | if ($event instanceof Event && $event->message->job()) { 50 | $job = $event->message->job(); 51 | $jobClass = get_class($job); 52 | if ($job instanceof AnnotationJob) { 53 | $jobClass = sprintf('Job[%s@%s]', $job->class, $job->method); 54 | } 55 | $date = date('Y-m-d H:i:s'); 56 | 57 | switch (true) { 58 | case $event instanceof BeforeHandle: 59 | $this->logger->info(sprintf('[%s] Processing %s.', $date, $jobClass)); 60 | break; 61 | case $event instanceof AfterHandle: 62 | $this->logger->info(sprintf('[%s] Processed %s.', $date, $jobClass)); 63 | break; 64 | case $event instanceof FailedHandle: 65 | $this->logger->error(sprintf('[%s] Failed %s.', $date, $jobClass)); 66 | $this->logger->error(format_throwable($event->getThrowable())); 67 | break; 68 | case $event instanceof RetryHandle: 69 | $this->logger->warning(sprintf('[%s] Retried %s.', $date, $jobClass)); 70 | break; 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/Model/Model.php: -------------------------------------------------------------------------------- 1 | get(\Hyperf\Contract\ApplicationInterface::class); 21 | $application->run(); 22 | })(); 23 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyperf/biz-skeleton", 3 | "type": "project", 4 | "keywords": [ 5 | "php", 6 | "swoole", 7 | "framework", 8 | "hyperf", 9 | "microservice", 10 | "middleware" 11 | ], 12 | "description": "A coroutine framework that focuses on hyperspeed and flexible, specifically use for build microservices and middlewares.", 13 | "license": "MIT", 14 | "require": { 15 | "php": ">=7.2", 16 | "ext-json": "*", 17 | "ext-openssl": "*", 18 | "ext-pdo": "*", 19 | "ext-pdo_mysql": "*", 20 | "ext-redis": "*", 21 | "ext-swoole": ">=4.4", 22 | "hyperf/async-queue": "1.1.*", 23 | "hyperf/cache": "1.1.*", 24 | "hyperf/command": "1.1.*", 25 | "hyperf/config": "1.1.*", 26 | "hyperf/constants": "1.1.*", 27 | "hyperf/contract": "1.1.*", 28 | "hyperf/database": "1.1.*", 29 | "hyperf/db-connection": "1.1.*", 30 | "hyperf/di": "1.1.*", 31 | "hyperf/dispatcher": "1.1.*", 32 | "hyperf/event": "1.1.*", 33 | "hyperf/exception-handler": "1.1.*", 34 | "hyperf/framework": "1.1.*", 35 | "hyperf/guzzle": "1.1.*", 36 | "hyperf/http-server": "1.1.*", 37 | "hyperf/logger": "1.1.*", 38 | "hyperf/model-cache": "1.1.*", 39 | "hyperf/pool": "1.1.*", 40 | "hyperf/process": "1.1.*", 41 | "hyperf/redis": "1.1.*", 42 | "hyperf/utils": "1.1.*" 43 | }, 44 | "require-dev": { 45 | "friendsofphp/php-cs-fixer": "^2.14", 46 | "hyperf/devtool": "1.1.*", 47 | "hyperf/testing": "1.1.*", 48 | "mockery/mockery": "^1.0", 49 | "phpstan/phpstan": "^0.11.2", 50 | "swoole/ide-helper": "dev-master" 51 | }, 52 | "autoload": { 53 | "psr-4": { 54 | "App\\": "app/" 55 | }, 56 | "files": [ 57 | "app/Kernel/Functions.php" 58 | ] 59 | }, 60 | "autoload-dev": { 61 | "psr-4": { 62 | "HyperfTest\\": "test/" 63 | } 64 | }, 65 | "minimum-stability": "dev", 66 | "prefer-stable": true, 67 | "config": { 68 | "sort-packages": true 69 | }, 70 | "extra": [], 71 | "scripts": { 72 | "post-root-package-install": [ 73 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 74 | ], 75 | "post-autoload-dump": [ 76 | "init-proxy.sh" 77 | ], 78 | "analyse": "phpstan analyse --memory-limit 300M -l 0 -c phpstan.neon ./app ./config", 79 | "cs-fix": "php-cs-fixer fix $1", 80 | "init-proxy": "init-proxy.sh", 81 | "start": "php ./bin/hyperf.php start", 82 | "test": "co-phpunit -c phpunit.xml --colors=always" 83 | }, 84 | "repositories": { 85 | "packagist": { 86 | "type": "composer", 87 | "url": "https://mirrors.aliyun.com/composer" 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /config/autoload/annotations.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'paths' => [ 15 | BASE_PATH . '/app', 16 | ], 17 | 'ignore_annotations' => [ 18 | 'mixin', 19 | ], 20 | ], 21 | ]; 22 | -------------------------------------------------------------------------------- /config/autoload/aspects.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'driver' => Hyperf\AsyncQueue\Driver\RedisDriver::class, 15 | 'channel' => '{queue}', 16 | 'timeout' => 2, 17 | 'retry_seconds' => 5, 18 | 'handle_timeout' => 10, 19 | 'processes' => 1, 20 | 'concurrent' => [ 21 | 'limit' => 2, 22 | ], 23 | ], 24 | ]; 25 | -------------------------------------------------------------------------------- /config/autoload/cache.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'driver' => Hyperf\Cache\Driver\RedisDriver::class, 15 | 'packer' => Hyperf\Utils\Packer\PhpSerializerPacker::class, 16 | 'prefix' => 'c:', 17 | ], 18 | ]; 19 | -------------------------------------------------------------------------------- /config/autoload/commands.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'driver' => env('DB_DRIVER', 'mysql'), 15 | 'host' => env('DB_HOST', 'localhost'), 16 | 'port' => env('DB_PORT', 3306), 17 | 'database' => env('DB_DATABASE', 'hyperf'), 18 | 'username' => env('DB_USERNAME', 'root'), 19 | 'password' => env('DB_PASSWORD', ''), 20 | 'charset' => env('DB_CHARSET', 'utf8mb4'), 21 | 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), 22 | 'prefix' => env('DB_PREFIX', ''), 23 | 'pool' => [ 24 | 'min_connections' => 1, 25 | 'max_connections' => 10, 26 | 'connect_timeout' => 10.0, 27 | 'wait_timeout' => 3.0, 28 | 'heartbeat' => -1, 29 | 'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60), 30 | ], 31 | 'cache' => [ 32 | 'handler' => Hyperf\ModelCache\Handler\RedisHandler::class, 33 | 'cache_key' => '{mc:%s:m:%s}:%s:%s', 34 | 'prefix' => 'default', 35 | 'ttl' => 3600 * 24, 36 | 'empty_model_ttl' => 600, 37 | 'load_script' => true, 38 | ], 39 | 'commands' => [ 40 | 'gen:model' => [ 41 | 'path' => 'app/Model', 42 | 'force_casts' => true, 43 | 'inheritance' => 'Model', 44 | 'uses' => '', 45 | 'refresh_fillable' => true, 46 | 'table_mapping' => [], 47 | ], 48 | ], 49 | ], 50 | ]; 51 | -------------------------------------------------------------------------------- /config/autoload/dependencies.php: -------------------------------------------------------------------------------- 1 | App\Kernel\Log\LoggerFactory::class, 14 | ]; 15 | -------------------------------------------------------------------------------- /config/autoload/devtool.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'amqp' => [ 15 | 'consumer' => [ 16 | 'namespace' => 'App\\Amqp\\Consumer', 17 | ], 18 | 'producer' => [ 19 | 'namespace' => 'App\\Amqp\\Producer', 20 | ], 21 | ], 22 | 'aspect' => [ 23 | 'namespace' => 'App\\Aspect', 24 | ], 25 | 'command' => [ 26 | 'namespace' => 'App\\Command', 27 | ], 28 | 'controller' => [ 29 | 'namespace' => 'App\\Controller', 30 | ], 31 | 'job' => [ 32 | 'namespace' => 'App\\Job', 33 | ], 34 | 'listener' => [ 35 | 'namespace' => 'App\\Listener', 36 | ], 37 | 'middleware' => [ 38 | 'namespace' => 'App\\Middleware', 39 | ], 40 | 'Process' => [ 41 | 'namespace' => 'App\\Processes', 42 | ], 43 | ], 44 | ]; 45 | -------------------------------------------------------------------------------- /config/autoload/exceptions.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'http' => [ 15 | App\Exception\Handler\BusinessExceptionHandler::class, 16 | ], 17 | ], 18 | ]; 19 | -------------------------------------------------------------------------------- /config/autoload/listeners.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'handler' => [ 15 | 'class' => Monolog\Handler\StreamHandler::class, 16 | 'constructor' => [ 17 | 'stream' => BASE_PATH . '/runtime/logs/hyperf.log', 18 | 'level' => Monolog\Logger::DEBUG, 19 | ], 20 | ], 21 | 'formatter' => [ 22 | 'class' => Monolog\Formatter\LineFormatter::class, 23 | 'constructor' => [ 24 | 'format' => null, 25 | 'dateFormat' => null, 26 | 'allowInlineLineBreaks' => true, 27 | ], 28 | ], 29 | 'processors' => [ 30 | ], 31 | ], 32 | ]; 33 | -------------------------------------------------------------------------------- /config/autoload/middlewares.php: -------------------------------------------------------------------------------- 1 | [ 14 | ], 15 | ]; 16 | -------------------------------------------------------------------------------- /config/autoload/processes.php: -------------------------------------------------------------------------------- 1 | [ 14 | 'host' => env('REDIS_HOST', 'localhost'), 15 | 'auth' => env('REDIS_AUTH', null), 16 | 'port' => (int) env('REDIS_PORT', 6379), 17 | 'db' => (int) env('REDIS_DB', 0), 18 | 'pool' => [ 19 | 'min_connections' => 1, 20 | 'max_connections' => 10, 21 | 'connect_timeout' => 10.0, 22 | 'wait_timeout' => 3.0, 23 | 'heartbeat' => -1, 24 | 'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60), 25 | ], 26 | ], 27 | ]; 28 | -------------------------------------------------------------------------------- /config/autoload/server.php: -------------------------------------------------------------------------------- 1 | SWOOLE_BASE, 17 | 'servers' => [ 18 | [ 19 | 'name' => 'http', 20 | 'type' => Server::SERVER_HTTP, 21 | 'host' => '0.0.0.0', 22 | 'port' => 9501, 23 | 'sock_type' => SWOOLE_SOCK_TCP, 24 | 'callbacks' => [ 25 | SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'], 26 | ], 27 | ], 28 | ], 29 | 'settings' => [ 30 | 'enable_coroutine' => true, 31 | 'worker_num' => 4, 32 | 'pid_file' => BASE_PATH . '/runtime/hyperf.pid', 33 | 'open_tcp_nodelay' => true, 34 | 'max_coroutine' => 100000, 35 | 'open_http2_protocol' => true, 36 | 'max_request' => 0, 37 | 'socket_buffer_size' => 2 * 1024 * 1024, 38 | ], 39 | 'callbacks' => [ 40 | SwooleEvent::ON_BEFORE_START => [Hyperf\Framework\Bootstrap\ServerStartCallback::class, 'beforeStart'], 41 | SwooleEvent::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'], 42 | SwooleEvent::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'], 43 | SwooleEvent::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'], 44 | ], 45 | ]; 46 | -------------------------------------------------------------------------------- /config/config.php: -------------------------------------------------------------------------------- 1 | env('APP_NAME', 'skeleton'), 17 | StdoutLoggerInterface::class => [ 18 | 'log_level' => [ 19 | LogLevel::ALERT, 20 | LogLevel::CRITICAL, 21 | LogLevel::DEBUG, 22 | LogLevel::EMERGENCY, 23 | LogLevel::ERROR, 24 | LogLevel::INFO, 25 | LogLevel::NOTICE, 26 | LogLevel::WARNING, 27 | ], 28 | ], 29 | ]; 30 | -------------------------------------------------------------------------------- /config/container.php: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./test 14 | 15 | 16 | 17 | 18 | ./app 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/Cases/ExampleTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 25 | 26 | $res = $this->get('/'); 27 | 28 | $this->assertSame(0, $res['code']); 29 | $this->assertSame('Hello Hyperf.', $res['data']['message']); 30 | $this->assertSame('GET', $res['data']['method']); 31 | $this->assertSame('Hyperf', $res['data']['user']); 32 | 33 | $res = $this->get('/', ['user' => 'limx']); 34 | 35 | $this->assertSame(0, $res['code']); 36 | $this->assertSame('limx', $res['data']['user']); 37 | 38 | $res = $this->post('/', [ 39 | 'user' => 'limx', 40 | ]); 41 | $this->assertSame('Hello Hyperf.', $res['data']['message']); 42 | $this->assertSame('POST', $res['data']['method']); 43 | $this->assertSame('limx', $res['data']['user']); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/HttpTestCase.php: -------------------------------------------------------------------------------- 1 | client = make(Testing\Client::class); 35 | // $this->client = make(Testing\HttpClient::class, ['baseUri' => 'http://127.0.0.1:9501']); 36 | } 37 | 38 | public function __call($name, $arguments) 39 | { 40 | return $this->client->{$name}(...$arguments); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/bootstrap.php: -------------------------------------------------------------------------------- 1 | get(Hyperf\Contract\ApplicationInterface::class); 25 | --------------------------------------------------------------------------------