kafkiansky/discovery

从应用程序自动加载类映射中查找接口、特性和类。

v0.5.0 2022-06-19 09:29 UTC

This package is auto-updated.

Last update: 2024-09-19 14:06:55 UTC


README

test Software License Total Downloads

内容

安装

composer require kafkiansky/discovery

用法

通常需要找到所有实现特定接口、继承特定类或使用特定特性的类。这些信息可以用于,例如,在IOC容器中实现自动装配。为了避免解析整个项目,可以使用autoload_classmap.php文件中的类信息,这是composer用于优化时使用的。

Class Implements

查找实现特定接口的所有类

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassImplements;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(new ClassImplements(\Stringable::class))); // discover all interfaces that implement the Stringable interface.

查找实现所有特定接口的所有类

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassImplements;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(new ClassImplements([\Stringable::class, \ArrayAccess::class])));

查找实现特定接口之一的所有类

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassImplements;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(new ClassImplements(interfaces: [\Stringable::class, \ArrayAccess::class], implementsAll: false)));

Class Extends

查找扩展特定类的所有类

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassExtends;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(new ClassExtends(\Exception::class)));

Class Uses

查找使用特定特性的所有类。此规则递归地在父特性和特性的特性中搜索所需的特性

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassUses;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(new ClassUses(SomeTrait::class)));

Class Has Attributes

查找使用特定属性的所有类。

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassHasAttributes;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(new ClassHasAttributes(SomeAttribute::class)));

全部

查找满足规则列表的所有类

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\All;
use Kafkiansky\Discovery\Rules\ClassExtends;
use Kafkiansky\Discovery\Rules\ClassImplements;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(
    new All(new ClassImplements(\Stringable::class), new ClassExtends(\Exception::class))
));

任意

查找至少满足列表中一个规则的所有类

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\Any;
use Kafkiansky\Discovery\Rules\ClassExtends;
use Kafkiansky\Discovery\Rules\ClassImplements;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(
    new Any(new ClassImplements(\Stringable::class), new ClassExtends(\Exception::class))
));

查找不满足任何规则的所有类

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\None;
use Kafkiansky\Discovery\Rules\ClassExtends;
use Kafkiansky\Discovery\Rules\ClassImplements;

$discovery = new Discovery(new ComposerClassmapClassLoader(__DIR__));

var_dump($discovery->discover(
    new None(new ClassImplements(\Stringable::class), new ClassExtends(\Exception::class))
));

加载器约束

如果您想指定可以加载的类,可以使用LoaderConstraint接口实现。默认情况下,有Kafkiansky\Discovery\CodeLocation\Composer\LoadOnlyApplicationCode类,它只加载来自您的composer.json文件中autoload.psr4部分的命名空间匹配的类。

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassImplements;
use Kafkiansky\Discovery\CodeLocation\Composer\LoadOnlyApplicationCode;

$applicationRoot = __DIR__;

$discovery = new Discovery(
    new ComposerClassmapClassLoader($applicationRoot, new LoadOnlyApplicationCode($applicationRoot))
);

var_dump($discovery->discover(new ClassImplements(\Stringable::class)));

Composer加载器

默认情况下,ComposerClassmapClassLoadervendor/composer/autoload_classmap.php路径中搜索autoload_classmap.php并强制它。如果您想传递自己的类映射加载器,可以使用withClassMapLoader方法覆盖默认加载器

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassExtends;
use Kafkiansky\Discovery\CodeLocation\Composer\LoadOnlyApplicationCode;
use Kafkiansky\Discovery\FileNotFound;

$applicationRoot = __DIR__;

$loader = new ComposerClassmapClassLoader($applicationRoot);
$loader = $loader->withClassMapLoader(function (string $path): array {
    return [FileNotFound::class => $path . '/src/FileNotFound.php'];
});

$discovery = new Discovery($loader);

var_dump($discovery->discover(new ClassExtends(\Exception::class)));

数组加载器

为了测试目的,您可以使用Kafkiansky\Discovery\CodeLocation\ArrayClassLoader

<?php

use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\Rules\ClassExtends;
use Kafkiansky\Discovery\CodeLocation\ArrayClassLoader;
use Kafkiansky\Discovery\FileNotFound;

$discovery = new Discovery(new ArrayClassLoader([
    FileNotFound::class,
]));

var_dump($discovery->discover(new ClassExtends(\Exception::class)));

性能优化

在生产中,您可能希望缓存匹配规则的类以避免不必要的检查。然后您必须使用DiscoveryWithCache

<?php

use Kafkiansky\Discovery\Cache\DiscoveryWithCache;
use Kafkiansky\Discovery\Cache\Adapter\FilesystemCache;
use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\CodeLocation\Composer\LoadOnlyApplicationCode;
use Kafkiansky\Discovery\Rules\ClassImplements;

$appPath = __DIR__;
$cacheDir = __DIR__.'/cache';

$discovery = new DiscoveryWithCache(
    new Discovery(new ComposerClassmapClassLoader($appPath), new LoadOnlyApplicationCode($appPath)),
    new FilesystemCache($cacheDir)
);

$discovery->discover(new ClassImplements(\Stringable::class));

或者,如果您想有条件地缓存,请使用cacheIf可调用函数来指定何时缓存和何时不缓存

<?php

use Kafkiansky\Discovery\Cache\DiscoveryWithCache;
use Kafkiansky\Discovery\Cache\Adapter\FilesystemCache;
use Kafkiansky\Discovery\Discovery;
use Kafkiansky\Discovery\CodeLocation\Composer\ComposerClassmapClassLoader;
use Kafkiansky\Discovery\CodeLocation\Composer\LoadOnlyApplicationCode;
use Kafkiansky\Discovery\Rules\ClassImplements;

$appPath = __DIR__;
$cacheDir = __DIR__.'/cache';

$discovery = new DiscoveryWithCache(
    new Discovery(new ComposerClassmapClassLoader($appPath), new LoadOnlyApplicationCode($appPath)),
    new FilesystemCache(directory: $cacheDir, cacheIf: function (): bool {
        return \get_env('APP_ENV') === 'production'; 
    });
);

$discovery->discover(new ClassImplements(\Stringable::class));

测试

$ composer test

许可

MIT许可(MIT)。有关更多信息,请参阅许可文件