Core/Database — bağlantı yönetimi, sorgu motoru, model ve repository katmanı
Doğrulanan kod tabanı:
1d89c431(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/Database/— 74*.php.
Envanter: 74 dosyanın 74'ü aşağıda anlatıldı (alt dal belgelerinde dağınık).
1. Ne işe yarar, kim kullanır
Framework'ün veri katmanıdır. Üç katmanı vardır ve katmanlar arasına
taşmak kuraldır:
| Katman | Soyut sınıf | Görev |
|---|---|---|
| Bağlantı | Database (singleton) |
database_project / database_master / database_common bağlantılarını yönetir, PDO verir, transaction açar |
| Sorgu | QueryBuilder (+ 7 query trait'i) |
SQL üretimi; Database üzerinde kendi bağlantısında çalışır |
| Veri | BaseModel / BaseRepository |
Sorgu builder'ı sarmalar; model satır, repository iş kuralıdır |
Anayasa §8 gereği yalnız Repository katmanı doğrudan SQL yazabilir;
model katmanı şemaya değil, hazır builder API'sine dayanır.
Kimler çağırır: Core/Base/Data/BaseModel, tüm Core/Services ve
Bundles/* repository/model sınıfları, CLI handler'ları (rbn db:*).
2. Klasör/dosya envanteri
Tam dosya listesi ve her dosyanın tek cümlelik görevi alt dal belgelerindedir:
| Alt dal belge | Kapsam | Dosya sayısı |
|---|---|---|
| Engine.md | Database.php, Engine/ (Collection, Providers, Traits, Traits/Query) |
16 |
| Models.md | Models/ (kök + Common + Master + Project) |
34 |
| Repositories.md | Repositories/ (Common + Master + Project) |
20 |
| Migrations.md | Migrations/ (Master + Tenant) |
3 |
Services/DatabaseService.php |
(aşağıda, bu belge) | 1 |
| Toplam | 74 |
Bu ana belgese ait tek dosya:
| Dosya | Görev | Önemli public yöntemler |
|---|---|---|
Services/DatabaseService.php |
Panelin/CLI'nin veritabanı yönetim yüzü: tablo listesi, satır gösterme, satır silme, optimize, collation dönüşümü, SQL dışa aktarım, temiz kurulum, admin seed. | static get(): self, table(string $name): self, entire(): self, getDashboardInfo(): array, optimize(): bool, convert(string $collation='utf8mb4_unicode_ci'): array, cleanInstall(): bool, seedAdmin(): bool, executeQuery(string $sql): array, getTableContent(string $table,int $limit=100): array, getTables(): array, getRows(?string $table=null,int $limit=100): array, getTableMetadata(?string $table=null): array, deleteRow(?string $table=null,$id=null): bool, bulkDeleteRows(?string $table=null,array $ids=[]): bool, dropTable(?string $table=null): bool, changeTableCollation(?string $table=null,string $collation=...): bool, exportTableSql(?string $table=null,?array $ids=null): string, sanitizeTableName(string $table): string (protected) |
3. Akış — bir model okumasından satıra
Controller/Service → $this->model('project.user')->where(...)->get()
├─ BaseComponent::__get('user'/'model') → component('model', …) keşif motoru BaseComponent.php:194
│ → Core/Base/Data/BaseModel örneği
├─ BaseModel::__construct() → BaseComponent → bootBaseContext() BaseModel.php:210
└─ QueryModelTrait::query() QueryModelTrait.php:44
├─ logModelScopeVisibility() (LOG-ONLY ölçüm) :49
├─ new QueryBuilder($this->db, $this->table) :67
├─ $builder->connection($this->connection) :71-73
├─ $builder->setModelClass(static::class) :77-79
└─ $scoped ise → where(project_key, aktif) veya whereIn(..., projectScopeIncludes) :88-108
(aktif anahtar boşsa kapsam UYGULANMAZ)
└─ where/orderBy/limit... → get()
└─ Query\ExecutionTrait::get() ExecutionTrait.php:17
└─ onConnection(fn) → Database::connectionScoped($connectionName, …) QueryBuilder.php:97
└─ Database::query()/raw()/execute() ExecutionTrait.php:46,131,151
└─ ConnectionTrait::getProvider($name) → MySqlProvider → getPdo() MySqlProvider.php:60
Yazma yolu aynıdır; ayrıca MassAssignmentTrait süzgeci
(create/update/save üzerinden) devreye girer.
4. Yapılandırma / ayar anahtarları
| Anahtar / sabit | Yer | Not |
|---|---|---|
KNOWN_CONNECTIONS |
ConnectionTrait.php:29 |
database_project, database_master, database_common |
CONNECTION_ALIASES |
ConnectionTrait.php:43 |
default → database_project |
security.mass_assignment |
MassAssignmentTrait.php:42 |
on|enforce zorlar; diğer her şey off (varsayılan on) |
security.protected_field_log |
MassAssignmentTrait.php:50 |
on → korumalı alan denemesi loglanır |
security.model_not_scoped_log |
QueryModelTrait.php:39 |
on → kapsam dışı model görünürlük logu (saatlik) |
MASTER_DB_* / DB_* ortam anahtarları |
MasterDbData::KEYS_MAP, ProjectDbData::KEYS_MAP |
Değerler Secrets üzerinden gelir |
MasterDbData::REQUIRED_TABLES |
MasterDbData.php:54 |
developers, ip_whitelist, ip_blocks, projects, z_sys_heartbeats |
5. Tuzaklar ve kurallar
- Geçersiz bağlantı adı istisna atar (fail-closed).
MySqlProvider'ın
önceki "bilinmeyen her adı sessizcedatabase_project'e düşür" davranışı
kaldırıldı; artıknormalizeConnectionName()InvalidArgumentException
atar (ConnectionTrait.php:68). Geriye uyum yalnızdefaultalias'ıyla. defaultvedatabase_projectaynı sağlayıcıyı paylaşır — aynı
veritabanına iki PDO açılmaz (ConnectionTrait.php:43).- Sorgu kendi bağlantısında çalışır, global durum kirlenmez.
QueryBuilder::onConnection()→Database::connectionScoped()
(QueryBuilder.php:97,ConnectionTrait.php:123). - Boş proje bağlamında kapsam uygulanmaz.
$activeKey === ''iken
where('project_key','')yazmak tüm tabloyu sıfıra indirirdi; bu yüzden
kapsam atlanır (QueryModelTrait.php:90). - Kiraci izolasyonu varsayılanı KAPALI.
BaseModel::$scoped = false
(BaseModel.php:57); her model kendi kararını dosyasında yazar
(@tenant-scopeetiketiyle). Açmak 7 veritabanında kırılma ölçülmüştür. - PDO, ayar değiştiğinde düşürülür.
getPdo()her çağrıdaConfig'i
okur; host/veritabanı/kullanıcı/parola farklıysa bağlantı yenilenir
(MySqlProvider.php:60). - CLI'da ölü bağlantı yoklanır. 10 sn'den eskiyse
SELECT 1atılır;
PDOExceptionyetmez,Throwableyakalanır (MySqlProvider.php:81). SchemaDoctorModeltablosuzdur.getTable(): stringyerine
getTableOrNull()kullanılmalıdır (strict_typesaltındanulldönmek
TypeError'dir) (SchemaDoctorModel.php:11).- İç içe transaction dış yüzeyi kullanmaz.
Database::transaction()
zaten transaction içindeyse içeriği çalıştırır ve commit/rollback yapmaz
(Database.php:57). - Sıfırlama API'leri yalnız test içindir.
BaseService::forgetInstance(),
StorageContextTrait::forgetStorage()üretimde çağrılmaz.
6. Örnek (gerçek koddan)
Repository katmanından okuma/yazma (Repositories/Project/UserRepository.php
imzası):
$user = $this->repository('project.user')->findByIdentity('ornek@site.example');
$ok = $this->repository('project.user')->updatePassword($id, $hash, 'user');
Model katmanında kiracı kapsamını daraltma (QueryModelTrait.php:88):
$model = $this->model('project.user')->withProjectScope('proje-anahtari');
$rows = $model->where('is_active', 1)->orderBy('id', 'DESC')->limit(20)->get();
7. İlgili belgeler
- ../Base/Data.md —
BaseModel/BaseRepositoryve tüm trait'ler - ../System/Config.md — bağlantı ayarlarının tek okuyucusu
- ../../kavramlar/03-veritabani-ve-kiracilik.md — bağlantı aileleri ve kiracılık
- ../../acik-sorular.md §1.2 / §3 (heartbeat tablosu)