2
.github/FUNDING.yml
vendored
@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: #
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: https://doc.hyperf.io/#/zh/donate
|
||||
custom: https://hyperf.wiki/2.0/#/zh-cn/donate
|
||||
|
28
.travis.yml
@ -5,17 +5,11 @@ sudo: required
|
||||
matrix:
|
||||
include:
|
||||
- php: 7.2
|
||||
env: SW_VERSION="4.5.1"
|
||||
env: SW_VERSION="4.5.2"
|
||||
- php: 7.3
|
||||
env: SW_VERSION="4.5.1"
|
||||
env: SW_VERSION="4.5.2"
|
||||
- php: 7.4
|
||||
env: SW_VERSION="4.5.1"
|
||||
- php: 7.2
|
||||
env: SW_VERSION="4.4.18"
|
||||
- php: 7.3
|
||||
env: SW_VERSION="4.4.18"
|
||||
- php: 7.4
|
||||
env: SW_VERSION="4.4.18"
|
||||
env: SW_VERSION="4.5.2"
|
||||
|
||||
services:
|
||||
- mysql
|
||||
@ -41,20 +35,6 @@ before_script:
|
||||
- composer config -g process-timeout 900 && composer update
|
||||
|
||||
script:
|
||||
- |
|
||||
composer analyse \
|
||||
src/di \
|
||||
src/json-rpc \
|
||||
src/tracer \
|
||||
src/metric \
|
||||
src/redis \
|
||||
src/nats \
|
||||
src/db \
|
||||
src/retry \
|
||||
src/grpc-client \
|
||||
src/nsq \
|
||||
src/filesystem \
|
||||
src/socketio-server \
|
||||
src/load-balancer
|
||||
- composer analyse src
|
||||
- composer test -- --exclude-group NonCoroutine
|
||||
- vendor/bin/phpunit --group NonCoroutine
|
139
CHANGELOG-2.0.md
Normal file
@ -0,0 +1,139 @@
|
||||
# v2.0.2 - TBD
|
||||
|
||||
## Fixed
|
||||
|
||||
[#2037](https://github.com/hyperf/hyperf/pull/2037) Fixed bug that tcp server running in only one coroutine.
|
||||
|
||||
# v2.0.1 - 2020-07-02
|
||||
|
||||
## Added
|
||||
|
||||
- [#1934](https://github.com/hyperf/hyperf/pull/1934) Added command `gen:constant`.
|
||||
- [#1982](https://github.com/hyperf/hyperf/pull/1982) Added watcher component.
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#1952](https://github.com/hyperf/hyperf/pull/1952) Fixed bug that migration will be created although class already exists.
|
||||
- [#1960](https://github.com/hyperf/hyperf/pull/1960) Fixed `Hyperf\HttpServer\ResponseEmitter::isMethodsExists()` method does not works as expected.
|
||||
- [#1961](https://github.com/hyperf/hyperf/pull/1961) Fixed start failed when `config/autoload/aspects.php` does not exists.
|
||||
- [#1964](https://github.com/hyperf/hyperf/pull/1964) Fixed http status code 500 caused by empty body.
|
||||
- [#1965](https://github.com/hyperf/hyperf/pull/1965) Fixed the wrong http code when `initRequestAndResponse` failed.
|
||||
- [#1968](https://github.com/hyperf/hyperf/pull/1968) Fixed aspect does not work as expected after `aspects.php` is edited.
|
||||
- [#1985](https://github.com/hyperf/hyperf/pull/1985) Fixed global_imports do not work when the aliases are not all lowercase letters.
|
||||
- [#1990](https://github.com/hyperf/hyperf/pull/1990) Fixed `@Inject` does not work when the parent class has the same property.
|
||||
- [#2019](https://github.com/hyperf/hyperf/pull/2019) Fixed bug that `gen:model` generate property failed, when used `morphTo` or `where`.
|
||||
- [#2026](https://github.com/hyperf/hyperf/pull/2026) Fixed invalid lazy proxy generation when magic methods are used.
|
||||
|
||||
## Changed
|
||||
|
||||
- [#1986](https://github.com/hyperf/hyperf/pull/1986) Changed exit_code `0` to `SIGTERM` when swoole short name do not set disable.
|
||||
|
||||
## Optimized
|
||||
|
||||
- [#1959](https://github.com/hyperf/hyperf/pull/1959) Make ClassLoader easier to be extended.
|
||||
- [#2002](https://github.com/hyperf/hyperf/pull/2002) Support aop in trait when php version >= `7.3`.
|
||||
|
||||
# v2.0.0 - 2020-06-22
|
||||
|
||||
## Major Changes
|
||||
|
||||
1. Refactor [hyperf/di](https://github.com/hyperf/di) component, in particular, AOP and Annotation Scanner are optimized, in v2.0, the component use a brand new loading mechanism to provided an incredible AOP function.
|
||||
1. The most significant functional differences compared to v1.x is that you can cut into any classes in any ways with Aspect. For example, in v1.x, you can only use AOP in the class instance that created by Hyperf DI container, you cannot cut into the class instance that created by `new` identifier. But now, in v2.0, it is available. But there is still has an exception, the classes that used in bootstrap stage still cannot works.
|
||||
2. In v1.x, the AOP ONLY available for the normal classes, not for Final class that cannot be inherited by a subclass. But now, in v2.0. it is available.
|
||||
3. In v1.x, you cannot use the property value that marked by `@Inject` or `@Value` annotation in the constructor of current class. But now, in v2.0, it is available.
|
||||
4. In v1.x, you can only use `@Inject` and `@Value` annotation in the class instance that created by Hyperf DI container. But now, in v2.0, it is available in any ways, such as the class instance that created by `new` identifier.
|
||||
5. In v1.x, you have to define the full namespace of Annotation class when you use the Annotation. But now, in v2.0, the component provide a global import mechanism, you cloud define an alias for Annotation to use the Annotation directly without using the namespace. For example, you cloud define `@Inject` annotation in any class without define `use Hyperf\Di\Annotation\Inject;`.
|
||||
6. In v1.x, the proxy class that created by the DI container is a subclass of the target class, this mechanism will cause the magic constant will return the value of proxy class but not original class, such as `__CLASS__`. But now, in v2.0, the proxy class will keep the same structure with the original class, will not change the class name or the class structure.
|
||||
7. In v1.x, the proxy class will not re-generate when the proxy file exists even the code of the proxy class changed, this strategy will improve the time-consuming of scan, but at the same time, this will lead to a certain degree of development inconvenience. And now, in v2.0, the file cache of proxy class will generated according to the code content of the proxy class, this changes will reduces the mental burden of development.
|
||||
8. Add `priority` parameter for Aspect, now you could define `priority` in Aspect class by class property or annotation property, to manage the order of the aspects.
|
||||
9. In v1.x, you can only define an Aspect class by `@Aspect` annotation, you cannot define the Aspect class by configuration file. But now, in v2.0, it is available to define the Aspect class by configuration file or ConfigProvider.
|
||||
10. In v1.x, you have to add `Hyperf\Di\Listener\LazyLoaderBootApplicationListener` to enable lazy loading. In 2.0, lazy loading can be used directly. This listener is therefore removed.
|
||||
11. Added `annotations.scan.class_map` configuration, now you could replace any content of class dynamically above the autoload rules.
|
||||
|
||||
## Dependencies Upgrade
|
||||
|
||||
- Upgraded `ext-swoole` to `>=4.5`;
|
||||
- Upgraded `psr/event-dispatcher` to `^1.0`;
|
||||
- Upgraded `monolog/monolog` to `^2.0`;
|
||||
- Upgraded `phpstan/phpstan` to `^0.12.18`;
|
||||
- Upgraded `vlucas/phpdotenv` to `^4.0`;
|
||||
- Upgraded `symfony/finder` to `^5.0`;
|
||||
- Upgraded `symfony/event-dispatcher` to `^5.0`;
|
||||
- Upgraded `symfony/console` to `^5.0`;
|
||||
- Upgraded `symfony/property-access` to `^5.0`;
|
||||
- Upgraded `symfony/serializer` to `^5.0`;
|
||||
- Upgraded `elasticsearch/elasticsearch` to `^7.0`;
|
||||
|
||||
## Removed
|
||||
|
||||
- Removed `Hyperf\Di\Aop\AstCollector`;
|
||||
- Removed `Hyperf\Di\Aop\ProxyClassNameVisitor`;
|
||||
- Removed `Hyperf\Di\Listener\LazyLoaderBootApplicationListener`
|
||||
- Removed method `dispatch(...$params)` from `Hyperf\Dispatcher\AbstractDispatcher`
|
||||
- Removed mapping for `Hyperf\Contract\NormalizerInterface => Hyperf\Utils\Serializer\SymfonyNormalizer` from `ConfigProvider` in utils.
|
||||
- Removed the typehint of `$server` parameter of `Hyperf\Contract\OnOpenInterface`、`Hyperf\Contract\OnCloseInterface`、`Hyperf\Contract\OnMessageInterface`、`Hyperf\Contract\OnReceiveInterface`;
|
||||
|
||||
## Added
|
||||
|
||||
- [#992](https://github.com/hyperf/hyperf/pull/992) Added ReactiveX component.
|
||||
- [#1245](https://github.com/hyperf/hyperf/pull/1245) Added Annotation `ExceptionHandler`.
|
||||
- [#1245](https://github.com/hyperf/hyperf/pull/1245) Exception handler's config and annotation support priority.
|
||||
- [#1819](https://github.com/hyperf/hyperf/pull/1819) Added `hyperf/signal` component.
|
||||
- [#1844](https://github.com/hyperf/hyperf/pull/1844) Support type `\DateInterval` for `ttl` in `model-cache`.
|
||||
- [#1855](https://github.com/hyperf/hyperf/pull/1855) Added `ConstantFrequency` to flush one connection, when it is idle connection for the interval of time.
|
||||
- [#1871](https://github.com/hyperf/hyperf/pull/1871) Added `sink` for guzzle.
|
||||
- [#1805](https://github.com/hyperf/hyperf/pull/1805) Added Coroutine Server.
|
||||
- Changed method `bind(Server $server)` to `bind($server)` in `Hyperf\Contract\ProcessInterface`.
|
||||
- Changed method `isEnable()` to `isEnable($server)` in `Hyperf\Contract\ProcessInterface`
|
||||
- Process mode of config-center, crontab, metric, comsumers of MQ can not running in coroutine server.
|
||||
- Change the life-cycle of `Hyperf\AsyncQueue\Environment`, can only applies in the current coroutine, not the whole current process.
|
||||
- Coroutine Server does not support task mechanism.
|
||||
|
||||
- [#1877](https://github.com/hyperf/hyperf/pull/1877) Support to use typehint of property on PHP 8 to replace `@var` when using `@Inject` annotation, for example:
|
||||
|
||||
```
|
||||
class Example {
|
||||
/**
|
||||
* @Inject
|
||||
*/
|
||||
private ExampleService $exampleService;
|
||||
}
|
||||
```
|
||||
|
||||
- [#1890](https://github.com/hyperf/hyperf/pull/1890) Added `Hyperf\HttpServer\ResponseEmitter` class to emit any PSR-7 response object with Swoole server, and extracted `Hyperf\Contract\ResponseEmitterInterface`.
|
||||
- [#1890](https://github.com/hyperf/hyperf/pull/1890) Added `getTrailers()` and `getTrailer(string $key)` and `withTrailer(string $key, $value)` methods for `Hyperf\HttpMessage\Server\Response`.
|
||||
- [#1920](https://github.com/hyperf/hyperf/pull/1920) Added method `Hyperf\WebSocketServer\Sender::close(int $fd, bool $reset = null)`.
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#1825](https://github.com/hyperf/hyperf/pull/1825) Fixed `TypeError` for `StartServer::execute`.
|
||||
- [#1854](https://github.com/hyperf/hyperf/pull/1854) Fixed `is_resource` does not works when use `Runtime::enableCoroutine()` privately in filesystem.
|
||||
- [#1900](https://github.com/hyperf/hyperf/pull/1900) Fixed caster decimal of Model does not work.
|
||||
- [#1917](https://github.com/hyperf/hyperf/pull/1917) Fixed `Request::isXmlHttpRequest` does not work.
|
||||
|
||||
## Changed
|
||||
|
||||
- [#705](https://github.com/hyperf/hyperf/pull/705) Uniformed the handling of HTTP exceptions, now unified throwing a `Hyperf\HttpMessage\Exception\HttpException` exception class to replace the way of direct response in `Dispatcher`, also provided an `Hyperf\HttpServer\Exception\Handler\ httptionHandler` ExceptionHandler to handle these HTTP Exception;
|
||||
- [#1846](https://github.com/hyperf/hyperf/pull/1846) Don't auto change the impl for `Hyperf\Contract\NormalizerInterface` when you require `symfony/serialize`. You can added dependiencies below to use symfony serializer.
|
||||
```php
|
||||
use Hyperf\Utils\Serializer\SerializerFactory;
|
||||
use Hyperf\Utils\Serializer\Serializer;
|
||||
|
||||
return [
|
||||
Hyperf\Contract\NormalizerInterface::class => new SerializerFactory(Serializer::class),
|
||||
];
|
||||
```
|
||||
|
||||
- [#1924](https://github.com/hyperf/hyperf/pull/1924) Changed `Hyperf\GrpcClient\BaseClient` methods `simpleRequest, getGrpcClient, clientStreamRequest` to `_simpleRequest, _getGrpcClient, _clientStreamRequest`.
|
||||
|
||||
## Removed
|
||||
|
||||
- [#1890](https://github.com/hyperf/hyperf/pull/1890) Removed `Hyperf\Contract\Sendable` interface and all implementations of it.
|
||||
- [#1905](https://github.com/hyperf/hyperf/pull/1905) Removed config `config/server.php`, you can merge it into `config/config.php`.
|
||||
|
||||
## Optimized
|
||||
|
||||
- [#1793](https://github.com/hyperf/hyperf/pull/1793) Socket.io server now only dispatch connect/disconnect events in onOpen and onClose. Also upgrade some class members from private to protected, so users can hack them.
|
||||
- [#1848](https://github.com/hyperf/hyperf/pull/1848) Auto generate rpc client code when server start and the interface is changed.
|
||||
- [#1863](https://github.com/hyperf/hyperf/pull/1863) Support async-queue stop safely.
|
||||
- [#1896](https://github.com/hyperf/hyperf/pull/1896) Keys will be merged when different constants use the same code.
|
@ -1,5 +1,9 @@
|
||||
# v1.1.33 - TBD
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#1917](https://github.com/hyperf/hyperf/pull/1917) Fixed bug that `Request::isXmlHttpRequest` does not work.
|
||||
|
||||
## Optimized
|
||||
|
||||
- [#1793](https://github.com/hyperf/hyperf/pull/1793) Socket.io server now only dispatch connect/disconnect events in onOpen and onClose. Also upgrade some class members from private to protected, so users can hack them.
|
||||
|
15
README-CN.md
@ -3,16 +3,18 @@
|
||||
<p align="center"><a href="https://hyperf.io" target="_blank" rel="noopener noreferrer"><img width="70" src="https://www.hyperf.wiki/logo.png" alt="Hyperf Logo"></a></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/hyperf/hyperf/releases"><img src="https://poser.pugx.org/hyperf/hyperf/v/stable" alt="Stable Version"></a>
|
||||
<a href="https://travis-ci.org/hyperf/hyperf"><img src="https://travis-ci.org/hyperf/hyperf.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://opencollective.com/hyperf"><img src="https://opencollective.com/hyperf/all/badge.svg?label=financial+contributors" alt="Financial Contributors on Open Collective"></a>
|
||||
<a href="https://secure.php.net/"><img src="https://img.shields.io/badge/php-%3E=7.2-brightgreen.svg?maxAge=2592000" alt="Php Version"></a>
|
||||
<a href="https://github.com/swoole/swoole-src"><img src="https://img.shields.io/badge/swoole-%3E=4.4-brightgreen.svg?maxAge=2592000" alt="Swoole Version"></a>
|
||||
<a href="https://packagist.org/packages/hyperf/framework"><img src="https://poser.pugx.org/hyperf/framework/downloads" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/hyperf/framework"><img src="https://poser.pugx.org/hyperf/framework/d/monthly" alt="Monthly Downloads"></a>
|
||||
<a href="https://www.php.net"><img src="https://img.shields.io/badge/php-%3E=7.2-brightgreen.svg?maxAge=2592000" alt="Php Version"></a>
|
||||
<a href="https://github.com/swoole/swoole-src"><img src="https://img.shields.io/badge/swoole-%3E=4.5-brightgreen.svg?maxAge=2592000" alt="Swoole Version"></a>
|
||||
<a href="https://github.com/hyperf/hyperf/blob/master/LICENSE"><img src="https://img.shields.io/github/license/hyperf/hyperf.svg?maxAge=2592000" alt="Hyperf License"></a>
|
||||
</p>
|
||||
|
||||
# 介绍
|
||||
|
||||
Hyperf 是基于 `Swoole 4.4+` 实现的高性能、高灵活性的 PHP 协程框架,内置协程服务器及大量常用的组件,性能较传统基于 `PHP-FPM` 的框架有质的提升,提供超高性能的同时,也保持着极其灵活的可扩展性,标准组件均基于 [PSR 标准](https://www.php-fig.org/psr) 实现,基于强大的依赖注入设计,保证了绝大部分组件或类都是 `可替换` 与 `可复用` 的。
|
||||
Hyperf 是基于 `Swoole 4.5+` 实现的高性能、高灵活性的 PHP 协程框架,内置协程服务器及大量常用的组件,性能较传统基于 `PHP-FPM` 的框架有质的提升,提供超高性能的同时,也保持着极其灵活的可扩展性,标准组件均基于 [PSR 标准](https://www.php-fig.org/psr) 实现,基于强大的依赖注入设计,保证了绝大部分组件或类都是 `可替换` 与 `可复用` 的。
|
||||
|
||||
框架组件库除了常见的协程版的 `MySQL 客户端`、`Redis 客户端`,还为您准备了协程版的 `Eloquent ORM`、`WebSocket 服务端及客户端`、`JSON RPC 服务端及客户端`、`GRPC 服务端及客户端`、`Zipkin/Jaeger (OpenTracing) 客户端`、`Guzzle HTTP 客户端`、`Elasticsearch 客户端`、`Consul 客户端`、`ETCD 客户端`、`AMQP 组件`、`NSQ 组件`、`Nats 组件`、`Apollo 配置中心`、`阿里云 ACM 应用配置管理`、`ETCD 配置中心`、`基于令牌桶算法的限流器`、`通用连接池`、`熔断器`、`Swagger 文档生成`、`Swoole Tracker`、`视图引擎`、`Snowflake 全局 ID 生成器` 等组件,省去了自己实现对应协程版本的麻烦。
|
||||
|
||||
@ -72,11 +74,6 @@ Hyperf 还提供了 `基于 PSR-11 的依赖注入容器`、`注解`、`AOP 面
|
||||
<img height="110px" src="https://hyperf.wiki/zh-cn/imgs/guojiang-club.jpg">
|
||||
</a>
|
||||
</td>
|
||||
<td align="left" valign="middle">
|
||||
<a href="https://1shanghu.com?from=hyperf" target="_blank">
|
||||
<img height="80px" src="https://hyperf.wiki/zh-cn/imgs/1shanghu.jpg">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
15
README.md
@ -3,16 +3,18 @@ English | [中文](./README-CN.md)
|
||||
<p align="center"><a href="https://hyperf.io" target="_blank" rel="noopener noreferrer"><img width="70" src="https://www.hyperf.wiki/logo.png" alt="Hyperf Logo"></a></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/hyperf/hyperf/releases"><img src="https://poser.pugx.org/hyperf/hyperf/v/stable" alt="Stable Version"></a>
|
||||
<a href="https://travis-ci.org/hyperf/hyperf"><img src="https://travis-ci.org/hyperf/hyperf.svg?branch=master" alt="Build Status"></a>
|
||||
<a href="https://opencollective.com/hyperf"><img src="https://opencollective.com/hyperf/all/badge.svg?label=financial+contributors" alt="Financial Contributors on Open Collective"></a>
|
||||
<a href="https://secure.php.net/"><img src="https://img.shields.io/badge/php-%3E=7.2-brightgreen.svg?maxAge=2592000" alt="Php Version"></a>
|
||||
<a href="https://github.com/swoole/swoole-src"><img src="https://img.shields.io/badge/swoole-%3E=4.4-brightgreen.svg?maxAge=2592000" alt="Swoole Version"></a>
|
||||
<a href="https://packagist.org/packages/hyperf/framework"><img src="https://poser.pugx.org/hyperf/framework/downloads" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/hyperf/framework"><img src="https://poser.pugx.org/hyperf/framework/d/monthly" alt="Monthly Downloads"></a>
|
||||
<a href="https://www.php.net"><img src="https://img.shields.io/badge/php-%3E=7.2-brightgreen.svg?maxAge=2592000" alt="Php Version"></a>
|
||||
<a href="https://github.com/swoole/swoole-src"><img src="https://img.shields.io/badge/swoole-%3E=4.5-brightgreen.svg?maxAge=2592000" alt="Swoole Version"></a>
|
||||
<a href="https://github.com/hyperf/hyperf/blob/master/LICENSE"><img src="https://img.shields.io/github/license/hyperf/hyperf.svg?maxAge=2592000" alt="Hyperf License"></a>
|
||||
</p>
|
||||
|
||||
# Introductions
|
||||
|
||||
Hyperf is an extremely performant and flexible PHP CLI framework based on `Swoole 4.4+`, powered by the state-of-the-art coroutine server and a large number of battle-tested components. Aside from the decisive benchmark outmatching against PHP-FPM frameworks, Hyperf also distinct itself by its focus on flexibility and composability. Hyperf ships with an AOP-enabling dependency injector to ensure components and classes are pluggable and meta programmable. All of its core components strictly follow the PSR standards and thus can be used in other frameworks.
|
||||
Hyperf is an extremely performant and flexible PHP CLI framework based on `Swoole 4.5+`, powered by the state-of-the-art coroutine server and a large number of battle-tested components. Aside from the decisive benchmark outmatching against PHP-FPM frameworks, Hyperf also distinct itself by its focus on flexibility and composability. Hyperf ships with an AOP-enabling dependency injector to ensure components and classes are pluggable and meta programmable. All of its core components strictly follow the PSR standards and thus can be used in other frameworks.
|
||||
|
||||
Hyperf's architecture is built upon the combination of `Coroutine`, `Dependency injection`, `Events`, `Annotation`, `AOP (aspect-oriented programming)`. Core components provided by Hyperf can be used out of the box in coroutine context. The set includes but not limited to: `MySQL coroutine client`, `Redis coroutine client`, `WebSocket server and client`, `JSON RPC server and client`, `gRPC server and client`, `Zipkin/Jaeger (OpenTracing) client`, `Guzzle HTTP client`, `Elasticsearch client`, `Consul client`, `ETCD client`, `AMQP component`, `Apollo configuration center`, `Aliyun ACM`, `ETCD configuration center`, `Token bucket algorithm-based limiter`, `Universal connection pool`, `Circuit breaker`, `Swagger`, `Swoole Tracker`, `Snowflake`, `Simply Redis MQ`, `RabbitMQ`, `NSQ`, `Nats`, `Seconds level crontab`, `Custom Processes`, etc. Be assured Hyperf is still a PHP framework. You will also find familiar packages such as `Middleware`, `Event Manager`, `Coroutine optimized Eloquent ORM` (And Model Cache!), `Translation`, `Validation`, `View engine (Blade/Smarty/Twig/Plates/ThinkTemplate)` and more at your command.
|
||||
|
||||
@ -60,11 +62,6 @@ Support this project with your organization or company. Your logo will show up h
|
||||
<img height="110px" src="https://hyperf.wiki/zh-cn/imgs/guojiang-club.jpg">
|
||||
</a>
|
||||
</td>
|
||||
<td align="left" valign="middle">
|
||||
<a href="https://1shanghu.com?from=hyperf" target="_blank">
|
||||
<img height="80px" src="https://hyperf.wiki/zh-cn/imgs/1shanghu.jpg">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -2,7 +2,10 @@
|
||||
<?php
|
||||
|
||||
$code = 0;
|
||||
\Swoole\Coroutine\Run(function () use (&$code) {
|
||||
Swoole\Coroutine::set(['exit_condition' => function(){
|
||||
return Swoole\Coroutine::stats()['coroutine_num'] === 0;
|
||||
}]);
|
||||
Swoole\Coroutine\Run(function () use (&$code) {
|
||||
if (version_compare('7.1.0', PHP_VERSION, '>')) {
|
||||
fwrite(
|
||||
STDERR,
|
||||
@ -55,6 +58,4 @@ $code = 0;
|
||||
$code = PHPUnit\TextUI\Command::main(false);
|
||||
});
|
||||
|
||||
swoole_event_wait();
|
||||
|
||||
exit($code);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* @notice Please DO NOT run this script manually, when you trying to submit a Pull Request of Documentation.
|
||||
* @notice Install https://github.com/nauxliu/opencc4php extension before use this script.
|
||||
* Run this PHP script to generate the zh-tw and zh-hk doucmentations via zh-cn.
|
||||
*/
|
||||
@ -12,22 +14,23 @@ use Symfony\Component\Finder\Finder;
|
||||
|
||||
$config = [
|
||||
'zh-tw' => [
|
||||
'targetDir' => BASE_PATH . '/doc/zh-tw/',
|
||||
'targetDir' => BASE_PATH . '/docs/zh-tw/',
|
||||
'rule' => 's2twp.json',
|
||||
],
|
||||
'zh-hk' => [
|
||||
'targetDir' => BASE_PATH . '/doc/zh-hk/',
|
||||
'targetDir' => BASE_PATH . '/docs/zh-hk/',
|
||||
'rule' => 's2hk.json',
|
||||
],
|
||||
];
|
||||
|
||||
$finder = new Finder();
|
||||
$finder->files()->in(BASE_PATH . '/doc/zh-cn');
|
||||
$finder->files()->in(BASE_PATH . '/docs/zh-cn');
|
||||
|
||||
foreach ($config as $key => $item) {
|
||||
$od = opencc_open($item['rule']);
|
||||
foreach ($finder as $fileInfo) {
|
||||
$targetPath = $item['targetDir'] . $fileInfo->getRelativePath();
|
||||
$targetDir = $item['targetDir'];
|
||||
$targetPath = $targetDir . $fileInfo->getRelativePath();
|
||||
$isCreateDir = false;
|
||||
if (! is_dir($targetPath)) {
|
||||
mkdir($targetPath, 0777, true);
|
||||
@ -40,10 +43,11 @@ foreach ($config as $key => $item) {
|
||||
if ($fileInfo->getExtension() === 'md') {
|
||||
$translated = opencc_convert($fileInfo->getContents(), $od);
|
||||
$translated = str_replace('](zh-cn/', '](' . $key . '/', $translated);
|
||||
$targetTranslatedPath = $item['targetDir'] . $fileInfo->getRelativePathname();
|
||||
$translated = str_replace('](./zh-cn/', '](./' . $key . '/', $translated);
|
||||
$targetTranslatedPath = $targetDir . $fileInfo->getRelativePathname();
|
||||
@file_put_contents($targetTranslatedPath, $translated);
|
||||
} else {
|
||||
$targetTranslatedPath = $item['targetDir'] . $fileInfo->getRelativePathname();
|
||||
$targetTranslatedPath = $targetDir . $fileInfo->getRelativePathname();
|
||||
@copy($fileInfo->getRealPath(), $targetTranslatedPath);
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ foreach ([__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php',
|
||||
}
|
||||
|
||||
$files = Finder::create()
|
||||
->in(__DIR__ . '/../doc/zh-cn')
|
||||
->in(__DIR__ . '/../docs/zh-cn')
|
||||
->name('*.md')
|
||||
->files();
|
||||
|
||||
|
@ -9,7 +9,22 @@ declare(strict_types=1);
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
use Hyperf\Config\Listener\RegisterPropertyHandlerListener;
|
||||
use Hyperf\Di\Aop\AstVisitorRegistry;
|
||||
use Hyperf\Di\Aop\PropertyHandlerVisitor;
|
||||
use Hyperf\Di\Aop\ProxyCallVisitor;
|
||||
use Hyperf\Di\Aop\RegisterInjectPropertyHandler;
|
||||
|
||||
! defined('BASE_PATH') && define('BASE_PATH', __DIR__);
|
||||
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
|
||||
|
||||
require_once BASE_PATH . '/vendor/autoload.php';
|
||||
|
||||
// Register AST visitors to the collector.
|
||||
AstVisitorRegistry::insert(PropertyHandlerVisitor::class, PHP_INT_MAX / 2);
|
||||
AstVisitorRegistry::insert(ProxyCallVisitor::class, PHP_INT_MAX / 2);
|
||||
|
||||
// Register Property Handler.
|
||||
RegisterInjectPropertyHandler::register();
|
||||
|
||||
(new RegisterPropertyHandlerListener())->process(new \stdClass());
|
||||
|
@ -20,10 +20,10 @@
|
||||
"ext-bcmath": "*",
|
||||
"ext-json": "*",
|
||||
"ext-redis": "*",
|
||||
"ext-swoole": ">=4.4",
|
||||
"ext-swoole": ">=4.5",
|
||||
"psr/container": "^1.0",
|
||||
"psr/event-dispatcher": "^0.7",
|
||||
"psr/http-message": "^1.0.1",
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/http-server-middleware": "^1.0",
|
||||
"psr/log": "^1.0",
|
||||
"psr/simple-cache": "^1.0"
|
||||
@ -58,7 +58,7 @@
|
||||
"markrogoyski/math-php": "^0.49.0",
|
||||
"mix/redis-subscribe": "^2.1",
|
||||
"mockery/mockery": "^1.0",
|
||||
"monolog/monolog": "^1.24",
|
||||
"monolog/monolog": "^2.0",
|
||||
"nesbot/carbon": "^2.0",
|
||||
"nikic/fast-route": "^1.3",
|
||||
"nikic/php-parser": "^4.1",
|
||||
@ -66,22 +66,24 @@
|
||||
"php-amqplib/php-amqplib": "^2.7",
|
||||
"php-di/php-di": "^6.0",
|
||||
"php-di/phpdoc-reader": "^2.0.1",
|
||||
"phpstan/phpstan": "^0.11.15",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpunit/phpunit": "^7.0.0",
|
||||
"predis/predis": "^1.1",
|
||||
"roave/better-reflection": "^4.0",
|
||||
"smarty/smarty": "^3.1",
|
||||
"squizlabs/php_codesniffer": "^3.4",
|
||||
"start-point/etcd-php": "^1.1",
|
||||
"swoole/ide-helper": "dev-master",
|
||||
"sy-records/think-template": "^2.0",
|
||||
"symfony/console": "^4.2",
|
||||
"symfony/event-dispatcher": "^4.3",
|
||||
"symfony/finder": "^4.1",
|
||||
"symfony/property-access": "^4.3",
|
||||
"symfony/serializer": "^4.3",
|
||||
"symfony/console": "^5.0",
|
||||
"symfony/event-dispatcher": "^5.0",
|
||||
"symfony/finder": "^5.0",
|
||||
"symfony/property-access": "^5.0",
|
||||
"symfony/serializer": "^5.0",
|
||||
"twig/twig": "^2.12",
|
||||
"vlucas/phpdotenv": "^3.1",
|
||||
"xxtime/flysystem-aliyun-oss": "^1.5"
|
||||
"vlucas/phpdotenv": "^4.0",
|
||||
"xxtime/flysystem-aliyun-oss": "^1.5",
|
||||
"reactivex/rxphp": "^2.0"
|
||||
},
|
||||
"replace": {
|
||||
"hyperf/amqp": "self.version",
|
||||
@ -121,6 +123,7 @@
|
||||
"hyperf/pool": "self.version",
|
||||
"hyperf/process": "self.version",
|
||||
"hyperf/rate-limit": "self.version",
|
||||
"hyperf/reactive-x": "self.version",
|
||||
"hyperf/redis": "self.version",
|
||||
"hyperf/retry": "self.version",
|
||||
"hyperf/server": "self.version",
|
||||
@ -198,6 +201,7 @@
|
||||
"Hyperf\\Process\\": "src/process/src/",
|
||||
"Hyperf\\Protocol\\": "src/protocol/src/",
|
||||
"Hyperf\\RateLimit\\": "src/rate-limit/src/",
|
||||
"Hyperf\\ReactiveX\\": "src/reactive-x/src/",
|
||||
"Hyperf\\Redis\\": "src/redis/src/",
|
||||
"Hyperf\\Retry\\": "src/retry/src/",
|
||||
"Hyperf\\RpcClient\\": "src/rpc-client/src/",
|
||||
@ -206,6 +210,7 @@
|
||||
"Hyperf\\Server\\": "src/server/src/",
|
||||
"Hyperf\\ServiceGovernance\\": "src/service-governance/src/",
|
||||
"Hyperf\\Session\\": "src/session/src/",
|
||||
"Hyperf\\Signal\\": "src/signal/src/",
|
||||
"Hyperf\\Snowflake\\": "src/snowflake/src/",
|
||||
"Hyperf\\SocketIOServer\\": "src/socketio-server/src/",
|
||||
"Hyperf\\Socket\\": "src/socket/src/",
|
||||
@ -219,6 +224,7 @@
|
||||
"Hyperf\\Utils\\": "src/utils/src/",
|
||||
"Hyperf\\Validation\\": "src/validation/src/",
|
||||
"Hyperf\\View\\": "src/view/src/",
|
||||
"Hyperf\\Watcher\\": "src/watcher/src/",
|
||||
"Hyperf\\WebSocketClient\\": "src/websocket-client/src/",
|
||||
"Hyperf\\WebSocketServer\\": "src/websocket-server/src/"
|
||||
}
|
||||
@ -269,12 +275,14 @@
|
||||
"HyperfTest\\Process\\": "src/process/tests/",
|
||||
"HyperfTest\\Protocol\\": "src/protocol/tests/",
|
||||
"HyperfTest\\RateLimit\\": "src/rate-limit/tests/",
|
||||
"HyperfTest\\ReactiveX\\": "src/reactive-x/tests/",
|
||||
"HyperfTest\\Redis\\": "src/redis/tests/",
|
||||
"HyperfTest\\Retry\\": "src/retry/tests/",
|
||||
"HyperfTest\\Rpc\\": "src/rpc/tests/",
|
||||
"HyperfTest\\Server\\": "src/server/tests/",
|
||||
"HyperfTest\\ServiceGovernance\\": "src/service-governance/tests/",
|
||||
"HyperfTest\\Session\\": "src/session/tests/",
|
||||
"HyperfTest\\Signal\\": "src/signal/tests/",
|
||||
"HyperfTest\\Snowflake\\": "src/snowflake/tests/",
|
||||
"HyperfTest\\SocketIOServer\\": "src/socketio-server/tests/",
|
||||
"HyperfTest\\Socket\\": "src/socket/tests/",
|
||||
@ -285,6 +293,7 @@
|
||||
"HyperfTest\\Utils\\": "src/utils/tests/",
|
||||
"HyperfTest\\Validation\\": "src/validation/tests/",
|
||||
"HyperfTest\\View\\": "src/view/tests/",
|
||||
"HyperfTest\\Watcher\\": "src/watcher/tests/",
|
||||
"HyperfTest\\WebSocketClient\\": "src/websocket-client/tests/"
|
||||
}
|
||||
},
|
||||
@ -320,6 +329,8 @@
|
||||
"Hyperf\\GraphQL\\ConfigProvider",
|
||||
"Hyperf\\GrpcClient\\ConfigProvider",
|
||||
"Hyperf\\GrpcServer\\ConfigProvider",
|
||||
"Hyperf\\Guzzle\\ConfigProvider",
|
||||
"Hyperf\\HttpMessage\\ConfigProvider",
|
||||
"Hyperf\\HttpServer\\ConfigProvider",
|
||||
"Hyperf\\JsonRpc\\ConfigProvider",
|
||||
"Hyperf\\LoadBalancer\\ConfigProvider",
|
||||
@ -335,6 +346,7 @@
|
||||
"Hyperf\\Process\\ConfigProvider",
|
||||
"Hyperf\\Protocol\\ConfigProvider",
|
||||
"Hyperf\\RateLimit\\ConfigProvider",
|
||||
"Hyperf\\ReactiveX\\ConfigProvider",
|
||||
"Hyperf\\Redis\\ConfigProvider",
|
||||
"Hyperf\\Retry\\ConfigProvider",
|
||||
"Hyperf\\RpcClient\\ConfigProvider",
|
||||
@ -342,6 +354,7 @@
|
||||
"Hyperf\\Server\\ConfigProvider",
|
||||
"Hyperf\\ServiceGovernance\\ConfigProvider",
|
||||
"Hyperf\\Session\\ConfigProvider",
|
||||
"Hyperf\\Signal\\ConfigProvider",
|
||||
"Hyperf\\Snowflake\\ConfigProvider",
|
||||
"Hyperf\\SocketIOServer\\ConfigProvider",
|
||||
"Hyperf\\Socket\\ConfigProvider",
|
||||
@ -354,6 +367,7 @@
|
||||
"Hyperf\\Utils\\ConfigProvider",
|
||||
"Hyperf\\Validation\\ConfigProvider",
|
||||
"Hyperf\\View\\ConfigProvider",
|
||||
"Hyperf\\Watcher\\ConfigProvider",
|
||||
"Hyperf\\WebSocketClient\\ConfigProvider",
|
||||
"Hyperf\\WebSocketServer\\ConfigProvider"
|
||||
]
|
||||
@ -366,7 +380,7 @@
|
||||
"license-check": "docheader check src/ test/",
|
||||
"cs-fix": "php-cs-fixer fix $1",
|
||||
"json-fix": "./bin/composer-json-fixer",
|
||||
"analyse": "phpstan analyse --memory-limit 300M -l 3 -c phpstan.neon"
|
||||
"analyse": "phpstan analyse --memory-limit 4096M -l 5 -c phpstan.neon"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Introduction
|
||||
|
||||
Hyperf is a high-performance, highly flexible PHP CLI framework based on `Swoole 4.4+`. It has a built-in coroutine server with a large number of commonly used components. It provides ultra-high and better performance than the traditional PHP-FPM-based framework and also maintains extremely flexible scalability at the same time. Standard components are implemented in the latest PSR standards, and a powerful dependency injection design ensures that most components or classes within the framework are replaceable.
|
||||
Hyperf is a high-performance, highly flexible PHP CLI framework based on `Swoole 4.5+`. It has a built-in coroutine server with a large number of commonly used components. It provides ultra-high and better performance than the traditional PHP-FPM-based framework and also maintains extremely flexible scalability at the same time. Standard components are implemented in the latest PSR standards, and a powerful dependency injection design ensures that most components or classes within the framework are replaceable.
|
||||
|
||||
In addition to providing `MySQL coroutine client` and `Redis coroutine client`, common coroutine clients, the Hyperf component libraries are also prepared for the coroutine version of `Eloquent ORM`, `GRPC server and client`, `Zipkin (OpenTracing) client`, `Guzzle HTTP client`, `Elasticsearch client`, `Consul client`, `ETCD client`, `AMQP component`, `Apollo configuration center`, `Token bucket algorithm-based limiter`, and `Universal connection pool`, etc. Therefore, the trouble of implementing the corresponding coroutine version client by yourself can be avoided. Hyperf also provides convenient functions such as `Dependency injection`, `Annotation`, `AOP (aspect-oriented programming)`, `Middleware`, `Custom Processes`, `Event Manager`, `Simply Redis message queue`, and `Full-featured RabbitMQ message queue` to meet a wide range of technical and business scenarios.
|
||||
|
@ -10,4 +10,4 @@ Group Number: `862099724`
|
||||
|
||||
Since the WeChat group can't be added directly, so you can scan the QR code below and add as a WeChat friend, please declare the purpose when you sending the friend request, then I will pull you into the group.
|
||||
|
||||
![wechat](./imgs/wechat.jpg ':size=375')
|
||||
![wechat](imgs/wechat.jpg ':size=375')
|
@ -1,6 +1,6 @@
|
||||
# 指南前言
|
||||
|
||||
为了帮助开发者更好的为 Hyperf 开发组件,共建生态,我们提供了本指南用于指导开发者进行组件开发,在阅读本指南前,需要您对 Hyperf 的文档进行了 **全面** 的阅读,特别是 [协程](zh/coroutine.md) 和 [依赖注入](zh/di.md) 章节,如果对 Hyperf 的基础组件缺少充分的理解,可能会导致开发时出现错误。
|
||||
为了帮助开发者更好的为 Hyperf 开发组件,共建生态,我们提供了本指南用于指导开发者进行组件开发,在阅读本指南前,需要您对 Hyperf 的文档进行了 **全面** 的阅读,特别是 [协程](en/coroutine.md) 和 [依赖注入](en/di.md) 章节,如果对 Hyperf 的基础组件缺少充分的理解,可能会导致开发时出现错误。
|
||||
|
||||
# 组件开发的目的
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Controller
|
||||
|
||||
通过控制器来处理 HTTP 请求,需要通过 `配置文件` 或 `注解` 的形式将路由与控制器方法进行绑定,具体请查阅 [路由](zh/route.md) 章节。
|
||||
对于 `请求(Request)` 与 `响应(Response)`,Hyperf 提供了 `Hyperf\HttpServer\Contract\RequestInterface` 和 `Hyperf\HttpServer\Contract\ResponseInterface` 方便您获取入参和返回数据,关于 [请求](zh/request.md) 与 [响应](zh/response.md) 的详细内容请查阅对应的章节。
|
||||
通过控制器来处理 HTTP 请求,需要通过 `配置文件` 或 `注解` 的形式将路由与控制器方法进行绑定,具体请查阅 [路由](en/route.md) 章节。
|
||||
对于 `请求(Request)` 与 `响应(Response)`,Hyperf 提供了 `Hyperf\HttpServer\Contract\RequestInterface` 和 `Hyperf\HttpServer\Contract\ResponseInterface` 方便您获取入参和返回数据,关于 [请求](en/request.md) 与 [响应](en/response.md) 的详细内容请查阅对应的章节。
|
||||
|
||||
## Create a Controller
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
# 使用方法
|
||||
|
||||
在您通过 [查询构造器](zh/db/querybuilder.md) 或 [模型](zh/db/model.md) 查询数据时,可以通过 `paginate` 方法来处理分页,该方法会自动根据用户正在查看的页面来设置限制和偏移量,默认情况下,通过当前 HTTP 请求所带的 `page` 参数的值来检测当前的页数:
|
||||
在您通过 [查询构造器](en/db/querybuilder.md) 或 [模型](en/db/model.md) 查询数据时,可以通过 `paginate` 方法来处理分页,该方法会自动根据用户正在查看的页面来设置限制和偏移量,默认情况下,通过当前 HTTP 请求所带的 `page` 参数的值来检测当前的页数:
|
||||
|
||||
> 由于 Hyperf 当前并不支持视图,所以分页组件尚未支持对视图的渲染,直接返回分页结果默认会以 application/json 格式输出。
|
||||
|
||||
@ -36,4 +36,4 @@ return User::where('gender', 1)->paginate(10);
|
||||
|
||||
## 分页器实例方法
|
||||
|
||||
这里仅说明分页器在数据库查询上的使用方法,更多关于分页器的细节可阅读 [分页](zh/paginator.md) 章节。
|
||||
这里仅说明分页器在数据库查询上的使用方法,更多关于分页器的细节可阅读 [分页](en/paginator.md) 章节。
|
@ -3,7 +3,7 @@
|
||||
## 简介
|
||||
|
||||
Hyperf 默认采用 [hyperf/di](https://github.com/hyperf-cloud/di) 作为框架的依赖注入管理容器,尽管从设计上我们允许您更换其它的依赖注入管理容器,但我们强烈不建议您更换该组件。
|
||||
[hyperf/di](https://github.com/hyperf-cloud/di) 是一个强大的用于管理类的依赖关并完成自动注入的组件,与传统依赖注入容器的区别在于更符合长生命周期的应用使用、提供了 [注解及注解注入](zh/annotation.md) 的支持、提供了无比强大的 [AOP 面向切面编程](zh/aop.md) 能力,这些能力及易用性作为 Hyperf 的核心输出,我们自信的认为该组件是最优秀的。
|
||||
[hyperf/di](https://github.com/hyperf-cloud/di) 是一个强大的用于管理类的依赖关并完成自动注入的组件,与传统依赖注入容器的区别在于更符合长生命周期的应用使用、提供了 [注解及注解注入](en/annotation.md) 的支持、提供了无比强大的 [AOP 面向切面编程](en/aop.md) 能力,这些能力及易用性作为 Hyperf 的核心输出,我们自信的认为该组件是最优秀的。
|
||||
|
||||
## Installation
|
||||
|
||||
@ -169,7 +169,7 @@ class IndexController
|
||||
|
||||
### 工厂对象注入
|
||||
|
||||
我们假设 `UserService` 的实现会更加复杂一些,在创建 `UserService` 对象时构造函数还需要传递进来一些非直接注入型的参数,假设我们需要从配置中取得一个值,然后 `UserService` 需要根据这个值来决定是否开启缓存模式(顺带一说 Hyperf 提供了更好用的 [模型缓存](zh/db/model-cache.md) 功能)
|
||||
我们假设 `UserService` 的实现会更加复杂一些,在创建 `UserService` 对象时构造函数还需要传递进来一些非直接注入型的参数,假设我们需要从配置中取得一个值,然后 `UserService` 需要根据这个值来决定是否开启缓存模式(顺带一说 Hyperf 提供了更好用的 [模型缓存](en/db/model-cache.md) 功能)
|
||||
|
||||
我们需要创建一个工厂来生成 `UserService` 对象:
|
||||
|
||||
@ -239,7 +239,7 @@ return [
|
||||
### 容器仅管理长生命周期的对象
|
||||
|
||||
换种方式理解就是容器内管理的对象**都是单例**,这样的设计对于长生命周期的应用来说会更加的高效,减少了大量无意义的对象创建和销毁,这样的设计也就意味着所有需要交由 DI 容器管理的对象**均不能包含** `状态` 值。
|
||||
`状态` 可直接理解为会随着请求而变化的值,事实上在 [协程](zh/coroutine.md) 编程中,这些状态值也是应该存放于 `协程上下文` 中的,即 `Hyperf\Utils\Context`。
|
||||
`状态` 可直接理解为会随着请求而变化的值,事实上在 [协程](en/coroutine.md) 编程中,这些状态值也是应该存放于 `协程上下文` 中的,即 `Hyperf\Utils\Context`。
|
||||
|
||||
## 短生命周期对象
|
||||
|
@ -11,8 +11,8 @@ If you are an individual user and have enjoyed the productivity of using Hyperf,
|
||||
|
||||
We accept donations through these channels:
|
||||
|
||||
![alipay](./imgs/alipay.jpg ':size=375')
|
||||
![wechat](./imgs/wechatpay.jpg ':size=375')
|
||||
![alipay](imgs/alipay.jpg ':size=375')
|
||||
![wechat](imgs/wechatpay.jpg ':size=375')
|
||||
|
||||
### Recurring Pledges
|
||||
|
@ -71,7 +71,7 @@ grpc
|
||||
|
||||
- gRPC server 服务器配置
|
||||
|
||||
`server.php` 文件(参考 [配置](zh/config.md)):
|
||||
`server.php` 文件(参考 [配置](en/config.md)):
|
||||
|
||||
```php
|
||||
'servers' => [
|
||||
@ -91,7 +91,7 @@ grpc
|
||||
|
||||
- gRPC server 路由配置
|
||||
|
||||
`routes.php` 文件(参考 [路由](zh/router.md)):
|
||||
`routes.php` 文件(参考 [路由](en/router.md)):
|
||||
|
||||
```php
|
||||
Router::addServer('grpc', function () {
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 185 KiB |
@ -42,7 +42,7 @@ class CalculatorService implements CalculatorServiceInterface
|
||||
`name` 属性为定义该服务的名称,这里定义一个全局唯一的名字即可,Hyperf 会根据该属性生成对应的 ID 注册到服务中心去;
|
||||
`protocol` 属性为定义该服务暴露的协议,目前仅支持 `jsonrpc` 和 `jsonrpc-http`,分别对应于 TCP 协议和 HTTP 协议下的两种协议,默认值为 `jsonrpc-http`,这里的值对应在 `Hyperf\Rpc\ProtocolManager` 里面注册的协议的 `key`,这两个本质上都是 JSON RPC 协议,区别在于数据格式化、数据打包、数据传输器等不同。
|
||||
`server` 属性为绑定该服务类发布所要承载的 `Server`,默认值为 `jsonrpc-http`,该属性对应 `config/autoload/server.php` 文件内 `servers` 下所对应的 `name`,这里也就意味着我们需要定义一个对应的 `Server`,我们下一章节具体阐述这里应该怎样去处理;
|
||||
`publishTo` 属性为定义该服务所要发布的服务中心,目前仅支持 `consul` 或为空,为空时代表不发布该服务到服务中心去,但也就意味着您需要手动处理服务发现的问题,当值为 `consul` 时需要对应配置好 [hyperf/consul](./consul.md) 组件的相关配置;
|
||||
`publishTo` 属性为定义该服务所要发布的服务中心,目前仅支持 `consul` 或为空,为空时代表不发布该服务到服务中心去,但也就意味着您需要手动处理服务发现的问题,当值为 `consul` 时需要对应配置好 [hyperf/consul](consul.md) 组件的相关配置;
|
||||
|
||||
> 使用 `@RpcService` 注解需 `use Hyperf\RpcServer\Annotation\RpcService;` 命名空间。
|
||||
|
@ -173,7 +173,7 @@ class Log
|
||||
|
||||
是的, 还是通过强大的 `容器(Container)`.
|
||||
|
||||
- 首先, 实现一个 `StdoutLoggerFactory` 类,关于 `Factory` 的用法可在 [依赖注入](zh/di.md) 章节获得更多详细的说明。
|
||||
- 首先, 实现一个 `StdoutLoggerFactory` 类,关于 `Factory` 的用法可在 [依赖注入](en/di.md) 章节获得更多详细的说明。
|
||||
|
||||
```php
|
||||
<?php
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
@ -6,7 +6,7 @@ The middleware here refers to the `middleware mode`, which is a main function in
|
||||
|
||||
*The middleware is mainly used to weave the entire process from `Request` to `Response`.* Through the organization of multiple middleware, the flow of data is carried out in the way we order. The essence of middleware is an `Onion model`. Explain it through a diagram:
|
||||
|
||||
![middleware](./middleware.jpg)
|
||||
![middleware](middleware.jpg)
|
||||
|
||||
The order in the figure is organized in the order of `Middleware 1 -> Middleware 2 -> Middleware 3`. We can notice that when the middle horizontal line passes through the `kernel`, ie `Middleware 3`, it returns to `Middleware 2 `, this is a nested model, then the actual order is actually:
|
||||
`Request -> Middleware 1 -> Middleware 2 -> Middleware 3 -> Middleware 2 -> Middleware 1 -> Response`
|
@ -1,7 +1,7 @@
|
||||
# 分页器
|
||||
|
||||
在您需要对数据进行分页处理时,可以借助 [hyperf/paginator](https://github.com/hyperf-cloud/paginator) 组件很方便的解决您的问题,您可对您的数据查询进行一定的封装处理,以便更好的使用分页功能,该组件也可用于其它框架上。
|
||||
通常情况下,您对分页器的需求可能都是存在于数据库查询上,[hyperf/database](https://github.com/hyperf-cloud/database) 数据库组件已经与分页器组件进行了结合,您可以在进行数据查询时很方便的调用分页器来实现分页,具体可查阅 [数据库模型-分页](zh/db/paginator.md) 章节。
|
||||
通常情况下,您对分页器的需求可能都是存在于数据库查询上,[hyperf/database](https://github.com/hyperf-cloud/database) 数据库组件已经与分页器组件进行了结合,您可以在进行数据查询时很方便的调用分页器来实现分页,具体可查阅 [数据库模型-分页](en/db/paginator.md) 章节。
|
||||
|
||||
# 安装
|
||||
|
@ -8,4 +8,4 @@ Under `PHP-FPM`, you can get the requested parameters through global variables,
|
||||
|
||||
## Classes obtained through the container are singletons
|
||||
|
||||
Through the dependency injection container, all of the in-process persistence is shared by multiple coroutines, so it cannot contain any data that is unique to the request or unique to the coroutine. This type of data is processed through the coroutine context. Please read the [Dependency Injection] (./en/di.md) and [Coroutine] (./en/coroutine.md) sections carefully.
|
||||
Through the dependency injection container, all of the in-process persistence is shared by multiple coroutines, so it cannot contain any data that is unique to the request or unique to the coroutine. This type of data is processed through the coroutine context. Please read the [Dependency Injection] (en/di.md) and [Coroutine] (en/coroutine.md) sections carefully.
|
@ -9,7 +9,7 @@ The various versions of Dockerfile have been prepared for you in the [hyperf\hyp
|
||||
When you don't want to use Docker as the basis for your running environment, you need to make sure that your operating environment meets the following requirements:
|
||||
|
||||
- PHP >= 7.2
|
||||
- Swoole PHP extension >= 4.4,and Disabled `Short Name`
|
||||
- Swoole PHP extension >= 4.5,and Disabled `Short Name`
|
||||
- OpenSSL PHP extension
|
||||
- JSON PHP extension
|
||||
- PDO PHP extension (If you need to use MySQL Client)
|
||||
@ -36,7 +36,7 @@ Assuming your native environment does not meet the Hyperf environment requiremen
|
||||
|
||||
```
|
||||
# Download and run hyperf/hyperf image,and bind the directory of project with /tmp/skeleton of Host
|
||||
docker run -v /tmp/skeleton:/hyperf-skeleton -p 9501:9501 -it --entrypoint /bin/sh hyperf/hyperf:7.2-alpine-cli
|
||||
docker run -v /tmp/skeleton:/hyperf-skeleton -p 9501:9501 -it --entrypoint /bin/sh hyperf/hyperf:latest
|
||||
|
||||
# After the mirror container is running, install Composer in the container
|
||||
wget https://github.com/composer/composer/releases/download/1.8.6/composer.phar
|
@ -6,7 +6,7 @@ In order to let you know more about the use of `Hyperf`, this chapter will intro
|
||||
|
||||
Hyperf use [nikic/fast-route] (https://github.com/nikic/FastRoute) as the default routing component, so you can easily define your route in `config/routes.php`.
|
||||
|
||||
Not only that,Hyperf also provides an extremely powerful and convenient "Annotation Routing" feature, for more information on routing, please refer to the [Router] (zh/router.md) section.
|
||||
Not only that,Hyperf also provides an extremely powerful and convenient "Annotation Routing" feature, for more information on routing, please refer to the [Router] (en/router.md) section.
|
||||
|
||||
### Define routes by file configuration
|
||||
|
||||
@ -36,7 +36,7 @@ Router::addRoute(['GET', 'POST', 'HEAD'], '/multi', [\App\Controller\IndexContro
|
||||
|
||||
### Define routes by annotations
|
||||
|
||||
`Hyperf` provides an extremely powerful and convenient [annotation] (zh/annotation.md) feature, and there is no doubt that the definition of the route also provides a way to define by annotation. Hyperf provides `@Controller` and `@ AutoController` annotations to define a `Controller`. Here is a brief description. For more details, please refer to the [Routing] (zh/router.md) section.
|
||||
`Hyperf` provides an extremely powerful and convenient [annotation] (en/annotation.md) feature, and there is no doubt that the definition of the route also provides a way to define by annotation. Hyperf provides `@Controller` and `@ AutoController` annotations to define a `Controller`. Here is a brief description. For more details, please refer to the [Routing] (en/router.md) section.
|
||||
|
||||
### Define routes by `@AutoController`
|
||||
s
|
@ -71,7 +71,7 @@ class RateLimitController
|
||||
## 触发限流
|
||||
当限流被触发时, 默认会抛出 `Hyperf\RateLimit\Exception\RateLimitException` 异常
|
||||
|
||||
可以通过[异常处理](zh/exception-handler.md)或者配置 `limitCallback` 限流回调处理。
|
||||
可以通过[异常处理](en/exception-handler.md)或者配置 `limitCallback` 限流回调处理。
|
||||
|
||||
例如:
|
||||
```php
|
@ -82,7 +82,7 @@ Router::addGroup('/user/',function (){
|
||||
|
||||
### 通过注解定义路由
|
||||
|
||||
`Hyperf` 提供了非常便利的 [注解](zh/annotation.md) 路由功能,您可以直接在任意类上通过定义 `@Controller` 或 `@AutoController` 注解来完成一个路由的定义。
|
||||
`Hyperf` 提供了非常便利的 [注解](en/annotation.md) 路由功能,您可以直接在任意类上通过定义 `@Controller` 或 `@AutoController` 注解来完成一个路由的定义。
|
||||
|
||||
#### `@AutoController` 注解
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
# 注册服务
|
||||
|
||||
注册服务可通过 `@RpcService` 注解对一个类进行定义,即为发布这个服务了,目前 Hyperf 仅适配了 JSON RPC 协议,具体内容也可到 [JSON RPC 服务](./zh/json-rpc.md) 章节了解详情。
|
||||
注册服务可通过 `@RpcService` 注解对一个类进行定义,即为发布这个服务了,目前 Hyperf 仅适配了 JSON RPC 协议,具体内容也可到 [JSON RPC 服务](en/json-rpc.md) 章节了解详情。
|
||||
|
||||
```php
|
||||
<?php
|
||||
@ -31,6 +31,6 @@ class CalculatorService implements CalculatorServiceInterface
|
||||
`name` 属性为定义该服务的名称,这里定义一个全局唯一的名字即可,Hyperf 会根据该属性生成对应的 ID 注册到服务中心去;
|
||||
`protocol` 属性为定义该服务暴露的协议,目前仅支持 `jsonrpc` 和 `jsonrpc-http`,分别对应于 TCP 协议和 HTTP 协议下的两种协议,默认值为 `jsonrpc-http`,这里的值对应在 `Hyperf\Rpc\ProtocolManager` 里面注册的协议的 `key`,这两个本质上都是 JSON RPC 协议,区别在于数据格式化、数据打包、数据传输器等不同。
|
||||
`server` 属性为绑定该服务类发布所要承载的 `Server`,默认值为 `jsonrpc-http`,该属性对应 `config/autoload/server.php` 文件内 `servers` 下所对应的 `name`,这里也就意味着我们需要定义一个对应的 `Server`,我们下一章节具体阐述这里应该怎样去处理;
|
||||
`publishTo` 属性为定义该服务所要发布的服务中心,目前仅支持 `consul` 或为空,为空时代表不发布该服务到服务中心去,但也就意味着您需要手动处理服务发现的问题,当值为 `consul` 时需要对应配置好 [hyperf/consul](./consul.md) 组件的相关配置;
|
||||
`publishTo` 属性为定义该服务所要发布的服务中心,目前仅支持 `consul` 或为空,为空时代表不发布该服务到服务中心去,但也就意味着您需要手动处理服务发现的问题,当值为 `consul` 时需要对应配置好 [hyperf/consul](consul.md) 组件的相关配置;
|
||||
|
||||
> 使用 `@RpcService` 注解需 use Hyperf\RpcServer\Annotation\RpcService; 命名空间。
|
@ -90,4 +90,4 @@
|
||||
* Component Development Guide
|
||||
|
||||
* [Introduction](en/component-guide/intro.md)
|
||||
* [Create a new component](en/zh/component-guide/create.md)
|
||||
* [Create a new component](en/component-guide/create.md)
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@ -60,7 +60,7 @@
|
||||
'/summary.md': './zh-cn/summary.md'
|
||||
},
|
||||
plugins: [
|
||||
EditOnGithubPlugin.create('https://github.com/hyperf/hyperf/tree/master/doc/')
|
||||
EditOnGithubPlugin.create('https://github.com/hyperf/hyperf/tree/master/docs/')
|
||||
],
|
||||
plantuml: {
|
||||
skin: 'classic',
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
@ -1,6 +1,6 @@
|
||||
# 介绍
|
||||
# 2.0 介绍
|
||||
|
||||
Hyperf 是基于 `Swoole 4.4+` 实现的高性能、高灵活性的 PHP 协程框架,内置协程服务器及大量常用的组件,性能较传统基于 `PHP-FPM` 的框架有质的提升,提供超高性能的同时,也保持着极其灵活的可扩展性,标准组件均基于 [PSR 标准](https://www.php-fig.org/psr) 实现,基于强大的依赖注入设计,保证了绝大部分组件或类都是 `可替换` 与 `可复用` 的。
|
||||
Hyperf 是基于 `Swoole 4.5+` 实现的高性能、高灵活性的 PHP 协程框架,内置协程服务器及大量常用的组件,性能较传统基于 `PHP-FPM` 的框架有质的提升,提供超高性能的同时,也保持着极其灵活的可扩展性,标准组件均基于 [PSR 标准](https://www.php-fig.org/psr) 实现,基于强大的依赖注入设计,保证了绝大部分组件或类都是 `可替换` 与 `可复用` 的。
|
||||
|
||||
框架组件库除了常见的协程版的 `MySQL 客户端`、`Redis 客户端`,还为您准备了协程版的 `Eloquent ORM`、`WebSocket 服务端及客户端`、`JSON RPC 服务端及客户端`、`GRPC 服务端及客户端`、`Zipkin/Jaeger (OpenTracing) 客户端`、`Guzzle HTTP 客户端`、`Elasticsearch 客户端`、`Consul 客户端`、`ETCD 客户端`、`AMQP 组件`、`Apollo 配置中心`、`阿里云 ACM 应用配置管理`、`ETCD 配置中心`、`基于令牌桶算法的限流器`、`通用连接池`、`熔断器`、`Swagger 文档生成`、`Swoole Tracker`、`视图引擎`、`Snowflake 全局 ID 生成器` 等组件,省去了自己实现对应协程版本的麻烦。
|
||||
|
@ -137,10 +137,218 @@ class Foo extends AbstractAnnotation
|
||||
- `public function collectMethod(string $className, ?string $target): void;` 当注解定义在类方法时被扫描时会触发该方法
|
||||
- `public function collectProperty(string $className, ?string $target): void` 当注解定义在类属性时被扫描时会触发该方法
|
||||
|
||||
因为框架实现了注解收集器缓存功能,所以需要您将自定义收集器配置到 `annotations.scan.collectors` 中,这样框架才能自动缓存收集好的注解,在下次启动时进行复用。
|
||||
如果没有配置对应的收集器,就会导致自定义注解只有在首次启动 `server` 时生效,而再次启动时不会生效。
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
return [
|
||||
// 注意在 config/autoload 文件下的配置文件则无 annotations 这一层
|
||||
'annotations' => [
|
||||
'scan' => [
|
||||
'collectors' => [
|
||||
CustomCollector::class,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
```
|
||||
|
||||
### 利用注解数据
|
||||
|
||||
在没有自定义注解收集方法时,默认会将注解的元数据统一收集在 `Hyperf\Di\Annotation\AnnotationCollector` 类内,通过该类的静态方法可以方便的获取对应的元数据用于逻辑判断或实现。
|
||||
|
||||
### ClassMap 功能
|
||||
|
||||
框架提供了 `class_map` 配置,可以方便用户直接替换需要加载的类。
|
||||
|
||||
比如以下我们实现一个可以自动复制协程上下文的功能:
|
||||
|
||||
首先,我们实现一个用于复制上下文的 `Coroutine` 类。其中 `create()` 方法,可以将父类的上下文复制到子类当中。
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace App\Kernel\Context;
|
||||
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
|
||||
use Hyperf\Utils;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Swoole\Coroutine as SwooleCoroutine;
|
||||
|
||||
class Coroutine
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @var StdoutLoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var null|FormatterInterface
|
||||
*/
|
||||
protected $formatter;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->logger = $container->get(StdoutLoggerInterface::class);
|
||||
if ($container->has(FormatterInterface::class)) {
|
||||
$this->formatter = $container->get(FormatterInterface::class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int Returns the coroutine ID of the coroutine just created.
|
||||
* Returns -1 when coroutine create failed.
|
||||
*/
|
||||
public function create(callable $callable): int
|
||||
{
|
||||
$id = Utils\Coroutine::id();
|
||||
$result = SwooleCoroutine::create(function () use ($callable, $id) {
|
||||
try {
|
||||
Utils\Context::copy($id);
|
||||
call($callable);
|
||||
} catch (Throwable $throwable) {
|
||||
if ($this->formatter) {
|
||||
$this->logger->warning($this->formatter->format($throwable));
|
||||
} else {
|
||||
$this->logger->warning((string) $throwable);
|
||||
}
|
||||
}
|
||||
});
|
||||
return is_int($result) ? $result : -1;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
然后,我们实现一个跟 `Hyperf\Utils\Coroutine` 一模一样的对象。其中 `create()` 方法替换成我们上述实现的方法。
|
||||
|
||||
`app/Kernel/ClassMap/Coroutine.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Utils;
|
||||
|
||||
use App\Kernel\Context\Coroutine as BCoroutine;
|
||||
use Swoole\Coroutine as SwooleCoroutine;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
|
||||
/**
|
||||
* @method static void defer(callable $callable)
|
||||
*/
|
||||
class Coroutine
|
||||
{
|
||||
public static function __callStatic($name, $arguments)
|
||||
{
|
||||
if (! method_exists(SwooleCoroutine::class, $name)) {
|
||||
throw new \BadMethodCallException(sprintf('Call to undefined method %s.', $name));
|
||||
}
|
||||
return SwooleCoroutine::$name(...$arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current coroutine ID.
|
||||
* Returns -1 when running in non-coroutine context.
|
||||
*/
|
||||
public static function id(): int
|
||||
{
|
||||
return SwooleCoroutine::getCid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent coroutine ID.
|
||||
* Returns -1 when running in the top level coroutine.
|
||||
* Returns null when running in non-coroutine context.
|
||||
*
|
||||
* @see https://github.com/swoole/swoole-src/pull/2669/files#diff-3bdf726b0ac53be7e274b60d59e6ec80R940
|
||||
*/
|
||||
public static function parentId(?int $coroutineId = null): ?int
|
||||
{
|
||||
if ($coroutineId) {
|
||||
$cid = SwooleCoroutine::getPcid($coroutineId);
|
||||
} else {
|
||||
$cid = SwooleCoroutine::getPcid();
|
||||
}
|
||||
if ($cid === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $cid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int Returns the coroutine ID of the coroutine just created.
|
||||
* Returns -1 when coroutine create failed.
|
||||
*/
|
||||
public static function create(callable $callable): int
|
||||
{
|
||||
return ApplicationContext::getContainer()->get(BCoroutine::class)->create($callable);
|
||||
}
|
||||
|
||||
public static function inCoroutine(): bool
|
||||
{
|
||||
return Coroutine::id() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
然后配置一下 `class_map`,如下:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Hyperf\Utils\Coroutine;
|
||||
|
||||
return [
|
||||
'scan' => [
|
||||
'paths' => [
|
||||
BASE_PATH . '/app',
|
||||
],
|
||||
'ignore_annotations' => [
|
||||
'mixin',
|
||||
],
|
||||
'class_map' => [
|
||||
// 需要映射的类名 => 类所在的文件地址
|
||||
Coroutine::class => BASE_PATH . '/app/Kernel/ClassMap/Coroutine.php',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
```
|
||||
|
||||
这样 `co()` 和 `parallel()` 等方法,就可以自动拿到父协程,上下文中的数据,比如 `Request`。
|
||||
|
||||
## IDE 注解插件
|
||||
|
||||
因为 `PHP` 并不是原生支持 `注解`,所以 `IDE` 不会默认增加注解支持。但我们可以添加第三方插件,来让 `IDE` 支持 `注解`。
|
@ -4,16 +4,16 @@
|
||||
|
||||
AOP 为 `Aspect Oriented Programming` 的缩写,意为:`面向切面编程`,通过动态代理等技术实现程序功能的统一维护的一种技术。AOP 是 OOP 的延续,也是 Hyperf 中的一个重要内容,是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
|
||||
|
||||
用通俗的话来讲,就是在 Hyperf 里可以通过 `切面(Aspect)` 介入到由 [hyperf/di](https://github.com/hyperf/di) 管理的任意类的任意方法的执行流程中去,从而改变或加强原方法的功能,这就是 AOP。
|
||||
用通俗的话来讲,就是在 Hyperf 里可以通过 `切面(Aspect)` 介入到任意类的任意方法的执行流程中去,从而改变或加强原方法的功能,这就是 AOP。
|
||||
|
||||
> 使用 AOP 功能必须使用 [hyperf/di](https://github.com/hyperf/di) 来作为依赖注入容器
|
||||
> 注意这里所指的任意类并不是完全意义上的所有类,在 Hyperf 启动初期用于实现 AOP 功能的类自身不能被切入。
|
||||
|
||||
## 介绍
|
||||
|
||||
相对于其它框架实现的 AOP 功能的使用方式,我们进一步简化了该功能的使用不做过细的划分,仅存在 `环绕(Around)` 一种通用的形式:
|
||||
|
||||
- `切面(Aspect)` 为对流程织入的定义类,包括要介入的目标,以及实现对原方法的修改加强处理
|
||||
- `代理类(ProxyClass)` ,每个被介入的目标类最终都会生成一个代理类,来达到执行 `切面(Aspect)` 方法的目的,而非通过原类
|
||||
- `代理类(ProxyClass)` ,每个被介入的目标类最终都会生成一个代理类,来达到执行 `切面(Aspect)` 方法的目的
|
||||
|
||||
## 定义切面(Aspect)
|
||||
|
||||
@ -62,10 +62,50 @@ class FooAspect extends AbstractAspect
|
||||
|
||||
> 使用 `@Aspect` 注解时需 `use Hyperf\Di\Annotation\Aspect;` 命名空间;
|
||||
|
||||
您也可以通过 `@Aspect` 注解本身的属性来完成切入目标的配置,通过下面注解的形式可以达到与上面的示例一样的目的:
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Aspect;
|
||||
|
||||
use App\Service\SomeClass;
|
||||
use App\Annotation\SomeAnnotation;
|
||||
use Hyperf\Di\Annotation\Aspect;
|
||||
use Hyperf\Di\Aop\AbstractAspect;
|
||||
use Hyperf\Di\Aop\ProceedingJoinPoint;
|
||||
|
||||
/**
|
||||
* @Aspect(
|
||||
* classes={
|
||||
* SomeClass::class,
|
||||
* "App\Service\SomeClass::someMethod",
|
||||
* "App\Service\SomeClass::*Method"
|
||||
* },
|
||||
* annotations={
|
||||
* SomeAnnotation::class
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class FooAspect extends AbstractAspect
|
||||
{
|
||||
public function process(ProceedingJoinPoint $proceedingJoinPoint)
|
||||
{
|
||||
// 切面切入后,执行对应的方法会由此来负责
|
||||
// $proceedingJoinPoint 为连接点,通过该类的 process() 方法调用原方法并获得结果
|
||||
// 在调用前进行某些处理
|
||||
$result = $proceedingJoinPoint->process();
|
||||
// 在调用后进行某些处理
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 注意目前的 AOP 机制尚未能直接切入 trait 的方法,您可通过使用类重写该方法,并对使用类进行切入。
|
||||
|
||||
## 代理类缓存
|
||||
|
||||
所有被 AOP 影响的类,都会在 `./runtime/container/proxy/` 文件夹内生成对应的 `代理类缓存`,服务启动时,如果类所对应的代理类缓存存在,则不会重新生成直接使用缓存,即使 `Aspect` 的切入范围发生了改变。不存在时,则会自动重新生成新的代理类缓存。
|
||||
所有被 AOP 影响的类,都会在 `./runtime/container/proxy/` 文件夹内生成对应的 `代理类缓存`,是否在启动时自动生成取决于 `config/config.php` 配置文件中 `scan_cacheable` 配置项的值,默认值为 `false`,如果该配置项为 `true` 则 Hyperf 不会扫描和生成代理类缓存,而是直接以现有的缓存文件作为最终的代理类。如果该配置项为 `false`,则 Hyperf 会在每次启动应用时扫描注解扫描域并自动的生成对应的代理类缓存,当代码发生变化时,代理类缓存也会自动的重新生成。
|
||||
|
||||
在部署生产环境时,我们可能会希望 Hyperf 提前将所有代理类提前生成,而不是使用时动态的生成,可以通过 `php bin/hyperf.php di:init-proxy` 命令来生成所有代理类,该命令会忽视现有的代理类缓存,全部重新生成。
|
||||
通常在开发环境下,该值为 `false`,这样更便于开发调试,而在部署生产环境时,我们可能会希望 Hyperf 提前将所有代理类提前生成,而不是使用时动态的生成,可以通过 `php bin/hyperf.php` 命令来生成所有代理类,然后再通过环境变量 `SCAN_CACHEABLE` 为 `true` 修改该配置项的值,以达到启动时间更短、应用内存占用更低的目的。
|
||||
|
||||
基于以上,我们可以将生成代理类的命令和启动服务的命令结合起来,`vendor/bin/init-proxy.sh && php bin/hyperf.php start` 来达到自动重新生成所有代理类缓存然后启动服务的目的。
|
||||
基于以上,如果您使用 Docker 或 Kubernetes 等虚拟化技术来部署您的应用的话,您可以在镜像构建阶段就生成对应的代理类缓存并写入到镜像中去,在运行镜像实例时,可大大减少启动时间和应用内存。
|
@ -440,3 +440,29 @@ use Hyperf\Utils\ApplicationContext;
|
||||
$driver = ApplicationContext::getContainer()->get(DriverFactory::class)->get('other');
|
||||
return $driver->push(new ExampleJob());
|
||||
```
|
||||
|
||||
## 安全关闭
|
||||
|
||||
异步队列在终止时,如果正在进行消费逻辑,可能会导致出现错误。框架提供了 `DriverStopHandler` ,可以让异步队列进程安全关闭。
|
||||
|
||||
安装信号处理器
|
||||
|
||||
```
|
||||
composer require hyperf/signal
|
||||
```
|
||||
|
||||
添加配置
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'handlers' => [
|
||||
Hyperf\AsyncQueue\Signal\DriverStopHandler::class,
|
||||
],
|
||||
'timeout' => 5.0,
|
||||
];
|
||||
|
||||
```
|
@ -5,7 +5,7 @@
|
||||
|
||||
## 如何提交我的组件?
|
||||
|
||||
如果您开发的协程组件适配了 Hyperf,那么您可以直接对 [hyperf/hyperf](https://github.com/hyperf/hyperf) 项目的 `master` 分支发起您的 `Pull Request`,也就是更改当前页`(./doc/zh/awesome-components.md)`。
|
||||
如果您开发的协程组件适配了 Hyperf,那么您可以直接对 [hyperf/hyperf](https://github.com/hyperf/hyperf) 项目的 `master` 分支发起您的 `Pull Request`,也就是更改当前页`(zh-cn/awesome-components.md)`。
|
||||
|
||||
## 如何适配 Hyperf ?
|
||||
|
||||
@ -117,6 +117,7 @@
|
||||
|
||||
- [mabu233/sdebug](https://github.com/mabu233/sdebug) 用于协助开发与调试,`xdebug`的协程改造版
|
||||
- [firstphp/wsdebug](https://github.com/lamplife/wsdebug) 通过 `WebSocket` 实时观测异常错误的开发调试组件
|
||||
- [qbhy/hyperf-multi-env](https://github.com/qbhy/hyperf-multi-env) 支持与 laravel 类似的多 env 配置文件功能,通过 `APP_ENV=testing` 可以加载 `.env.testing` 配置覆盖默认的 `.env`
|
||||
|
||||
## 权限认证
|
||||
|
@ -1,5 +1,139 @@
|
||||
# 版本更新记录
|
||||
|
||||
# v2.0.1 - 2020-07-02
|
||||
|
||||
## Added
|
||||
|
||||
- [#1934](https://github.com/hyperf/hyperf/pull/1934) 增加脚本 `gen:constant` 用于创建常量类。
|
||||
- [#1982](https://github.com/hyperf/hyperf/pull/1982) 添加热更新组件,文件修改后自动收集注解,自动重启。
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#1952](https://github.com/hyperf/hyperf/pull/1952) 修复数据库迁移类存在时,也会生成同类名类,导致类名冲突的BUG。
|
||||
- [#1960](https://github.com/hyperf/hyperf/pull/1960) 修复 `Hyperf\HttpServer\ResponseEmitter::isMethodsExists()` 判断错误的BUG。
|
||||
- [#1961](https://github.com/hyperf/hyperf/pull/1961) 修复因文件 `config/autoload/aspects.php` 不存在导致服务无法启动的BUG。
|
||||
- [#1964](https://github.com/hyperf/hyperf/pull/1964) 修复接口请求时,数据体为空会导致 `500` 错误的BUG。
|
||||
- [#1965](https://github.com/hyperf/hyperf/pull/1965) 修复 `initRequestAndResponse` 失败后,会导致请求状态码与实际不符的BUG。
|
||||
- [#1968](https://github.com/hyperf/hyperf/pull/1968) 修复当修改 `aspects.php` 文件后,`Aspect` 无法安装修改后的结果运行的BUG。
|
||||
- [#1985](https://github.com/hyperf/hyperf/pull/1985) 修复注解全局配置不全为小写时,会导致 `global_imports` 失败的BUG。
|
||||
- [#1990](https://github.com/hyperf/hyperf/pull/1990) 修复当父类存在与子类一样的成员变量时, `@Inject` 无法正常使用的BUG。
|
||||
- [#2019](https://github.com/hyperf/hyperf/pull/2019) 修复脚本 `gen:model` 因为使用了 `morphTo` 或 `where` 导致生成对应的 `@property` 失败的BUG。
|
||||
- [#2026](https://github.com/hyperf/hyperf/pull/2026) 修复当使用了魔术方法时,LazyLoad 代理生成有误的BUG。
|
||||
|
||||
## Changed
|
||||
|
||||
- [#1986](https://github.com/hyperf/hyperf/pull/1986) 当没有设置正确的 `swoole.use_shortname` 变更脚本 `exit_code` 为 `SIGTERM`。
|
||||
|
||||
## Optimized
|
||||
|
||||
- [#1959](https://github.com/hyperf/hyperf/pull/1959) 优化类 `ClassLoader` 可以更容易被用户继承并修改。
|
||||
- [#2002](https://github.com/hyperf/hyperf/pull/2002) 当 `PHP` 版本大于等于 `7.3` 时,支持 `AOP` 切入 `Trait`。
|
||||
|
||||
# v2.0 - 2020-06-22
|
||||
|
||||
## 主要功能
|
||||
|
||||
1. 重构 [hyperf/di](https://github.com/hyperf/di) 组件,特别是对 AOP 和注解的优化,在 2.0 版本,该组件使用了一个全新的加载机制来提供 AOP 功能的支持。
|
||||
1. 对比 1.x 版本来说最显著的一个功能就是现在你可以通过 AOP 功能切入任何方式实例化的一个类了,比如说,在 1.x 版本,你只能切入由 DI 容器创建的类,你无法切入一个由 `new` 关键词实例化的类,但在 2.0 版本都可以生效了。不过仍有一些例外的情况,您仍无法切入那些在启动阶段用来提供 AOP 功能的类;
|
||||
2. 在 1.x 版本,AOP 只能作用于普通的类,无法支持 `Final` 类,但在 2.0 版本您可以这么做了;
|
||||
3. 在 1.x 版本,您无法在当前类的构造函数中使用 `@Inject` 或 `@Value` 注解标记的类成员属性的值,但在 2.0 版本里,您可以这么做了;
|
||||
4. 在 1.x 版本,只有通过 DI 容器创建的对象才能使 `@Inject` 和 `@Value` 注解的功能生效,通过 `new` 关键词创建的对象无法生效,但在 2.0 版本,都可以生效了;
|
||||
5. 在 1.x 版本,在使用注解时,您必须定义注解的命名空间来指定使用的注解类,但在 2.0 版本下,您可以为任一注解提供一个别名,这样在使用这个注解时可以直接使用别名而无需引入注解类的命名空间。比如您可以直接在任意类属性上标记 `@Inject` 注解而无需编写 `use Hyperf\Di\Annotation\Inject;`;
|
||||
6. 在 1.x 版本,创建的代理类是一个目标类的子类,这样的实现机制会导致一些魔术常量获得的值返回的是代理类子类的信息,而不是目标类的信息,但在 2.0 版本,代理类会与目标类保持一样的类名和代码结构;
|
||||
7. 在 1.x 版本,当代理类缓存存在时则不会重新生成缓存,就算源代码发生了变化,这样的机制有助于扫描耗时的提升,但与此同时,这也会导致开发阶段的一些不便利,但在 2.0 版本,代理类缓存会根据源代码的变化而自动变化,这一改变会减少很多在开发阶段的心智负担;
|
||||
8. 为 Aspect 类增加了 `priority` 优先级属性,现在您可以组织多个 Aspect 之间的顺序了;
|
||||
9. 在 1.x 版本,您只能通过 `@Aspect` 注解类定义一个 Aspect 类,但在 2.0 版本,您还可以通过配置文件、ConfigProvider 来定义 Aspect 类;
|
||||
10. 在 1.x 版本,您在使用到依赖懒加载功能时,必须注册一个 `Hyperf\Di\Listener\LazyLoaderBootApplicationListener` 监听器,但在 2.0 版本,您可以直接使用该功能而无需做任何的注册动作;
|
||||
11. 增加了 `annotations.scan.class_map` 配置项,通过该配置您可以将任意类替换成您自己的类,而使用时无需做任何的改变;
|
||||
|
||||
## 依赖库更新
|
||||
|
||||
- 将 `ext-swoole` 升级到了 `>=4.5`;
|
||||
- 将 `psr/event-dispatcher` 升级到了 `^1.0`;
|
||||
- 将 `monolog/monolog` 升级到了 `^2.0`;
|
||||
- 将 `phpstan/phpstan` 升级到了 `^0.12.18`;
|
||||
- 将 `vlucas/phpdotenv` 升级到了 `^4.0`;
|
||||
- 将 `symfony/finder` 升级到了 `^5.0`;
|
||||
- 将 `symfony/event-dispatcher` 升级到了 `^5.0`;
|
||||
- 将 `symfony/console` 升级到了 `^5.0`;
|
||||
- 将 `symfony/property-access` 升级到了 `^5.0`;
|
||||
- 将 `symfony/serializer` 升级到了 `^5.0`;
|
||||
- 将 `elasticsearch/elasticsearch` 升级到了 `^7.0`;
|
||||
|
||||
## 类和方法的变更
|
||||
|
||||
- 移除了 `Hyperf\Di\Aop\AstCollector`;
|
||||
- 移除了 `Hyperf\Di\Aop\ProxyClassNameVisitor`;
|
||||
- 移除了 `Hyperf\Di\Listener\LazyLoaderBootApplicationListener`;
|
||||
- 移除了 `Hyperf\Dispatcher\AbstractDispatcher` 类的 `dispatch(...$params)` 方法;
|
||||
- 移除了 hyperf/utils 组件中 ConfigProvider 中的 `Hyperf\Contract\NormalizerInterface => Hyperf\Utils\Serializer\SymfonyNormalizer` 关系;
|
||||
- 移除了 `Hyperf\Contract\OnOpenInterface`、`Hyperf\Contract\OnCloseInterface`、`Hyperf\Contract\OnMessageInterface`、`Hyperf\Contract\OnReceiveInterface` 接口中的 `$server` 参数的强类型声明;
|
||||
|
||||
## 新增
|
||||
|
||||
- [#992](https://github.com/hyperf/hyperf/pull/992) 新增 [hyperf/reactive-x](https://github.com/hyperf/reactive-x) 组件;
|
||||
- [#1245](https://github.com/hyperf/hyperf/pull/1245) 为 `ExceptionHandler` 新增了注解的定义方式;
|
||||
- [#1245](https://github.com/hyperf/hyperf/pull/1245) `ExceptionHandler` 新增了 `priority` 优先级属性,通过配置文件或注解方式均可定义优先级;
|
||||
- [#1819](https://github.com/hyperf/hyperf/pull/1819) 新增 [hyperf/signal](https://github.com/hyperf/signal) 组件;
|
||||
- [#1844](https://github.com/hyperf/hyperf/pull/1844) 为 [hyperf/model-cache](https://github.com/hyperf/model-cache) 组件中的 `ttl` 属性增加了 `\DateInterval` 类型的支持;
|
||||
- [#1855](https://github.com/hyperf/hyperf/pull/1855) 连接池新增了 `ConstantFrequency` 恒定频率策略来释放限制的连接;
|
||||
- [#1871](https://github.com/hyperf/hyperf/pull/1871) 为 Guzzle 增加 `sink` 选项支持;
|
||||
- [#1805](https://github.com/hyperf/hyperf/pull/1805) 新增 Coroutine Server 协程服务支持;
|
||||
- 变更了 `Hyperf\Contract\ProcessInterface` 中的 `bind(Server $server)` 方法声明为 `bind($server)`;
|
||||
- 变更了 `Hyperf\Contract\ProcessInterface` 中的 `isEnable()` 方法声明为 `isEnable($server)`;
|
||||
- 配置中心、Crontab、服务监控、消息队列消费者现在可以通过协程模式来运行,且在使用协程服务模式时,也必须以协程模式来运行;
|
||||
- `Hyperf\AsyncQueue\Environment` 的作用域改为当前协程内,而不是整个进程;
|
||||
- 协程模式下不再支持 Task 机制;
|
||||
- [#1877](https://github.com/hyperf/hyperf/pull/1877) 在 PHP 8 下使用 `@Inject` 注解时支持通过成员属性强类型声明来替代 `@var` 声明,如下所示:
|
||||
|
||||
```
|
||||
class Example {
|
||||
/**
|
||||
* @Inject
|
||||
*/
|
||||
private ExampleService $exampleService;
|
||||
}
|
||||
```
|
||||
|
||||
- [#1890](https://github.com/hyperf/hyperf/pull/1890) 新增 `Hyperf\HttpServer\ResponseEmitter` 类来响应任意符合 PSR-7 标准的 Response 对象,同时抽象了 `Hyperf\Contract\ResponseEmitterInterface` 契约;
|
||||
- [#1890](https://github.com/hyperf/hyperf/pull/1890) 为 `Hyperf\HttpMessage\Server\Response` 类新增了 `getTrailers()` 和 `getTrailer(string $key)` 和 `withTrailer(string $key, $value)` 方法;
|
||||
- [#1920](https://github.com/hyperf/hyperf/pull/1920) 新增方法 `Hyperf\WebSocketServer\Sender::close(int $fd, bool $reset = null)`.
|
||||
|
||||
## 修复
|
||||
|
||||
- [#1825](https://github.com/hyperf/hyperf/pull/1825) 修复了 `StartServer::execute` 的 `TypeError`;
|
||||
- [#1854](https://github.com/hyperf/hyperf/pull/1854) 修复了在 filesystem 中使用 `Runtime::enableCoroutine()` 时,`is_resource` 不能工作的问题;
|
||||
- [#1900](https://github.com/hyperf/hyperf/pull/1900) 修复了 `Model` 中的 `asDecimal` 方法类型有可能错误的问题;
|
||||
- [#1917](https://github.com/hyperf/hyperf/pull/1917) 修复了 `Request::isXmlHttpRequest` 方法无法正常工作的问题;
|
||||
|
||||
## 变更
|
||||
|
||||
- [#705](https://github.com/hyperf/hyperf/pull/705) 统一了 HTTP 异常的处理方式,现在统一抛出一个 `Hyperf\HttpMessage\Exception\HttpException` 依赖类来替代在 `Dispatcher` 中直接响应的方式,同时提供了 `Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler` 异常处理器来处理该类异常;
|
||||
- [#1846](https://github.com/hyperf/hyperf/pull/1846) 当您 require 了 `symfony/serializer` 库,不再自动映射 `Hyperf\Contract\NormalizerInterface` 的实现类,您需要手动添加该映射关系,如下:
|
||||
|
||||
```php
|
||||
use Hyperf\Utils\Serializer\SerializerFactory;
|
||||
use Hyperf\Utils\Serializer\Serializer;
|
||||
|
||||
return [
|
||||
Hyperf\Contract\NormalizerInterface::class => new SerializerFactory(Serializer::class),
|
||||
];
|
||||
```
|
||||
|
||||
- [#1924](https://github.com/hyperf/hyperf/pull/1924) 重命名 `Hyperf\GrpcClient\BaseClient` 内 `simpleRequest, getGrpcClient, clientStreamRequest` 方法名为 `_simpleRequest, _getGrpcClient, _clientStreamRequest`;
|
||||
|
||||
## 移除
|
||||
|
||||
- [#1890](https://github.com/hyperf/hyperf/pull/1890) Removed `Hyperf\Contract\Sendable` interface and all implementations of it.
|
||||
- [#1905](https://github.com/hyperf/hyperf/pull/1905) Removed config `config/server.php`, you can merge it into `config/config.php`.
|
||||
|
||||
## 优化
|
||||
|
||||
- [#1793](https://github.com/hyperf/hyperf/pull/1793) Socket.io 服务现在只在 onOpen and onClose 中触发 connect/disconnect 事件,同时将一些类方法从 private 级别调整到了 protected 级别,以便用户可以方便的重写这些方法;
|
||||
- [#1848](https://github.com/hyperf/hyperf/pull/1848) 当 RPC 客户端对应的 Contract 发生变更时,自动重写生成对应的动态代理客户端类;
|
||||
- [#1863](https://github.com/hyperf/hyperf/pull/1863) 为 async-queue 组件提供更加安全的停止机制;
|
||||
- [#1896](https://github.com/hyperf/hyperf/pull/1896) 当在 constants 组件中使用了同样的 code 时,keys 会被合并起来;
|
||||
|
||||
# v1.1.32 - 2020-05-21
|
||||
|
||||
## 修复
|
@ -13,7 +13,7 @@ composer require hyperf/circuit-breaker
|
||||
## 使用熔断器
|
||||
|
||||
熔断器的使用十分简单,只需要加入 `Hyperf\CircuitBreaker\Annotation\CircuitBreaker` 注解,就可以根据规定策略,进行熔断。
|
||||
比如我们需要到另外服务中查询用户列表,用户列表需要关联很多的表,查询效率较低,但平常并发量不高的时候,相应速度还说得过去。一旦并发量激增,就会导致响应速度变慢,并会使对方服务出现慢查。这个时候,我们只需要配置一下熔断超时时间 `timeout` 为 0.05 秒,失败计数 `failCounter` 超过 1 次后熔断,相应 `fallback` 为 `App\Service\UserService` 类的 `searchFallback` 方法。这样当响应超时并触发熔断后,就不会再请求对端的服务了,而是直接将服务降级从当前项目中返回数据,即根据 `fallback` 指定的方法来进行返回。
|
||||
比如我们需要到另外服务中查询用户列表,用户列表需要关联很多的表,查询效率较低,但平常并发量不高的时候,响应速度还说得过去。一旦并发量激增,就会导致响应速度变慢,并会使对方服务出现慢查。这个时候,我们只需要配置一下熔断超时时间 `timeout` 为 0.05 秒,失败计数 `failCounter` 超过 1 次后熔断,相应 `fallback` 为 `App\Service\UserService` 类的 `searchFallback` 方法。这样当响应超时并触发熔断后,就不会再请求对端的服务了,而是直接将服务降级从当前项目中返回数据,即根据 `fallback` 指定的方法来进行返回。
|
||||
|
||||
```php
|
||||
<?php
|
@ -360,4 +360,80 @@ array(2) {
|
||||
|
||||
```
|
||||
|
||||
# 运行命令
|
||||
|
||||
## 命令行中运行
|
||||
|
||||
```bash
|
||||
php bin/hyperf.php foo
|
||||
```
|
||||
|
||||
## 在 Command 中运行其他命令
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use Hyperf\Command\Command as HyperfCommand;
|
||||
use Hyperf\Command\Annotation\Command;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @Command
|
||||
*/
|
||||
class FooCommand extends HyperfCommand
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
parent::__construct('foo');
|
||||
}
|
||||
|
||||
public function configure()
|
||||
{
|
||||
parent::configure();
|
||||
$this->setDescription('foo command');
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$this->call('bar', [
|
||||
'--foo' => 'foo'
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 在非 Command 中运行命令
|
||||
|
||||
```php
|
||||
$command = 'foo';
|
||||
|
||||
$params = ["command" => $command, "--foo" => "foo", "--bar" => "bar"];
|
||||
|
||||
// 可以根据自己的需求, 选择使用的 input/output
|
||||
$input = new ArrayInput($params);
|
||||
$output = new NullOutput();
|
||||
|
||||
/** @var \Psr\Container\ContainerInterface $container */
|
||||
$container = \Hyperf\Utils\ApplicationContext::getContainer();
|
||||
|
||||
/** @var \Symfony\Component\Console\Application $application */
|
||||
$application = $container->get(\Hyperf\Contract\ApplicationInterface::class);
|
||||
$application->setAutoExit(false);
|
||||
|
||||
// 这种方式: 不会暴露出命令执行中的异常, 不会阻止程序返回
|
||||
$exitCode = $application->run($input, $output);
|
||||
|
||||
// 第二种方式: 会暴露异常, 需要自己捕捉和处理运行中的异常, 否则会阻止程序的返回
|
||||
$exitCode = $application->find($command)->run($input, $output);
|
||||
```
|
@ -15,4 +15,4 @@ Hyperf 交流 2 群: `811414891`
|
||||
|
||||
为了更好的发展 Hyperf 的社区,我们专门为 Hyperf Contributor 提供了一个微信群,以便我们对 Pull Request 或迭代计划进行更详细的探讨,由于微信群无法直接加入,故可先加下方二维码好友,并声明目的且带上您已经被 Merged 的 Pull Request,再拉您入群。
|
||||
|
||||
![wechat](./imgs/wechat.jpg ':size=375')
|
||||
![wechat](imgs/wechat.jpg ':size=375')
|
@ -20,7 +20,7 @@ $message = ErrorCode::messages[ErrorCode::SERVER_ERROR] ?? '未知错误';
|
||||
|
||||
```
|
||||
|
||||
但这种实现方式并不友好,每当要查询错误码与对应错误信息时,都要在当前 `Class` 中搜索两次。所以框架提供了基于注解的枚举类。
|
||||
但这种实现方式并不友好,每当要查询错误码与对应错误信息时,都要在当前 `Class` 中搜索两次,所以框架提供了基于注解的枚举类。
|
||||
|
||||
## 安装
|
||||
|
||||
@ -32,6 +32,14 @@ composer require hyperf/constants
|
||||
|
||||
### 定义枚举类
|
||||
|
||||
通过 `gen:constant` 命令可以快速的生成一个枚举类。
|
||||
|
||||
```bash
|
||||
php bin/hyperf.php gen:constant ErrorCode
|
||||
```
|
||||
|
||||
!> 此生成命令仅在 [hyperf/constants](https://github.com/hyperf/constants) 组件版本大于等于 v2.0.1 版本时可用,小于此版本时请手动创建枚举类。
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
@ -57,7 +65,6 @@ class ErrorCode extends AbstractConstants
|
||||
*/
|
||||
const SYSTEM_INVALID = 700;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
用户可以使用 `ErrorCode::getMessage(ErrorCode::SERVER_ERROR)` 来获取对应错误信息。
|
||||
@ -88,7 +95,6 @@ class BusinessException extends ServerException
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 抛出异常
|
||||
@ -112,7 +118,6 @@ class IndexController extends Controller
|
||||
throw new BusinessException(ErrorCode::SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 可变参数
|
||||
@ -139,7 +144,6 @@ class ErrorCode extends AbstractConstants
|
||||
$message = ErrorCode::getMessage(ErrorCode::PARAMS_INVALID, ['user_id']);
|
||||
|
||||
// 1.2 版本以下 可以使用以下方式,但会在 1.2 版本移除
|
||||
|
||||
$message = ErrorCode::getMessage(ErrorCode::PARAMS_INVALID, 'user_id');
|
||||
```
|
||||
|
||||
@ -153,7 +157,7 @@ $message = ErrorCode::getMessage(ErrorCode::PARAMS_INVALID, 'user_id');
|
||||
composer require hyperf/translation
|
||||
```
|
||||
|
||||
相关配置详见 [国际化](./translation.md)
|
||||
相关配置详见 [国际化](translation.md)
|
||||
|
||||
```php
|
||||
<?php
|
||||
@ -180,4 +184,3 @@ class ErrorCode extends AbstractConstants
|
||||
|
||||
$message = ErrorCode::getMessage(ErrorCode::SERVER_ERROR, ['param' => 'user_id']);
|
||||
```
|
||||
|