Core/System/Discovery — Keşif motoru (bileşen/ad alanı/dosya yolu çözümü)
Doğrulanan kod tabanı:
d508f5e1(dalfeat/fw-license-master) · Tarih: 2026-10-05 · Yayın: 0.9.7 = bu commit + sonrası; belge yalnız doğrulama anındaki kodu anlatır
Kaynak klasör:Core/System/Discovery/— 24*.php.
Envanter: 24 dosyanın 24'ü aşağıda anlatıldı.
1. Ne işe yarar, kim kullanır
Framework'ün "adı verilen şeyi bul" katmanıdır. Kod service('mail'), model('user'), constant('X') ya da Definition::get('namespace','MAP') dediğinde:
- adı bir sınıf adına (FQCN) çevirir (
NamespaceResolver,ComponentContext), - bir dosya/dizin yoluna çevirir (
FolderContext,FolderResolver,AssetResolver), - sabit tanımlarını (ad alanı haritası, klasör matrisi,
DB_*anahtar eşlemesi) kategori adıyla verir (Definition/DefinitionResolver), - modül/paket (Bundle) kayıtlarını bulup rotalarını yükler (
ModuleDiscoveryDriver), - sonuçları proje dizinindeki dosya önbelleğine yazar (
DiscoveryMapper,ComponentMapper) ve açılışta proje verisini master veritabanından toplayıp önyükleme önbelleğine koyar (ProjectDataMapper).
Kimler çağırır: BaseService/BaseController/BaseModel taban sınıfları ($this->service(), ->model()…), Paths::module() (ModuleDiscoveryDriver), Kernel/Stages/* (Autoload → Definition::get), Kernel/Base/PreBoot ve Kernel/Stages/ProjectDiscovery (→ ProjectDataMapper), Config/Engine/Database/DatabaseConfig (→ Definition::get('database_project','KEYS_MAP')).
2. Klasör/dosya envanteri
2.1 Base/ — ortak soyut katman (ad alanı …\Discovery\Base)
| Dosya | Görev | Önemli yöntemler |
|---|---|---|
BaseDiscoveryContext.php |
Bütün bağlam sınıflarının atası (BaseComponent'ten türer): $this->rbn ve DiscoveryEngine::instance() bağlar; tanılama + önbellek yardımcısı. |
static setGlobalDNA(?object $rbn), protected triggerDiagnostic(string $name, string $type), protected cacheDiscovery(string $key, callable $resolver) |
BaseDiscoveryResult.php |
Bir keşif sonucunun değer nesnesi: fiziksel yol, kaynak türü, modül. | getPath(), getSourceType(), getModule(), getModifiedTime(): int |
BaseResolver.php |
DiscoveryInterface'i uygulayan soyut çözücü. |
abstract resolve(string $name, ?string $context = null): ?object |
Traits/DiscoveryActionsTrait.php |
Tür-adlı kısayol yöntemleri; hepsi resolveDiscovery($tür,$ad)'a gider. |
controller(), service(), model(), helper(), queries(), handler(), constant(), validation(), provider(), repository(), preset(), rule(), prompt(), manager(), command(), cluster(), resolver(), builder(), job(), task(), queue(), rbnEvent() (tür event), listener(), action(), rbnDriver() (tür driver) — 25 yöntem |
Traits/NamespaceExpansionTrait.php |
Kayıt defterinden gelen kısa sınıf adını tam adına tamamlar. | protected static expandRegistryResult(?string): ?string |
2.2 Engine/ — ana motor ve sürücüler
| Dosya | Görev | Yöntemler |
|---|---|---|
DiscoveryEngine.php |
Tekil (singleton) giriş kapısı: çözücüleri/sürücüleri tembel kurar, aynı anahtarın özyinelemesini kesen koruma tutar. | static instance(?object $rbn = null), resolve(object $context, string $type, ?string $name = null, bool $mandatory = true), configs(), views(), assets(), folders(), namespace(), definitions(), getResolver(string $type), getDriver(string $type), getMapper(), cluster(string $name) |
Drivers/ComponentDriver.php |
Tür+ad → örnek: NamespaceResolver::find() ile sınıfı bulur, new ile örnekler, örneği bellekte tutar. |
resolveDiscovery() (trait), private discover() |
Drivers/MetadataDriver.php |
Sınıf olmayan keşifler: constant, config, validation. |
constant($name), config($key), validation($path) |
Drivers/PathDriver.php |
Takma ada (framework, project, Paths::<ad>()) göre kök yol. |
resolve(string $alias): ?string, resolveFolder(string $key): ?string |
Drivers/ModuleDiscoveryDriver.php |
Proje modüllerini ve çatı paketlerini (ModuleData sınıfları) bulur, rotalarını yükler, bileşenleri (#[Component]) tarar. |
registerBundles(string $type = 'map', ?array $bundles = null), discoverBundles(): array, discoverComponents(string $folder): array, resolveModuleContext(string $name, string $source = 'auto'): ModuleContext, static resetMemory() |
Drivers/ModuleDataDriver.php |
Bir modülün kimlik/başlık/ikon/alt-modül bilgisini #[Bundle]/#[Module] öznitelikleri ya da CONFIG sabitinden çıkarır. |
resolveFromClass(string $bundleClass): array, getModuleInfo(string $module, string $moduleSource = 'auto'): array, deepSearch(array $tree, string $target, ?string $normalizedTarget = null): ?array |
Cache/DiscoveryMapper.php |
Çözüm haritası (anahtar → FQCN) için bellek + dosya önbelleği; kapanışta yazar. | get($key), set($key,$value), clear(): bool, saveMap(), static resetMemory() |
Cache/ComponentMapper.php |
Klasör → bileşen listesi için JSON önbelleği. | get(string $folder), set(string $folder, array $components), clear(), saveMap(), static resetMemory() |
Cache/ProjectDataMapper.php |
Açılışta proje verisini master/common/proje veritabanlarından toplar; BootCacheProvider'a yazar. |
static build(string $column, string $value, string $publicPath, string $prefix): array; sabitler MASTER_QUERIES, COMMON_QUERIES, PROJECT_QUERIES, EXTRA_CACHE_KEYS |
2.3 Clusters/ — alan çözücüleri
| Dosya | Görev | Yöntemler |
|---|---|---|
Logic/Component/ComponentContext.php |
$context nesnesi için bileşen çözer: #[SubModule] özniteliği → target<Tür> özelliği → ad; sonra NamespaceResolver ve "deterministik yol". |
resolve(object $context, string $type, ?string $targetProperty = null, bool $mandatory = true), resolveSuffix(object $context, string $name) |
Logic/Component/ComponentResolver.php |
ComponentContext'e statik ön yüz. |
static resolve(...), static resolveSuffix(...) |
Logic/Definition/Definition.php |
Definition::get(kategori, anahtar) statik kapısı; çözüm sırasında "hayatta kalma" (survival) yedeği. |
static get(string $category, string $key): mixed |
Logic/Definition/DefinitionResolver.php |
Kategori adı → sabit sınıfı eşlemesi; Core/Support/Definitions altını tarar. |
get(string $category, string $key), resolveCategory(string $category), resolve(string $name, ?string $context = null) |
Logic/Validation/ValidationResolver.php |
Core/Support/Blueprints/Validations altındaki doğrulama sabit sınıflarını kategori adıyla verir. |
get(string $category, string $key), resolveCategory(), resolve() |
Resources/AssetResolver.php |
Bir varlık yolunu proje/çatı klasörlerinde arar. | resolve(string $name, ?string $context = null), findPhysicalPath(string $path, &$detectedModule = null) |
Structure/Folder/FolderContext.php |
FolderMatrix ağacı üzerinde anahtar → klasör adı/yol çözümü. |
static name(string $key, bool $returnFull = false), static path(string $key, ?string $sub = null), static discoverDirectories(array $tree, string $prefix = ''), static recursiveSearch(...), static hasSpecializedFolder(string $namespace, string $subFolder); sabitler DATA, MODELS, MODULE_DATA |
Structure/Folder/FolderResolver.php |
Takma ad ve ad alanı → fiziksel dizin. | path(string $alias), resolveLayerDirectory(string $baseNamespace) |
Structure/Namespace/NamespaceContext.php |
Bir modülün taban ad alanı için sınıf adı üretir. | getBase(), resolveClass($layer,$className), resolveRootClass($className), resolveVariations($layer,$className), moduleDataClass() |
Structure/Namespace/NamespaceResolver.php |
(ad, tür) → FQCN: önce SystemRegistry::locate, sonra NamespaceMap::MAP taraması. |
find(string $name, string $type): ?string, resolveLayer(string $key): string |
3. Akışlar
3.1 service('x') / model('x') ... (tür-adlı çağrı)
DiscoveryActionsTrait::service($ad)→resolveDiscovery('service',$ad)(DiscoveryActionsTrait.php:32).DiscoveryEngine::resolveDiscovery()aynıtür:adanahtarı zaten çözülüyorsanulldöner (özyineleme kesici,DiscoveryEngine.php:49);constantvevalidationMetadataDriver'a, diğerleriComponentDriver'a gider (:56-59).ComponentDriver::discover()bellek önbelleğine bakar, yoksaDiscoveryEngine::instance()->namespace()->find($ad,$tür)ile FQCN'i bulur venew $class()ile örnekler (ComponentDriver.php:53).queriestürü iç anahtardaqueryolur (:30).NamespaceResolver::find()önceDiscoveryMapperönbelleğine bakar (cacheDiscovery), sonraSystemRegistry::locate($ad,$tür); bulursaNamespaceExpansionTrait::expandRegistryResult()ileRbn\Framework\/Rbn\Project\önekini tamamlar, bulamazsaresolve()→resolveCoreLayer()içindeNamespaceMap::MAP'teki her taban ad alanı için sırayla şu kalıplara bakar (NamespaceResolver.php:109):<Taban><Türler>\<Ad><Tür>·<Taban><Modül>\<Türler>\<Ad><Tür>·<Taban><Modül>\<Türler>\<Alt>\<Hedef><Tür>·…\<KlasörAdı>\<Hedef><Tür>·<Taban><Services|Tasks|UI|Frontend|Project|Master>\<Türler>\…·<Taban><Türler>\<Project|Master>\<Kök>\….
3.2 Bileşen çözümü bağlamdan (ComponentContext::resolve, ComponentContext.php:43)
Sıra: #[SubModule] özniteliğindeki $type alanı → bağlam nesnesinin target<Tür> ya da <tür> özelliği → verilen $targetProperty → NamespaceResolver::find("{tür}.{ad}") → find($ad) → calculateDeterministicPath() (bağlamın kendi ad alanından <Taban>\<Türler>\<Ad><Tür> ve kardeş <Taban>\<Ad><Tür>). Bulunursa new $fqcn(); bulunamazsa ve $mandatory ise triggerDiagnostic() ile shield()->diagnostic(...) çağrılır, null döner.
3.3 Definition::get(kategori, anahtar) (Definition.php:28)
- Çözüm sürüyorsa: kategori
namespaceiseNamespaceMap'ten yedek, değilsenull(:33-35). identitykategorisi doğrudanAssetConfig::PROXY_SETUP'tanPROXY_PATHS/PROXY_TOKENSüretir (:54-66).- Diğer kategoriler
DiscoveryEngine::instance()->definitions()->get()→DefinitionResolver::get(); sabit adıstrtoupper($anahtar); sabit yoksaget<Anahtar>statik yöntemi; hiçbiri yoksaLogicException(DefinitionResolver.php:28). - Kategori eşlemesi (
ensureDiscovery,:72-120): önce sabit dört kayıt (namespace→NamespaceMap,database_master|common|project→*DbData), sonraCore/Support/Definitionsaltındaki her*.phptaranıpgetDefinitionCategory()/$definitionCategory/ dosya adından türetilen anahtarla eklenir.
3.4 Proje verisi toplama (ProjectDataMapper::build, ProjectDataMapper.php:74)
- Master PDO ile
projectssatırı:status IN ('active','maintenance','suspended')ve{column} = ?(:85-89;$columnyalnızProjectDiscoveryiçinde sabitproject_keyya dadomainolarak verilir). MASTER_QUERIES(settings,cron_jobs), grup projeleri (project_group),COMMON_QUERIES(shield), projenin kendi DB'si (buildProjectPdo) üzerindePROJECT_QUERIES(options) çalışır; her sorgu kenditry/catch'inde hata olursa[]döner (runQueryMatrix,:167-183).assemble()(:192-326):project-routemap.phpiçindekiview_mapping[<proje>]iledashboard_prefix/admin_panel_disabled; shield ayarlarındanbot_activity,use_master_api,required_login_role,admin_panel_disabled; API anahtarları;EXTRA_CACHE_KEYS(cron_notification_emailse-posta listesi);cron_tasks.sanitizeResult()boş anahtarları atar (:337-370).- Sonuç
BootCacheProvider::set($value,$result,$publicPath,$prefix)ile yazılır; grup varsa ayrıcaDISCOVERY_PREFIX_GROUPönekiyle (:137-147). Herhangi birThrowable[]döndürür (:151-153).
3.5 Modül/paket keşfi (ModuleDiscoveryDriver)
discoverBundles() (:120-191) iki kaynaktan ModuleData sınıflarını toplar ve işlem içi önbellekler:
- Proje modülleri:
Paths::project()->module()altında<bağlam>/<modül>/Data/ModuleData.php(yoksaModels/ModuleData.php) dosyası olan her modül; sınıf adıRbn\Project\Modules\<Bağlam>\<Modül>\Data|Models\ModuleData. Anahtarlar"<bağlam>.<modül>"ve"<modül>"(küçük harf). - Çatı paketleri:
SystemRegistry::sovereignBundles()listesi; anahtarlar"<bağlam>.<ad>","<bağlam>.<adSonrasındaRbnYok>",<ad>,<adRbnYok>(bağlam = ad alanındakiBundles\<X>parçası, yoksasuite).
resolveModuleContext($ad,$kaynak='auto') (:324-343): auto iken frontend.<ad> varsa onu, yoksa backend.<ad>'ı dener; bulunamazsa düz <ad> anahtarına düşer; hiçbiri yoksa ModuleContext($temiz,'Unknown','') döner. Paths::module() bunu çağırır (Core/System/Paths/Paths.php:160).
registerBundles('routes') her benzersiz ModuleData sınıfı için Route::module($kaynak,$ad)->load() çağırır; backend kaynaklıları Route::middleware('admin')->panel('admin')->group() içine alır; frontend kaynaklı modülde proje için ayarlı module farklıysa atlar (:62-93).
4. Yapılandırma ve varsayılanlar
| Anahtar | Değer | Kaynak |
|---|---|---|
| Çözüm önbelleği dosyası | <proje>/Storage/framework/discovery_map_<proje>.php (PHP return dizisi) |
DiscoveryMapper.php:147 |
| Bileşen önbelleği dosyası | <proje>/Storage/framework/components_map_<proje>.json |
ComponentMapper.php:139 |
| Önbellek yazma zamanı | register_shutdown_function([$this,'saveMap']); yalnız isDirty iken |
DiscoveryMapper.php:101,107-110 |
| Proje PDO zaman aşımı | PDO::ATTR_TIMEOUT = 2 sn |
ProjectDataMapper.php:467 |
| Taranan bileşen kökleri | proje App, proje Core, <workspace>/Packages, <workspace>/Bundles (+ her modülün <klasör>'ü) |
ModuleDiscoveryDriver.php:213,241-269 |
| Alias → çözücü | config,configs,definition → DefinitionResolver; view → ViewResolver; asset → AssetResolver; folder; namespace; validation; bilinmeyen → NamespaceResolver |
DiscoveryEngine.php:159 |
5. Tuzaklar ve kurallar
discoverBundles()ve bileşen önbelleği süreç içinde kalıcıdır; test/CLI içinde proje değişirseModuleDiscoveryDriver::resetMemory(),DiscoveryMapper::resetMemory(),ComponentMapper::resetMemory()çağrılmalıdır.- Sınıf yüklenir, çalıştırılır:
ModuleDiscoveryDriver::processComponentFile()yalnız içinde#[Componentgeçen dosyalarırequire_onceeder;DefinitionResolver/ValidationResolveriseSupport/DefinitionsveSupport/Blueprints/Validationsaltındaki tüm*.phpdosyalarınırequire_onceeder (yan etkisiz sabit sınıfları olmaları gerekir). DiscoveryMapperanahtarları küçük harfe çevirir;nullsonuçlar önbelleğe yazılmaz (cacheDiscovery()yalnıznullolmayan değeriseteder,BaseDiscoveryContext.php:85); yüklenirken denulldeğerler süzülür (DiscoveryMapper.php:91). Önbellek okuma/yazma hatası sessizce yutulur.Definition::getbilinmeyen anahtardaLogicExceptionatar (DefinitionResolver.php:48), amaDefinitionçözüm sürerkennulldöner: hata sessiznull'a dönüşebilir.- Özyineleme kesicileri bilerek
nulldöner:DiscoveryEngine::$resolvingKeys,NamespaceResolver::$resolving,Definition::$isResolving— aynı anahtarı çözerken tekrar istenirse sonuçnull'dır, hata değildir. ProjectDataMapperçıplak SQL kullanır (§8 "DB yalnız Repository" kuralının bilinçli istisnası: Repository katmanı açılıştan sonra kurulur).projectssorgusunda yalnızstatus∈ {active,maintenance,suspended} satırlar bulunur;inactive/başka durum "proje yok" gibi görünür.DiscoveryEngine::cluster()trait'tekicluster()'ı ezer (DiscoveryEngine.php:204↔DiscoveryActionsTrait.php:146): motor üzerindecluster('x')bir çözücü döndürür, bileşen değil.ModuleDiscoveryDriver::discoverComponents()ilk ziyarette dosyaları yükler; sonuçComponentMapperile JSON'a yazılır, sonraki istekte dosya taranmaz. Yeni#[Component]ekledikten sonra önbellek dosyası silinmelidir (ComponentMapper::clear()).- Modül kökleri: keşif yalnız projenin
Modulesklasörünü (Paths::project()->module()) veSystemRegistry::sovereignBundles()listesini tarar; çatıBundles/klasörü doğrudan taranmaz (yalnızdiscoverComponentsiçin<workspace>/Bundles/<klasör>). (Eskiacik-sorular.md§2.1 birinci kısım — kodla çözüldü.) - Proje rota dosyası yükletmek:
Definition::get('route','FILES')→RouteBlueprint::FILES(definitionCategory='route',Core/Support/Definitions/Route/RouteBlueprint.php:19,57-64);'project'listesi boştur.Route::loadRoutes()bu listedeki her dosya adı içinPaths::project()->routes()/<ad>.phpvarsarequire_onceeder (Core/Routes/Route.php:265); yoksa sessizce atlar. Yani ekleme yeriRouteBlueprint::FILES['project'](çatı kodu) — proje başına ayarlanabilir bir yol yoktur. (Eskiacik-sorular.md§2.1 ikinci kısım.)
6. Örnek (gerçek koddan)
// Core/System/Kernel/Stages/Autoload.php:41,50
$projectPrefix = Definition::get('namespace', 'PROJECT_PREFIX') ?: 'Rbn\Project\\';
$frameworkPrefix = Definition::get('namespace', 'FRAMEWORK_PREFIX') ?: 'Rbn\Framework\\';
// Core/System/Config/Engine/Database/DatabaseConfig.php:71
$map = Definition::get($category, 'KEYS_MAP'); // $category = 'database_project'
7. İlgili belgeler
- Core/System genel bakış · Kernel · Paths · Registries · Storage
- Support/Definitions (
NamespaceMap,FolderMatrix,ComponentTypes,RouteBlueprint) - Kavram: mimari harita · Açık sorular