|
| 1 | +# LibReflect Incubator |
| 2 | + |
| 3 | +`LibReflect` is not an official standalone package yet. |
| 4 | + |
| 5 | +EasyLibrary 3.0-dev now has a small internal incubator under: |
| 6 | + |
| 7 | +```text |
| 8 | +imperazim\library\reflect |
| 9 | +``` |
| 10 | + |
| 11 | +The goal is to validate whether a future `LibReflect` should exist without |
| 12 | +turning reflection into hidden framework magic. |
| 13 | + |
| 14 | +## Why This Exists |
| 15 | + |
| 16 | +Several parts of the ecosystem already need cautious reflection: |
| 17 | + |
| 18 | +- package entry classes need existence and constructor checks; |
| 19 | +- module loaders need to validate module classes; |
| 20 | +- provider diagnostics need to identify class file ownership; |
| 21 | +- plugin migration tools may need controlled class metadata; |
| 22 | +- optional attributes can reduce boilerplate when used explicitly. |
| 23 | + |
| 24 | +Those are legitimate cases. The risky part is uncontrolled auto-discovery, |
| 25 | +global class scans and silent instantiation. The incubator intentionally avoids |
| 26 | +those patterns. |
| 27 | + |
| 28 | +## Current Experimental Pieces |
| 29 | + |
| 30 | +| Class | Role | |
| 31 | +|---|---| |
| 32 | +| `ClassInspector` | Entry point for inspecting one class/interface/trait name. | |
| 33 | +| `ClassInspection` | Read-only snapshot of class metadata, attributes and safe instantiation. | |
| 34 | +| `ClassContract` | Fluent validation for inheritance, interfaces and instantiability. | |
| 35 | +| `ClassContractResult` | Validation result with errors and structured output. | |
| 36 | +| `ClassFactory` | Small helper for instantiating only validated, instantiable classes. | |
| 37 | + |
| 38 | +All of these are `@experimental`. |
| 39 | + |
| 40 | +## Example |
| 41 | + |
| 42 | +```php |
| 43 | +use imperazim\library\reflect\ClassContract; |
| 44 | +use imperazim\library\reflect\ClassFactory; |
| 45 | +use imperazim\module\BaseModule; |
| 46 | + |
| 47 | +$contract = ClassContract::for($className) |
| 48 | + ->mustExtend(BaseModule::class) |
| 49 | + ->mustBeInstantiable() |
| 50 | + ->validate(); |
| 51 | + |
| 52 | +if (!$contract->isOk()) { |
| 53 | + foreach ($contract->getErrors() as $error) { |
| 54 | + $logger->warning($error); |
| 55 | + } |
| 56 | + return; |
| 57 | +} |
| 58 | + |
| 59 | +$module = ClassFactory::newInstance($className, [$plugin, $config]); |
| 60 | +``` |
| 61 | + |
| 62 | +## Attribute Example |
| 63 | + |
| 64 | +```php |
| 65 | +use Attribute; |
| 66 | +use imperazim\library\reflect\ClassInspector; |
| 67 | + |
| 68 | +#[Attribute(Attribute::TARGET_CLASS)] |
| 69 | +final class FeatureInfo { |
| 70 | + public function __construct(public string $id) {} |
| 71 | +} |
| 72 | + |
| 73 | +#[FeatureInfo('economy')] |
| 74 | +final class EconomyFeature {} |
| 75 | + |
| 76 | +$inspection = ClassInspector::inspect(EconomyFeature::class); |
| 77 | +$info = $inspection->newAttributeInstances(FeatureInfo::class)[0] ?? null; |
| 78 | +``` |
| 79 | + |
| 80 | +## Rules |
| 81 | + |
| 82 | +- Inspect explicit class names only. |
| 83 | +- Do not scan all declared classes by default. |
| 84 | +- Do not recursively scan arbitrary source directories in runtime code. |
| 85 | +- Do not instantiate classes unless a contract has passed. |
| 86 | +- Do not hide runtime behavior behind attributes without a visible registration |
| 87 | + path. |
| 88 | +- Prefer normal `use` imports and explicit PHP code when reflection does not |
| 89 | + remove real duplication. |
| 90 | + |
| 91 | +## Candidate Uses |
| 92 | + |
| 93 | +| Area | Candidate use | |
| 94 | +|---|---| |
| 95 | +| Module loader | Replace ad-hoc `ReflectionClass` checks for module class validation. | |
| 96 | +| Package entry loader | Standardize zero-argument or host-argument entry instantiation checks. | |
| 97 | +| Provider diagnostics | Standardize file/class metadata reporting. | |
| 98 | +| Command tooling | Optional explicit attributes for command metadata if it reduces boilerplate. | |
| 99 | +| Migration/debug docs | Safer class metadata output for diagnostics and reports. | |
| 100 | + |
| 101 | +## What This Does Not Promise |
| 102 | + |
| 103 | +This incubator is not: |
| 104 | + |
| 105 | +- a dependency injection container; |
| 106 | +- a global class scanner; |
| 107 | +- an annotation framework; |
| 108 | +- an automatic command/module loader; |
| 109 | +- a replacement for explicit package/module manifests; |
| 110 | +- a stable public API yet. |
| 111 | + |
| 112 | +## Graduation Criteria |
| 113 | + |
| 114 | +Only create `LibReflect` as an official repository if the incubator proves all |
| 115 | +of these: |
| 116 | + |
| 117 | +- at least two real EasyLibrary/libs call sites become smaller or safer; |
| 118 | +- no runtime path depends on scanning all classes; |
| 119 | +- docs define which metadata can be used in production; |
| 120 | +- tests cover missing classes, abstract classes, inheritance, interfaces, |
| 121 | + attributes and instantiation; |
| 122 | +- migration docs explain when not to use reflection; |
| 123 | +- release/package assets follow the same official lib standard as |
| 124 | + `LibCommons`, `LibHttp` and `LibAssets`. |
| 125 | + |
| 126 | +Until then, this stays inside EasyLibrary as a 3.0-dev experiment. |
0 commit comments