Merge pull request #1 from hyperf-cloud/master

merge master
This commit is contained in:
lcbyz 2019-09-02 14:04:13 +08:00 committed by GitHub
commit ad8b1ae398
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 414 additions and 40 deletions

View File

@ -12,6 +12,25 @@
## Changed
- [#437](https://github.com/hyperf-cloud/hyperf/pull/437) Changed `Hyperf\Testing\Client` handle exception handlers instead of throw an exception directly.
- [#463](https://github.com/hyperf-cloud/hyperf/pull/463) Simplify `container.php` and improve annotation caching mechanism.
config/container.php
```php
<?php
use Hyperf\Di\Container;
use Hyperf\Di\Definition\DefinitionSourceFactory;
use Hyperf\Utils\ApplicationContext;
$container = new Container((new DefinitionSourceFactory(true))());
if (! $container instanceof \Psr\Container\ContainerInterface) {
throw new RuntimeException('The dependency injection container is invalid.');
}
return ApplicationContext::setContainer($container);
```
- [#486](https://github.com/hyperf-cloud/hyperf/pull/486) Changed `getParsedBody` can return JSON formatted data normally.
## Deleted

View File

@ -81,7 +81,7 @@ if ($paginator->hasMorePages()) {
}
```
## 获取上一页和下一页的 URL
## 获取对应分页的 URL
```php
<?php
@ -89,12 +89,34 @@ if ($paginator->hasMorePages()) {
$nextPageUrl = $paginator->nextPageUrl();
// 上一页的 URL
$previousPageUrl = $paginator->previousPageUrl();
// 获取指定 $page 页数的 URL
$url = $paginator->url($page);
```
## 获取指定页数的 URL
## 是否处于第一页
```php
<?php
// 获取指定 $page 页数的 URL
$url = $paginator->url($page);
```
$onFirstPage = $paginator->onFirstPage();
```
## 是否有更多分页
```php
<?php
$hasMorePages = $paginator->hasMorePages();
```
## 每页的数据条数
```php
<?php
$perPage = $paginator->perPage();
```
## 数据总数
```php
<?php
$total = $paginator->total();
```

View File

@ -12,12 +12,11 @@ declare(strict_types=1);
namespace Hyperf\Cache;
use Hyperf\Di\MetadataCollector;
use Hyperf\Utils\Traits\Container;
class CacheListenerCollector
class CacheListenerCollector extends MetadataCollector
{
use Container;
/**
* @var array
*/

View File

@ -28,6 +28,9 @@ class ConfigProvider
'paths' => [
__DIR__,
],
'collectors' => [
CacheListenerCollector::class,
]
],
'publish' => [
[

View File

@ -40,6 +40,7 @@
"dev-master": "1.1-dev"
},
"hyperf": {
"config": "Hyperf\\Constants\\ConfigProvider"
}
},
"bin": [

View File

@ -0,0 +1,30 @@
<?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-cloud/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Constants;
class ConfigProvider
{
public function __invoke(): array
{
return [
'dependencies' => [
],
'scan' => [
'paths' => [],
'collectors' => [
ConstantsCollector::class,
],
],
];
}
}

View File

@ -12,12 +12,10 @@ declare(strict_types=1);
namespace Hyperf\Constants;
use Hyperf\Utils\Traits\Container;
use Hyperf\Di\MetadataCollector;
class ConstantsCollector
class ConstantsCollector extends MetadataCollector
{
use Container;
/**
* @var array
*/

View File

@ -57,7 +57,7 @@ class InitProxyCommand extends Command
protected function clearRuntime($paths)
{
$finder = new Finder();
$finder->files()->in($paths)->name('*.php');
$finder->files()->in($paths)->name(['*.php', '*.cache']);
/** @var SplFileInfo $file */
foreach ($finder as $file) {
@ -91,7 +91,7 @@ class InitProxyCommand extends Command
{
$scanDirs = $this->getScanDir();
$runtime = BASE_PATH . '/runtime/container/proxy/';
$runtime = BASE_PATH . '/runtime/container/';
if (is_dir($runtime)) {
$this->clearRuntime($runtime);
}

View File

@ -12,6 +12,8 @@ declare(strict_types=1);
namespace Hyperf\Di;
use Hyperf\Di\Annotation\AnnotationCollector;
use Hyperf\Di\Annotation\AspectCollector;
use Hyperf\Di\Command\InitProxyCommand;
use Hyperf\Di\Listener\BootApplicationListener;
@ -33,6 +35,10 @@ class ConfigProvider
'paths' => [
__DIR__,
],
'collectors' => [
AnnotationCollector::class,
AspectCollector::class,
],
],
];
}

View File

@ -16,6 +16,7 @@ use Hyperf\Di\Annotation\AnnotationCollector;
use Hyperf\Di\Annotation\AspectCollector;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Di\Annotation\Scanner;
use Hyperf\Di\MetadataCacheCollector;
use Hyperf\Di\ReflectionManager;
use ReflectionClass;
use ReflectionFunctionAbstract;
@ -67,13 +68,13 @@ class DefinitionSource implements DefinitionSourceInterface
*/
private $scanner;
public function __construct(array $source, array $scanDir, Scanner $scanner, bool $enableCache = false)
public function __construct(array $source, ScanConfig $scanConfig, bool $enableCache = false)
{
$this->scanner = $scanner;
$this->scanner = new Scanner($scanConfig->getIgnoreAnnotations());
$this->enableCache = $enableCache;
// Scan the specified paths and collect the ast and annotations.
$this->scan($scanDir);
$this->scan($scanConfig->getDirs(), $scanConfig->getCollectors());
$this->source = $this->normalizeSource($source);
}
@ -213,18 +214,17 @@ class DefinitionSource implements DefinitionSourceInterface
return $definition;
}
private function scan(array $paths): bool
private function scan(array $paths, array $collectors): bool
{
if (empty($paths)) {
return true;
}
$pathsHash = md5(implode(',', $paths));
$cacher = new MetadataCacheCollector($collectors);
if ($this->hasAvailableCache($paths, $pathsHash, $this->cachePath)) {
$this->printLn('Detected an available cache, skip the scan process.');
[, $annotationMetadata, $aspectMetadata] = explode(PHP_EOL, file_get_contents($this->cachePath));
// Deserialize metadata when the cache is valid.
AnnotationCollector::deserialize($annotationMetadata);
AspectCollector::deserialize($aspectMetadata);
[, $serialized] = explode(PHP_EOL, file_get_contents($this->cachePath));
$cacher->unserialize($serialized);
return false;
}
$this->printLn('Scanning ...');
@ -242,7 +242,8 @@ class DefinitionSource implements DefinitionSourceInterface
mkdir($dirPath, 0755, true);
}
}
$data = implode(PHP_EOL, [$pathsHash, AnnotationCollector::serialize(), AspectCollector::serialize()]);
$data = implode(PHP_EOL, [$pathsHash, $cacher->serialize()]);
file_put_contents($this->cachePath, $data);
return true;
}

View File

@ -0,0 +1,71 @@
<?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-cloud/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Di\Definition;
use Hyperf\Config\ProviderConfig;
use Hyperf\Di\Exception\Exception;
class DefinitionSourceFactory
{
/**
* @var bool
*/
protected $enableCache = false;
/**
* @var string
*/
protected $baseUri;
public function __construct(bool $enableCache = false)
{
$this->enableCache = $enableCache;
if (! defined('BASE_PATH')) {
throw new Exception('BASE_PATH is not defined.');
}
$this->baseUri = BASE_PATH;
}
public function __invoke()
{
$configDir = $this->baseUri . '/config';
$configFromProviders = [];
if (class_exists(ProviderConfig::class)) {
$configFromProviders = ProviderConfig::load();
}
$serverDependencies = $configFromProviders['dependencies'] ?? [];
if (file_exists($configDir . '/dependencies.php')) {
$definitions = include $configDir . '/dependencies.php';
$serverDependencies = array_replace($serverDependencies, $definitions['dependencies'] ?? []);
}
$scanDirs = $configFromProviders['scan']['paths'] ?? [];
$ignoreAnnotations = [];
$collectors = $configFromProviders['scan']['collectors'] ?? [];
if (file_exists($configDir . '/autoload/annotations.php')) {
$annotations = include $configDir . '/autoload/annotations.php';
$scanDirs = array_merge($scanDirs, $annotations['scan']['paths'] ?? []);
$ignoreAnnotations = $annotations['scan']['ignore_annotations'] ?? [];
$collectors = array_merge($collectors, $annotations['scan']['collectors'] ?? []);
}
$scanConfig = new ScanConfig($scanDirs, $ignoreAnnotations, $collectors);
return new DefinitionSource($serverDependencies, $scanConfig, $this->enableCache);
}
}

View File

@ -0,0 +1,71 @@
<?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-cloud/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Di\Definition;
class ScanConfig
{
/**
* @var array
*/
protected $dirs;
/**
* @var array
*/
protected $ignoreAnnotations;
/**
* @var array
*/
protected $collectors;
public function __construct(array $dirs = [], array $ignoreAnnotations = [], array $collectors = [])
{
$this->dirs = $dirs;
$this->ignoreAnnotations = $ignoreAnnotations;
$this->collectors = $collectors;
}
public function getDirs(): array
{
return $this->dirs;
}
public function setDirs(array $dirs): self
{
$this->dirs = $dirs;
return $this;
}
public function getIgnoreAnnotations(): array
{
return $this->ignoreAnnotations;
}
public function setIgnoreAnnotations(array $ignoreAnnotations): self
{
$this->ignoreAnnotations = $ignoreAnnotations;
return $this;
}
public function getCollectors(): array
{
return $this->collectors;
}
public function setCollectors(array $collectors): self
{
$this->collectors = $collectors;
return $this;
}
}

View File

@ -0,0 +1,65 @@
<?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-cloud/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Di;
class MetadataCacheCollector
{
/**
* @var array
*/
protected $collectors = [];
public function __construct(array $collectors)
{
$this->collectors = $collectors;
}
public function addCollector(string $collector)
{
$this->collectors = array_unique(array_merge(
$this->collectors,
[$collector]
));
}
public function clear()
{
$this->collectors = [];
}
public function serialize(): string
{
$metadata = [];
foreach ($this->collectors as $collector) {
if (is_string($collector) && method_exists($collector, 'serialize')) {
$metadata[$collector] = call([$collector, 'serialize']);
}
}
return json_encode($metadata);
}
public function unserialize($serialized): void
{
$metadatas = json_decode($serialized, true) ?? [];
$collectors = [];
foreach ($metadatas as $collector => $metadata) {
if (method_exists($collector, 'deserialize')) {
call([$collector, 'deserialize'], [$metadata]);
$collectors[] = $collector;
}
}
$this->collectors = $collectors;
}
}

View File

@ -35,4 +35,9 @@ interface MetadataCollectorInterface
* Deserialize the serialized metadata and set the metadata to holder.
*/
public static function deserialize(string $metadata): bool;
/**
* Return all metadata array.
*/
public static function list(): array;
}

View File

@ -12,9 +12,9 @@ declare(strict_types=1);
namespace HyperfTest\Di;
use Hyperf\Di\Annotation\Scanner;
use Hyperf\Di\Container;
use Hyperf\Di\Definition\DefinitionSource;
use Hyperf\Di\Definition\ScanConfig;
use HyperfTest\Di\Stub\Foo;
use HyperfTest\Di\Stub\FooInterface;
use PHPUnit\Framework\TestCase;
@ -27,7 +27,7 @@ class ContainerTest extends TestCase
{
public function testHas()
{
$container = new Container(new DefinitionSource([], [], new Scanner()));
$container = new Container(new DefinitionSource([], new ScanConfig()));
$this->assertFalse($container->has(FooInterface::class));
$this->assertFalse($container->has(NotExistClass::class));
$this->assertTrue($container->has(Foo::class));

View File

@ -12,9 +12,9 @@ declare(strict_types=1);
namespace HyperfTest\Di;
use Hyperf\Di\Annotation\Scanner;
use Hyperf\Di\Container;
use Hyperf\Di\Definition\DefinitionSource;
use Hyperf\Di\Definition\ScanConfig;
use HyperfTest\Di\Stub\Foo;
use HyperfTest\Di\Stub\FooFactory;
use PHPUnit\Framework\TestCase;
@ -27,7 +27,7 @@ class DefinitionSourceTest extends TestCase
{
public function testAddDefinition()
{
$container = new Container(new DefinitionSource([], [], new Scanner()));
$container = new Container(new DefinitionSource([], new ScanConfig()));
$container->getDefinitionSource()->addDefinition('Foo', function () {
return 'bar';
});
@ -36,7 +36,7 @@ class DefinitionSourceTest extends TestCase
public function testDefinitionFactory()
{
$container = new Container(new DefinitionSource([], [], new Scanner()));
$container = new Container(new DefinitionSource([], new ScanConfig()));
$container->getDefinitionSource()->addDefinition('Foo', FooFactory::class);
$foo = $container->get('Foo');

View File

@ -12,9 +12,9 @@ declare(strict_types=1);
namespace HyperfTest\Di;
use Hyperf\Di\Annotation\Scanner;
use Hyperf\Di\Container;
use Hyperf\Di\Definition\DefinitionSource;
use Hyperf\Di\Definition\ScanConfig;
use Hyperf\Utils\ApplicationContext;
use HyperfTest\Di\Stub\Bar;
use HyperfTest\Di\Stub\Demo;
@ -29,7 +29,7 @@ class MakeTest extends TestCase
{
public function setUp()
{
$container = new Container(new DefinitionSource([], [], new Scanner()));
$container = new Container(new DefinitionSource([], new ScanConfig()));
ApplicationContext::setContainer($container);
}

View File

@ -0,0 +1,76 @@
<?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-cloud/hyperf/blob/master/LICENSE
*/
namespace HyperfTest\Di;
use Hyperf\Config\Config;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Di\MetadataCacheCollector;
use HyperfTest\Di\Stub\AnnotationCollector;
use HyperfTest\Di\Stub\AspectCollector;
use HyperfTest\Di\Stub\DemoAnnotation;
use Mockery;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
/**
* @internal
* @coversNothing
*/
class MetadataCollectorTest extends TestCase
{
protected function tearDown()
{
AspectCollector::clear();
AnnotationCollector::clear();
}
public function testMetadataCollectorCache()
{
$annotation = DemoAnnotation::class;
$id = uniqid();
AnnotationCollector::collectClass('Demo', $annotation, new DemoAnnotation($id));
$collector = AnnotationCollector::list();
$cacher = new MetadataCacheCollector([
AnnotationCollector::class,
AspectCollector::class,
]);
$string = $cacher->serialize();
AnnotationCollector::clear();
$cacher->unserialize($string);
$collector2 = AnnotationCollector::list();
$this->assertEquals($collector, $collector2);
}
public function getContainer()
{
$container = Mockery::mock(ContainerInterface::class);
$container->shouldReceive('get')->with(ConfigInterface::class)->andReturn(new Config([
'scan' => [
'paths' => [
__DIR__,
],
'cacheable' => [
AnnotationCollector::class,
AspectCollector::class,
],
],
]));
return $container;
}
}

View File

@ -16,9 +16,9 @@ use Hyperf\Config\Config;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\NormalizerInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Scanner;
use Hyperf\Di\Container;
use Hyperf\Di\Definition\DefinitionSource;
use Hyperf\Di\Definition\ScanConfig;
use Hyperf\Di\MethodDefinitionCollector;
use Hyperf\Di\MethodDefinitionCollectorInterface;
use Hyperf\JsonRpc\DataFormatter;
@ -142,7 +142,7 @@ class RpcServiceClientTest extends TestCase
JsonRpcTransporter::class => function () use ($transporter) {
return $transporter;
},
], [], new Scanner()));
], new ScanConfig()));
ApplicationContext::setContainer($container);
return $container;
}

View File

@ -12,7 +12,9 @@ declare(strict_types=1);
namespace Hyperf\ModelListener\Collector;
class ListenerCollector
use Hyperf\Di\MetadataCollector;
class ListenerCollector extends MetadataCollector
{
/**
* User exposed listeners.
@ -21,16 +23,16 @@ class ListenerCollector
*
* @var array
*/
protected static $listeners = [];
protected static $container = [];
/**
* Register a single listener with the model.
*/
public static function register(string $model, string $listener): void
{
static::$listeners[$model] = array_unique(
static::$container[$model] = array_unique(
array_merge(
static::$listeners[$model] ?? [],
static::$container[$model] ?? [],
[$listener]
)
);
@ -38,12 +40,12 @@ class ListenerCollector
public static function setListenersForModel(string $model, array $listeners): void
{
static::$listeners[$model] = $listeners;
static::$container[$model] = $listeners;
}
public static function getListenersForModel(string $model): array
{
return static::$listeners[$model] ?? [];
return static::$container[$model] ?? [];
}
/**
@ -51,6 +53,6 @@ class ListenerCollector
*/
public static function clearListeners(): void
{
static::$listeners = [];
static::$container = [];
}
}

View File

@ -12,6 +12,8 @@ declare(strict_types=1);
namespace Hyperf\ModelListener;
use Hyperf\ModelListener\Collector\ListenerCollector;
class ConfigProvider
{
public function __invoke(): array
@ -25,6 +27,9 @@ class ConfigProvider
'paths' => [
__DIR__,
],
'collectors' => [
ListenerCollector::class,
],
],
];
}

View File

@ -12,8 +12,8 @@ declare(strict_types=1);
namespace HyperfTest\ModelListener;
use Hyperf\ModelListener\Collector\ListenerCollector;
use Hyperf\ModelListener\Annotation\ModelListener;
use Hyperf\ModelListener\Collector\ListenerCollector;
use HyperfTest\ModelListener\Stub\ModelStub;
use PHPUnit\Framework\TestCase;