fields

package
v0.0.0-...-83c8914 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 22, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package fields, admin panel için alan (field) tanımlamalarını sağlar.

Bu dosya, core paketinden type alias'ları içe aktarır ve fields paketinde kullanılabilir hale getirir. Bu sayede fields paketi, core paketine doğrudan bağımlı olmadan temel tipleri kullanabilir.

Alan Bağımlılık Çözücü Paketi

Bu paket, form alanları arasındaki bağımlılıkları yönetir ve çözer. Bir alanın değeri değiştiğinde, ona bağımlı diğer alanların otomatik olarak güncellenmesini sağlar.

## Temel Özellikler

- **Bağımlılık Grafiği**: Alanlar arası bağımlılık ilişkilerini graf yapısında tutar - **Otomatik Güncelleme**: Değişen alanlara bağlı tüm alanları otomatik günceller - **Döngüsel Bağımlılık Tespiti**: Sonsuz döngülere neden olabilecek bağımlılıkları tespit eder - **BFS/DFS Algoritmaları**: Etkin graf traversal algoritmaları kullanır

## Kullanım Senaryoları

1. **Cascade Seçimler**: Ülke seçildiğinde şehir listesinin güncellenmesi 2. **Koşullu Alanlar**: Bir checkbox işaretlendiğinde ilgili alanların gösterilmesi 3. **Dinamik Validasyon**: Bir alanın değerine göre diğer alanların validasyon kurallarının değişmesi 4. **Hesaplanan Alanlar**: Birden fazla alanın değerine göre otomatik hesaplama yapılması

## Örnek Kullanım

```go // Bağımlılık çözücü oluştur resolver := NewDependencyResolver(fields, "form")

// Döngüsel bağımlılık kontrolü

if err := resolver.DetectCircularDependencies(); err != nil {
    log.Fatal(err)
}

// Değişen alanlar için bağımlılıkları çöz updates, err := resolver.ResolveDependencies(formData, []string{"country"}, ctx)

if err != nil {
    log.Fatal(err)
}

```

Package fields, admin panel için alan (field) tanımlamalarını sağlar.

Bu dosya, core paketinden type alias'ları ve constant'ları içe aktarır. Bu sayede fields paketi, core paketine doğrudan bağımlı olmadan temel tipleri kullanabilir.

Package fields, alan davranışlarını birleştirilebilir hale getiren mixin'leri sağlar.

Bu paket, alanlara modüler işlevsellik eklemek için mixin pattern (kompozisyon) uygular. Her mixin, alan türlerine gömülebilen belirli bir yetenek sağlar.

Mevcut Mixin'ler

- Searchable: Alanların özel arama mantığı ile aranabilir olmasını sağlar - Sortable: Alanların özel sıralama mantığı ile sıralanabilir olmasını sağlar - Filterable: Alanların özel filtreleme mantığı ile filtrelenebilir olmasını sağlar - Validatable: Alanların doğrulama kuralları ve özel doğrulayıcılara sahip olmasını sağlar - Displayable: Alanların görüntüleme formatını özelleştirmesini sağlar - Hideable: Alanların farklı bağlamlarda görünürlüğünü kontrol etmesini sağlar

Kullanım Örneği

type CustomField struct {
    fields.Base
    fields.Searchable
    fields.Sortable
}

field := &CustomField{}
field.SetSearchableColumns([]string{"name", "email"})
field.SetSortable(true)

Mimari

Mixin'ler, Go Panel API mimarisinde önerilen kompozisyon pattern'ini takip eder. Kalıtım olmadan yeniden kullanılabilir işlevsellik sağlarlar, bu da tek bir alan türünde birden fazla yeteneği birleştirmeyi kolaylaştırır.

Daha fazla bilgi için docs/Fields.md ve .docs/ARCHITECTURE.md dosyalarına bakın.

Package fields, veritabanı ilişkilerini alan sisteminde temsil eden yapıları sağlar.

Bu dosya, ilişki alanlarının (BelongsTo, HasMany, HasOne, BelongsToMany, MorphTo) temel interface'lerini ve tiplerini tanımlar.

İlişki Türleri

- **BelongsTo**: Ters one-to-one veya one-to-many ilişki (bir Post bir Author'a aittir) - **HasMany**: One-to-many ilişki (bir Author birden fazla Post'a sahiptir) - **HasOne**: One-to-one ilişki (bir User bir Profile'a sahiptir) - **BelongsToMany**: Many-to-many ilişki (bir User birden fazla Role'e sahiptir) - **MorphTo**: Polimorfik ilişki (bir Comment farklı tiplere ait olabilir)

Yükleme Stratejileri

- **Eager Loading**: N+1 sorgu problemini önler, ilişkili verileri önceden yükler - **Lazy Loading**: İhtiyaç anında yükler, bellek tasarrufu sağlar

Kullanım Örneği

// BelongsTo ilişkisi
field := fields.NewBelongsTo("Author", "author_id", "authors").
    DisplayUsing("name").
    WithSearchableColumns("name", "email").
    WithEagerLoad()

// HasMany ilişkisi
field := fields.NewHasMany("Posts", "posts", "posts").
    ForeignKey("author_id").
    WithEagerLoad()

Daha fazla bilgi için docs/Relationships.md ve .docs/RESOURCE_BASED_RELATIONSHIPS.md dosyalarına bakın.

Package fields, ilişkisel alanlar için kısıtlama (constraint) yönetimi sağlar.

Bu paket, relationship field'ları üzerinde sorgu kısıtlamaları uygulamak için gerekli interface ve implementasyonları içerir. LIMIT, OFFSET, WHERE ve WHERE IN gibi SQL kısıtlamalarını yönetir.

Referans

Detaylı kullanım ve örnekler için: docs/Relationships.md(../../docs/Relationships.md)

Package fields, ilişkisel veritabanı alanları için sayma (counting) işlevselliği sağlar.

Bu paket, farklı ilişki türleri (BelongsTo, HasMany, HasOne, BelongsToMany, MorphTo) için ilişkili kaynak sayılarını hesaplamak üzere tasarlanmıştır.

Desteklenen İlişki Türleri

- `belongsTo`: 0 veya 1 döner (tekil ilişki) - `hasOne`: 0 veya 1 döner (tekil ilişki) - `hasMany`: İlişkili kaynak sayısını döner (çoğul ilişki) - `belongsToMany`: Pivot tablo kayıt sayısını döner (çoktan-çoğa ilişki) - `morphTo`: 0 veya 1 döner (polimorfik ilişki)

Referanslar

Detaylı ilişki dokümantasyonu için: `docs/Relationships.md`

Package fields, ilişkisel veritabanı alanları için varlık kontrolü işlevselliği sağlar.

Bu paket, relationship field'ların ilişkili kaynaklarının var olup olmadığını kontrol etmek için kullanılan interface ve implementasyonları içerir.

Desteklenen İlişki Tipleri

- `belongsTo`: Ters bire-bir veya bire-çok ilişki - `hasMany`: Bire-çok ilişki - `hasOne`: Bire-bir ilişki - `belongsToMany`: Çoka-çok ilişki (pivot tablo üzerinden) - `morphTo`: Polimorfik ilişki

Referans

Detaylı bilgi için bkz: `docs/Relationships.md`

Package fields, ilişkisel veritabanı alanları ve sayfalama işlevselliği sağlar.

Bu paket, ilişkili kayıtlar için sayfalama yönetimi ve metadata işlemlerini içerir. Sayfa numarası, sayfa boyutu ve toplam kayıt sayısı gibi bilgileri yönetir.

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

Package fields, ilişki serileştirme işlemlerini yönetir.

Bu paket, relationship field'larının JSON formatına dönüştürülmesi için gerekli interface ve implementasyonları sağlar.

Referans

Detaylı bilgi için: docs/Relationships.md(../../docs/Relationships.md)

Package fields, ilişkisel alan (relationship field) doğrulama işlemlerini yönetir.

Bu paket, veritabanı ilişkilerinin (BelongsTo, HasMany, HasOne, BelongsToMany, MorphTo) doğrulanması için gerekli validator implementasyonlarını sağlar.

İlişki Tipleri

- **BelongsTo**: Bir kaydın başka bir kayda ait olduğu ilişki - **HasMany**: Bir kaydın birden fazla ilişkili kayda sahip olduğu ilişki - **HasOne**: Bir kaydın tek bir ilişkili kayda sahip olduğu ilişki - **BelongsToMany**: Çoka-çok ilişki (pivot tablo ile) - **MorphTo**: Polimorfik ilişki (birden fazla model tipine bağlanabilir)

Referans

Detaylı ilişki dokümantasyonu için: `docs/Relationships.md`

Örnek Kullanım

```go validator := fields.NewRelationshipValidator()

// BelongsTo ilişkisini doğrula err := validator.ValidateBelongsTo(ctx, userID, belongsToField)

if err != nil {
    log.Printf("İlişki doğrulama hatası: %v", err)
}

// MorphTo ilişkisini doğrula err = validator.ValidateMorphTo(ctx, morphValue, morphToField)

if err != nil {
    log.Printf("Polimorfik ilişki hatası: %v", err)
}

```

Package fields, test senaryoları için yardımcı fonksiyonlar ve yapılar sağlar.

Bu paket, field sisteminin test edilmesi için gerekli olan veritabanı bağlantıları, test verileri ve model yapılarını içerir. SQLite in-memory veritabanı kullanarak hızlı ve izole test ortamları oluşturur.

Temel Özellikler

- In-memory SQLite veritabanı desteği - Otomatik tablo oluşturma ve veri doldurma - İlişkisel veri modelleri (HasOne, HasMany, BelongsTo, BelongsToMany, MorphTo) - Test için hazır örnek veriler

Kullanım Senaryoları

- Unit testlerde veritabanı bağlantısı gerektiğinde - İlişkisel sorguların test edilmesinde - Field sisteminin entegrasyon testlerinde - Performans testlerinde tutarlı veri seti oluşturmada

Örnek Kullanım

```go

func TestMyFeature(t *testing.T) {
    // Test veritabanı oluştur
    testDB := NewTestDB(t)
    defer testDB.Close()

    // Veritabanını kullan
    var users []User
    testDB.DB.Query("SELECT * FROM users")
}

```

Package fields, admin panel için alan (field) tanımlamalarını sağlar.

Bu dosya, alan doğrulama (validation) sistemini içerir. Alanlar için çeşitli doğrulama kuralları tanımlanabilir ve bu kurallar form gönderildiğinde otomatik olarak çalıştırılır.

Index

Constants

This section is empty.

Variables

DefaultCurrencies, money field için önerilen başlangıç para birimi listesidir.

Functions

func ApplyConditionalValidation

func ApplyConditionalValidation(validator ConditionalValidator, value interface{}, context interface{}) error

ApplyConditionalValidation applies a validator only if condition is met

func ApplyCustomValidator

func ApplyCustomValidator(name string, value interface{}, context interface{}) error

ApplyCustomValidator applies a global custom validator

func ApplyValidationRule

func ApplyValidationRule(rule ValidationRule, value interface{}) error

ApplyValidationRule applies a validation rule to a value

func GetTestDataDir

func GetTestDataDir() string

GetTestDataDir, test verileri için geçici dizin yolunu döndürür.

Bu fonksiyon, test sırasında geçici dosyaların saklanması gereken dizin yolunu sağlar. İşletim sisteminin standart geçici dizinini kullanır.

Dönüş Değeri

İşletim sisteminin geçici dizin yolunu string olarak döndürür. - Unix/Linux/macOS: Genellikle `/tmp` - Windows: Genellikle `C:\Users\<username>\AppData\Local\Temp`

Kullanım Senaryoları

- Test sırasında geçici dosya oluşturma - Test verilerini diske yazma - Dosya yükleme testleri - Önbellek testleri

Önemli Notlar

- **Geçici Dizin**: Döndürülen dizin işletim sistemi tarafından yönetilir - **Temizlik**: Test sonunda oluşturulan dosyaları manuel olarak temizlemek gerekebilir - **İzinler**: Geçici dizine yazma izni genellikle mevcuttur - **Çakışma**: Benzersiz dosya adları kullanarak çakışmaları önleyin

Örnek Kullanım

```go

func TestFileUpload(t *testing.T) {
    testDir := GetTestDataDir()
    testFile := filepath.Join(testDir, "test_upload.txt")

    // Test dosyası oluştur
    err := os.WriteFile(testFile, []byte("test data"), 0644)
    if err != nil {
        t.Fatal(err)
    }
    defer os.Remove(testFile) // Temizlik

    // Test kodunuz...
}

// Benzersiz dosya adı ile kullanım

func TestWithUniqueFile(t *testing.T) {
    testDir := GetTestDataDir()
    testFile := filepath.Join(testDir, fmt.Sprintf("test_%d.txt", time.Now().UnixNano()))

    // Test kodunuz...
}

```

func RegisterCustomValidator

func RegisterCustomValidator(name string, validator ValidatorFunc)

RegisterCustomValidator registers a global custom validator

func ValidateEmail

func ValidateEmail(value interface{}) error

ValidateEmail, e-posta formatını doğrular.

Bu fonksiyon, RFC 5322 standardına uygun e-posta adresi formatını kontrol eder. Boş string geçerli sayılır (zorunluluk için Required() kullanın).

Parametreler

- **value**: Doğrulanacak değer (string olmalı)

Kullanım Örneği

err := fields.ValidateEmail("[email protected]")  // nil
err := fields.ValidateEmail("invalid-email")     // error: "invalid email format"
err := fields.ValidateEmail("")                  // nil (boş geçerli)

Döndürür:

  • nil: E-posta formatı geçerli veya boş
  • error: E-posta formatı geçersiz veya tip uyumsuz

func ValidateMax

func ValidateMax(value interface{}, max interface{}) error

ValidateMax validates maximum value

func ValidateMaxLength

func ValidateMaxLength(value interface{}, length int) error

ValidateMaxLength validates maximum string length

func ValidateMin

func ValidateMin(value interface{}, min interface{}) error

ValidateMin validates minimum value

func ValidateMinLength

func ValidateMinLength(value interface{}, length int) error

ValidateMinLength validates minimum string length

func ValidatePattern

func ValidatePattern(value interface{}, pattern string) error

ValidatePattern validates regex pattern matching

func ValidateRequired

func ValidateRequired(value interface{}) error

ValidateRequired, bir değerin boş olmadığını doğrular.

Bu fonksiyon, değerin nil, boş string, boş slice olmadığını kontrol eder. Farklı veri tipleri için farklı boşluk kontrolleri yapar.

Parametreler

- **value**: Doğrulanacak değer (interface{})

Desteklenen Tipler

- **nil**: Hata döndürür - **string**: Boşluk karakterleri temizlendikten sonra boş string kontrolü - **[]interface{}**: Boş slice kontrolü - **[]string**: Boş string slice kontrolü

Kullanım Örneği

err := fields.ValidateRequired("test")  // nil
err := fields.ValidateRequired("")      // error: "value is required"
err := fields.ValidateRequired(nil)     // error: "value is required"

Döndürür:

  • nil: Değer geçerli
  • error: Değer boş

func ValidateURL

func ValidateURL(value interface{}) error

ValidateURL validates URL format

Types

type BelongsToField

type BelongsToField struct {
	Schema
	RelatedResourceSlug string
	RelatedResource     interface{} // resource.Resource interface (interface{} to avoid circular import)
	DisplayKey          string
	SearchableColumns   []string
	QueryCallback       func(query interface{}) interface{}
	LoadingStrategy     LoadingStrategy
	GormRelationConfig  *RelationshipGormConfig
	// contains filtered or unexported fields
}

BelongsToField, ters one-to-one ilişkiyi temsil eder (örn. Post -> Author).

BelongsTo ilişkisi, bir kaydın başka bir kayda ait olduğunu belirtir. Bu, veritabanında foreign key ile temsil edilir.

Kullanım Senaryoları

- **Post -> Author**: Bir yazı bir yazara aittir - **Comment -> User**: Bir yorum bir kullanıcıya aittir - **Order -> Customer**: Bir sipariş bir müşteriye aittir

Özellikler

- **Tip Güvenliği**: Resource instance veya string slug kullanılabilir - **Otomatik Seçenekler**: AutoOptions ile veritabanından otomatik seçenek yükleme - **Arama Desteği**: İlişkili kayıtlarda arama yapabilme - **Eager/Lazy Loading**: Yükleme stratejisi seçimi - **GORM Yapılandırması**: Foreign key ve references özelleştirme - **Hover Card**: Index ve detail sayfalarında hover card desteği

Kullanım Örneği

// String slug ile
field := fields.BelongsTo("Author", "author_id", "authors").
    DisplayUsing("name").
    WithSearchableColumns("name", "email").
    AutoOptions("name").
    WithEagerLoad()

// Resource instance ile (tip güvenli)
field := fields.BelongsTo("Author", "author_id", blog.NewAuthorResource()).
    DisplayUsing("name").
    WithSearchableColumns("name", "email").
    AutoOptions("name").
    WithEagerLoad()

// Hover card ile
field := fields.BelongsTo("Author", "author_id", "authors").
    DisplayUsing("name").
    WithHoverCard(fields.NewHoverCardConfig().
        WithAvatar("avatar", "").
        WithGrid([]fields.HoverCardGridField{
            {Key: "email", Label: "Email", Type: "email", Icon: "mail"},
            {Key: "role", Label: "Rol", Type: "badge"},
        }, "2-column"))

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func BelongsTo

func BelongsTo(name, key string, relatedResource interface{}) *BelongsToField

BelongsTo, yeni bir BelongsTo ilişki alanı oluşturur.

Bu fonksiyon, hem string slug hem de resource instance kabul eder. Resource instance kullanımı tip güvenliği sağlar ve refactoring'i kolaylaştırır.

Parametreler

- **name**: Alanın görünen adı (örn. "Author", "Yazar") - **key**: Foreign key sütun adı (örn. "author_id") - **relatedResource**: İlgili resource (string slug veya resource instance)

String Slug Kullanımı

field := fields.BelongsTo("Author", "author_id", "authors")

**Avantajlar:** - Basit ve hızlı - Circular import sorunu yok

**Dezavantajlar:** - Tip güvenliği yok - Refactoring zor - IDE desteği sınırlı

Resource Instance Kullanımı (Önerilen)

field := fields.BelongsTo("Author", "author_id", blog.NewAuthorResource())

**Avantajlar:** - ✅ Tip güvenliği (derleme zamanı kontrolü) - ✅ Refactoring desteği (resource adı değişirse otomatik güncellenir) - ✅ IDE desteği (autocomplete, go-to-definition) - ✅ Tablo adı otomatik alınır (resource.Slug())

**Dezavantajlar:** - Circular import'a dikkat edilmeli

Varsayılan Değerler

- **DisplayKey**: "name" (görüntüleme için kullanılacak alan) - **SearchableColumns**: ["name"] (aranabilir sütunlar) - **LoadingStrategy**: EAGER_LOADING (N+1 sorgu problemini önler) - **Foreign Key**: key parametresi (örn. "author_id") - **References**: "id" (ilgili tablonun primary key'i)

Döndürür:

  • Yapılandırılmış BelongsToField pointer'ı

Daha fazla bilgi için docs/Relationships.md ve .docs/RESOURCE_BASED_RELATIONSHIPS.md dosyalarına bakın.

func (*BelongsToField) AutoOptions

func (b *BelongsToField) AutoOptions(displayField string) *BelongsToField

AutoOptions, ilgili tablodan otomatik seçenek oluşturmayı etkinleştirir.

Bu metod, backend'in veritabanından otomatik olarak tüm kayıtları çekip form elemanları (Combobox/Select) için seçenekler oluşturmasını sağlar. Manuel olarak Options callback'i tanımlamaya gerek kalmaz.

Parametreler

- **displayField**: Seçenek etiketi için kullanılacak sütun adı (örn. "name", "title", "email")

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors").
    AutoOptions("name")
// Backend otomatik olarak authors tablosundan tüm kayıtları çeker
// ve "name" sütununu etiket olarak kullanır

Önemli Notlar

- AutoOptions kullanıldığında, backend otomatik olarak ilgili tablodan tüm kayıtları çeker - Büyük tablolar için performans sorunu olabilir, bu durumda Query() ile filtreleme yapılmalıdır - displayField, ilgili tabloda mevcut bir sütun olmalıdır

Döndürür:

  • BelongsToField pointer'ı (method chaining için)

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func (*BelongsToField) DisplayUsing

func (b *BelongsToField) DisplayUsing(key string) *BelongsToField

DisplayUsing, ilişkili resource'u göstermek için kullanılacak key'i ayarlar.

Bu metod, ilişkili kaydın hangi field'ının görüntüleneceğini belirler. Varsayılan olarak "name" field'ı kullanılır.

Parametreler

- **key**: Görüntüleme için kullanılacak field adı (örn. "name", "title", "email", "username")

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors").
    DisplayUsing("email")
// Author'un email'i görüntülenir

Yaygın Kullanım Senaryoları

- **name**: Genel amaçlı görüntüleme (varsayılan) - **title**: Başlık alanları için - **email**: E-posta adresi görüntüleme - **username**: Kullanıcı adı görüntüleme - **full_name**: Tam ad görüntüleme

Döndürür:

  • BelongsToField pointer'ı (method chaining için)

func (*BelongsToField) Extract

func (b *BelongsToField) Extract(record any)

Extract, BelongsTo ilişkisini minimal formatta serialize eder.

Bu metod, ilişkili kaydı {"id": ..., "title": ...} formatında döndürür. Record title pattern'ini takip eder.

Çalışma Mantığı

1. Schema.Extract ile foreign key değerini alır 2. İlişki eager loaded ise ve RelatedResource varsa:

  • İlişkili kaydın ID'sini alır
  • RelatedResource.RecordTitle ile başlığı alır
  • {"id": foreignKey, "title": recordTitle} formatında döndürür

3. İlişki yüklenmemişse veya nil ise null döndürür

Önemli Notlar

- İlişki eager loaded olmalı (WithEagerLoad veya Preload kullanılmalı) - RelatedResource nil ise sadece foreign key değeri döner - DisplayUsing callback'i varsa öncelik verilir

Kullanım Örneği

// Post -> Author ilişkisi
post := &Post{
    ID: 1,
    AuthorID: 5,
    Author: &User{ID: 5, Name: "John Doe"},
}
field.Extract(&post)
// field.Data = {"id": 5, "title": "John Doe"}

// İlişki yüklenmemiş
post := &Post{ID: 1, AuthorID: 5, Author: nil}
field.Extract(&post)
// field.Data = nil

Parametreler:

  • record: Kayıt instance'ı (pointer olmalı)

func (*BelongsToField) GetDisplayKey

func (b *BelongsToField) GetDisplayKey() string

GetDisplayKey returns the display key

func (*BelongsToField) GetForeignKey

func (b *BelongsToField) GetForeignKey() string

GetForeignKey, foreign key sütun adını döndürür.

Bu metod, BelongsTo ilişkisinde kullanılan foreign key sütununun adını döndürür. GormRelationConfig'den foreign key bilgisini alır.

Dönüş Değeri

- Foreign key sütun adı (örn. "author_id", "user_id") - GormRelationConfig nil ise boş string döner

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors")
foreignKey := field.GetForeignKey() // "author_id"

Döndürür:

  • Foreign key sütun adı

func (*BelongsToField) GetHoverCard

func (b *BelongsToField) GetHoverCard() *HoverCardConfig

GetHoverCard, hover card konfigürasyonunu döndürür.

Bu metod, hover card konfigürasyonunu alır.

Döndürür:

  • HoverCardConfig pointer'ı (nil olabilir)

func (*BelongsToField) GetLoadingStrategy

func (b *BelongsToField) GetLoadingStrategy() LoadingStrategy

GetLoadingStrategy returns the loading strategy

func (*BelongsToField) GetOwnerKeyColumn

func (b *BelongsToField) GetOwnerKeyColumn() string

GetOwnerKeyColumn, owner key sütun adını döndürür.

Bu metod, BelongsTo ilişkisinde kullanılan owner key (references) sütununun adını döndürür. Owner key, ilişkili tablodaki referans sütunudur (genellikle primary key).

Dönüş Değeri

- Owner key sütun adı (örn. "id", "uuid") - GormRelationConfig nil ise varsayılan olarak "id" döner

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors")
ownerKey := field.GetOwnerKeyColumn() // "id"

Döndürür:

  • Owner key sütun adı

func (*BelongsToField) GetQueryCallback

func (b *BelongsToField) GetQueryCallback() func(interface{}) interface{}

GetQueryCallback returns the query callback

func (*BelongsToField) GetRelatedResource

func (b *BelongsToField) GetRelatedResource() string

GetRelatedResource returns the related resource slug

func (*BelongsToField) GetRelatedResourceSlug

func (b *BelongsToField) GetRelatedResourceSlug() string

GetRelatedResourceSlug, ilişkili resource'un slug'ını döndürür.

Bu metod, BelongsTo ilişkisinde kullanılan ilişkili resource'un slug'ını döndürür.

Dönüş Değeri

- İlişkili resource slug'ı (örn. "authors", "users", "categories")

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors")
slug := field.GetRelatedResourceSlug() // "authors"

Döndürür:

  • İlişkili resource slug'ı

func (*BelongsToField) GetRelatedTableName

func (b *BelongsToField) GetRelatedTableName() string

GetRelatedTableName, ilişkili tablo adını döndürür.

Bu metod, BelongsTo ilişkisinde kullanılan ilişkili tablonun adını döndürür. Raw SQL sorguları için kullanılır.

Dönüş Değeri

- İlişkili tablo adı (örn. "authors", "users", "categories")

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors")
tableName := field.GetRelatedTableName() // "authors"

Döndürür:

  • İlişkili tablo adı

func (*BelongsToField) GetRelationshipName

func (b *BelongsToField) GetRelationshipName() string

GetRelationshipName returns the relationship name

func (*BelongsToField) GetRelationshipType

func (b *BelongsToField) GetRelationshipType() string

GetRelationshipType returns the relationship type

func (*BelongsToField) GetSearchableColumns

func (b *BelongsToField) GetSearchableColumns() []string

GetSearchableColumns returns the searchable columns

func (*BelongsToField) GetTypes

func (b *BelongsToField) GetTypes() map[string]string

GetTypes returns the type mappings (not used for BelongsTo)

func (*BelongsToField) HoverCard

func (b *BelongsToField) HoverCard(hoverStruct interface{}) *BelongsToField

HoverCard, hover card struct'ını ayarlar ve hover card'ı etkinleştirir.

Bu metod, hover card için kullanılacak struct'ı belirler ve hover card özelliğini aktif eder.

Parametreler

- **hoverStruct**: Hover card verisi için kullanılacak struct (örn. &AuthorHoverCard{})

Kullanım Örneği

type AuthorHoverCard struct {
    Avatar string `json:"avatar"`
    Name   string `json:"name"`
    Email  string `json:"email"`
    Phone  string `json:"phone"`
}

field := fields.BelongsTo("Author", "author_id", "authors").
    DisplayUsing("name").
    HoverCard(&AuthorHoverCard{})

Döndürür:

  • BelongsToField pointer'ı (method chaining için)

func (*BelongsToField) IsRequired

func (b *BelongsToField) IsRequired() bool

IsRequired returns whether the field is required

func (*BelongsToField) Query

func (b *BelongsToField) Query(fn func(interface{}) interface{}) *BelongsToField

Query sets the query callback for customizing relationship query

func (*BelongsToField) ResolveHoverCard

func (b *BelongsToField) ResolveHoverCard(resolver HoverCardResolver) *BelongsToField

ResolveHoverCard, hover card verilerini çözmek için callback fonksiyonunu ayarlar.

Bu metod, hover card açıldığında çağrılacak resolver fonksiyonunu belirler. Resolver, ilişkili kaydın hover card verilerini döndürür.

Parametreler

- **resolver**: Hover card resolver callback fonksiyonu

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors").
    DisplayUsing("name").
    HoverCard(&AuthorHoverCard{}).
    ResolveHoverCard(func(ctx context.Context, record interface{}, relatedID interface{}, field fields.Field) (interface{}, error) {
        // İlişkili kaydı veritabanından al
        author := &Author{}
        if err := db.First(author, relatedID).Error; err != nil {
            return nil, err
        }

        // Hover card verisini döndür
        return &AuthorHoverCard{
            Avatar: author.Avatar,
            Name:   author.Name,
            Email:  author.Email,
            Phone:  author.Phone,
        }, nil
    })

API Endpoint

Frontend, hover card açıldığında şu endpoint'e istek atar:

GET /api/resource/{resource}/resolver/{field_name}?id={related_id}
POST /api/resource/{resource}/resolver/{field_name} (body: {id: related_id})

Döndürür:

  • BelongsToField pointer'ı (method chaining için)

func (*BelongsToField) ResolveRelationship

func (b *BelongsToField) ResolveRelationship(item interface{}) (interface{}, error)

ResolveRelationship resolves the relationship value using reflection

func (*BelongsToField) Searchable

func (b *BelongsToField) Searchable() Element

Searchable, alanı aranabilir olarak işaretler (Element interface'ini implement eder).

Bu metod, alanın global arama işlemlerine dahil edilmesini sağlar. Global arama yapıldığında, bu alan da arama sonuçlarına dahil edilir.

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors").
    Searchable()
// Bu alan global arama işlemlerine dahil edilir

Önemli Notlar

- Global arama, tüm aranabilir alanlarda arama yapar - WithSearchableColumns() ile birlikte kullanılmalıdır - Performans için dikkatli kullanılmalıdır

Döndürür:

  • Element interface'i (method chaining için)

func (*BelongsToField) ValidateRelationship

func (b *BelongsToField) ValidateRelationship(value interface{}) error

ValidateRelationship validates the relationship

func (*BelongsToField) WithEagerLoad

func (b *BelongsToField) WithEagerLoad() *BelongsToField

WithEagerLoad sets the loading strategy to eager loading

func (*BelongsToField) WithHoverCard

func (b *BelongsToField) WithHoverCard(config HoverCardConfig) *BelongsToField

WithHoverCard, hover card konfigürasyonunu ayarlar.

Bu metod, index ve detail sayfalarında ilişkili kaydın hover card ile nasıl görüntüleneceğini belirler.

Parametreler

- **config**: Hover card konfigürasyonu

Kullanım Örneği (Deprecated - Yeni API kullanın)

field := fields.BelongsTo("Author", "author_id", "authors").
    WithHoverCard(*fields.NewHoverCardConfig())

Yeni API (Önerilen)

field := fields.BelongsTo("Author", "author_id", "authors").
    HoverCard(&AuthorHoverCard{}).
    ResolveHoverCard(func(ctx context.Context, record interface{}, relatedID interface{}, field fields.Field) (interface{}, error) {
        // Custom logic
        return &AuthorHoverCard{...}, nil
    })

Döndürür:

  • BelongsToField pointer'ı (method chaining için)

func (*BelongsToField) WithLazyLoad

func (b *BelongsToField) WithLazyLoad() *BelongsToField

WithLazyLoad sets the loading strategy to lazy loading

func (*BelongsToField) WithSearchableColumns

func (b *BelongsToField) WithSearchableColumns(columns ...string) *BelongsToField

WithSearchableColumns, BelongsTo için aranabilir sütunları ayarlar.

Bu metod, ilişkili kayıtlarda arama yapılabilecek sütunları belirler. Bu sütunlar, combobox'ta arama yaparken kullanılır.

Parametreler

- **columns**: Aranabilir sütun adlarının listesi (örn. "name", "email", "username")

Kullanım Örneği

field := fields.BelongsTo("Author", "author_id", "authors").
    WithSearchableColumns("name", "email", "username")
// Kullanıcı combobox'ta arama yaptığında name, email ve username sütunlarında arama yapılır

Önemli Notlar

- Aranabilir sütunlar, ilgili tabloda mevcut olmalıdır - Çok fazla sütun eklemek performans sorunlarına neden olabilir - Genellikle 2-4 sütun yeterlidir

Döndürür:

  • BelongsToField pointer'ı (method chaining için)

type BelongsToManyField

type BelongsToManyField struct {
	Schema
	RelatedResourceSlug string
	RelatedResource     interface{} // resource.Resource interface (interface{} to avoid circular import)
	PivotTableName      string
	ForeignKeyColumn    string
	RelatedKeyColumn    string
	QueryCallback       func(query interface{}) interface{}
	LoadingStrategy     LoadingStrategy
	GormRelationConfig  *RelationshipGormConfig
}

BelongsToManyField, many-to-many ilişkiyi temsil eder (örn. User -> Roles).

BelongsToMany ilişkisi, bir kaydın birden fazla ilişkili kayda sahip olduğunu ve ilişkili kayıtların da birden fazla kayda sahip olabileceğini belirtir. Bu, veritabanında pivot (ara) tablo ile temsil edilir.

Kullanım Senaryoları

- **User -> Roles**: Bir kullanıcının birden fazla rolü vardır, bir rol birden fazla kullanıcıya atanabilir - **Post -> Tags**: Bir yazının birden fazla etiketi vardır, bir etiket birden fazla yazıda kullanılabilir - **Student -> Courses**: Bir öğrenci birden fazla kursa kayıtlıdır, bir kursta birden fazla öğrenci vardır

Özellikler

- **Tip Güvenliği**: Resource instance veya string slug kullanılabilir - **Pivot Tablo**: Ara tablo adı otomatik oluşturulur veya özelleştirilebilir - **Foreign Key Özelleştirme**: Ana tablodaki foreign key sütunu özelleştirilebilir - **Related Key Özelleştirme**: İlişkili tablodaki foreign key sütunu özelleştirilebilir - **Eager/Lazy Loading**: Yükleme stratejisi seçimi - **GORM Yapılandırması**: Pivot tablo ve key'ler özelleştirilebilir

Kullanım Örneği

// String slug ile
field := fields.BelongsToMany("Roles", "roles", "roles").
    PivotTable("user_roles").
    ForeignKey("user_id").
    RelatedKey("role_id").
    WithEagerLoad()

// Resource instance ile (tip güvenli)
field := fields.BelongsToMany("Roles", "roles", user.NewRoleResource()).
    PivotTable("user_roles").
    ForeignKey("user_id").
    RelatedKey("role_id").
    WithEagerLoad()

Pivot Tablo Yapısı

Pivot tablo genellikle şu yapıya sahiptir:

CREATE TABLE user_roles (
    user_id INT,
    role_id INT,
    PRIMARY KEY (user_id, role_id)
);

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func BelongsToMany

func BelongsToMany(name, key string, relatedResource interface{}) *BelongsToManyField

BelongsToMany, yeni bir BelongsToMany ilişki alanı oluşturur.

Bu fonksiyon, hem string slug hem de resource instance kabul eder. Resource instance kullanımı tip güvenliği sağlar ve refactoring'i kolaylaştırır.

Parametreler

- **name**: Alanın görünen adı (örn. "Roles", "Roller") - **key**: İlişki key'i (örn. "roles") - **relatedResource**: İlgili resource (string slug veya resource instance)

String Slug Kullanımı

field := fields.BelongsToMany("Tags", "tags", "tags")

Resource Instance Kullanımı (Önerilen)

field := fields.BelongsToMany("Tags", "tags", blog.NewTagResource())

**Avantajlar:** - ✅ Tip güvenliği (derleme zamanı kontrolü) - ✅ Refactoring desteği - ✅ IDE desteği (autocomplete, go-to-definition)

Varsayılan Değerler

- **PivotTableName**: Otomatik oluşturulur (örn. "post_tag", "user_role") - **ForeignKeyColumn**: "user_id" (ana tablonun foreign key'i) - **RelatedKeyColumn**: slug + "_id" (örn. "role_id", "tag_id") - **LoadingStrategy**: EAGER_LOADING (N+1 sorgu problemini önler)

Döndürür:

  • Yapılandırılmış BelongsToManyField pointer'ı

func (*BelongsToManyField) AutoOptions

func (b *BelongsToManyField) AutoOptions(displayField string) *BelongsToManyField

AutoOptions enables automatic options generation from the related table. displayField is the column name to use for the option label.

func (*BelongsToManyField) Count

func (b *BelongsToManyField) Count() int64

Count returns the count of related resources

func (*BelongsToManyField) Extract

func (b *BelongsToManyField) Extract(resource interface{})

Extract, BelongsToMany ilişkisini minimal formatta serialize eder.

Bu metod, ilişkili kayıtları [{"id": ..., "title": ...}, ...] formatında döndürür. Record title pattern'ini takip eder.

Çalışma Mantığı

1. Schema.Extract ile ilişki verilerini alır 2. Data nil ise boş array döndürür 3. RelatedResource varsa her kayıt için:

  • ID field'ını alır
  • RelatedResource.RecordTitle ile başlığı alır
  • {"id": ..., "title": ...} formatında ekler

4. İlişki yüklenmemişse boş array döndürür

Önemli Notlar

- İlişki eager loaded olmalı (WithEagerLoad veya Preload kullanılmalı) - RelatedResource nil ise mevcut veri döner - HasMany ile aynı mantıkta çalışır

Kullanım Örneği

// User -> Roles ilişkisi
user := &User{
    ID: 1,
    Roles: []Role{
        {ID: 1, Name: "Admin"},
        {ID: 2, Name: "Editor"},
    },
}
field.Extract(&user)
// field.Data = [{"id": 1, "title": "Admin"}, {"id": 2, "title": "Editor"}]

// İlişki yüklenmemiş
user := &User{ID: 1, Roles: nil}
field.Extract(&user)
// field.Data = []

Parametreler:

  • record: Kayıt instance'ı (pointer olmalı)

func (*BelongsToManyField) ForeignKey

func (b *BelongsToManyField) ForeignKey(key string) *BelongsToManyField

ForeignKey sets the foreign key in pivot table

func (*BelongsToManyField) GetDisplayKey

func (b *BelongsToManyField) GetDisplayKey() string

GetDisplayKey returns the display key (not used for BelongsToMany)

func (*BelongsToManyField) GetLoadingStrategy

func (b *BelongsToManyField) GetLoadingStrategy() LoadingStrategy

GetLoadingStrategy returns the loading strategy

func (*BelongsToManyField) GetQueryCallback

func (b *BelongsToManyField) GetQueryCallback() func(interface{}) interface{}

GetQueryCallback returns the query callback

func (*BelongsToManyField) GetRelatedResourceSlug

func (b *BelongsToManyField) GetRelatedResourceSlug() string

GetRelatedResource returns the related resource slug

func (*BelongsToManyField) GetRelationshipName

func (b *BelongsToManyField) GetRelationshipName() string

GetRelationshipName returns the relationship name

func (*BelongsToManyField) GetRelationshipType

func (b *BelongsToManyField) GetRelationshipType() string

GetRelationshipType returns the relationship type

func (*BelongsToManyField) GetSearchableColumns

func (b *BelongsToManyField) GetSearchableColumns() []string

GetSearchableColumns returns the searchable columns (not used for BelongsToMany)

func (*BelongsToManyField) GetTypes

func (b *BelongsToManyField) GetTypes() map[string]string

GetTypes returns the type mappings (not used for BelongsToMany)

func (*BelongsToManyField) IsRequired

func (b *BelongsToManyField) IsRequired() bool

IsRequired returns whether the field is required

func (*BelongsToManyField) PivotTable

func (b *BelongsToManyField) PivotTable(table string) *BelongsToManyField

PivotTable sets the pivot table name

func (*BelongsToManyField) Query

func (b *BelongsToManyField) Query(fn func(interface{}) interface{}) *BelongsToManyField

Query sets the query callback for customizing relationship query

func (*BelongsToManyField) RelatedKey

func (b *BelongsToManyField) RelatedKey(key string) *BelongsToManyField

RelatedKey sets the related key in pivot table

func (*BelongsToManyField) ResolveRelationship

func (b *BelongsToManyField) ResolveRelationship(item interface{}) (interface{}, error)

ResolveRelationship resolves the relationship by loading through pivot table

func (*BelongsToManyField) Searchable

func (b *BelongsToManyField) Searchable() Element

Searchable marks the element as searchable (implements Element interface)

func (*BelongsToManyField) ValidateRelationship

func (b *BelongsToManyField) ValidateRelationship(value interface{}) error

ValidateRelationship validates the relationship

func (*BelongsToManyField) WithEagerLoad

func (b *BelongsToManyField) WithEagerLoad() *BelongsToManyField

WithEagerLoad sets the loading strategy to eager loading

func (*BelongsToManyField) WithLazyLoad

func (b *BelongsToManyField) WithLazyLoad() *BelongsToManyField

WithLazyLoad sets the loading strategy to lazy loading

type Comment

type Comment struct {
	// ID, yorumun benzersiz kimliğidir (primary key).
	ID int `json:"id"`

	// PostID, yorumun yapıldığı gönderinin ID'sidir (foreign key).
	PostID int `json:"post_id"`

	// UserID, yorumu yapan kullanıcının ID'sidir (foreign key).
	UserID int `json:"user_id"`

	// Content, yorumun içeriğidir.
	Content string `json:"content"`

	// Post, yorumun yapıldığı gönderidir (BelongsTo ilişkisi).
	// Bu alan opsiyoneldir ve eager loading ile doldurulur.
	Post *Post `json:"post,omitempty"`

	// Author, yorumu yapan kullanıcıdır (BelongsTo ilişkisi).
	// Bu alan opsiyoneldir ve eager loading ile doldurulur.
	Author *User `json:"author,omitempty"`
}

Comment, bir gönderi yorumunu temsil eden model yapısıdır.

Bu model, kullanıcıların gönderilere yaptığı yorumları tutar ve birden fazla BelongsTo ilişkisinin test edilmesinde kullanılır.

İlişkiler

- **BelongsTo**: Post (her yorum bir gönderiye aittir) - **BelongsTo**: User (her yorum bir kullanıcıya aittir)

JSON Serileştirme

Post ve Author alanları opsiyoneldir ve `omitempty` ile işaretlenmiştir. İlişkiler yüklenmemişse JSON'da görünmez.

Örnek Kullanım

```go var comment Comment err := db.QueryRow(`

SELECT c.id, c.post_id, c.user_id, c.content,
       p.id, p.title,
       u.id, u.name
FROM comments c
LEFT JOIN posts p ON c.post_id = p.id
LEFT JOIN users u ON c.user_id = u.id
WHERE c.id = ?

`, 1).Scan(&comment.ID, &comment.PostID, &comment.UserID, &comment.Content,

&comment.Post.ID, &comment.Post.Title,
&comment.Author.ID, &comment.Author.Name)

```

type ConditionalValidator

type ConditionalValidator struct {
	Condition func(context interface{}) bool
	Validator ValidatorFunc
}

ConditionalValidator represents a validator that applies conditionally

type Currency

type Currency string

Currency, money field'larında kullanılacak ISO 4217 currency kodunu temsil eder.

const (
	CurrencyUSD Currency = "USD"
	CurrencyEUR Currency = "EUR"
	CurrencyTRY Currency = "TRY"
	CurrencyGBP Currency = "GBP"
	CurrencyJPY Currency = "JPY"
	CurrencyCHF Currency = "CHF"
	CurrencyCAD Currency = "CAD"
	CurrencyAUD Currency = "AUD"
	CurrencyCNY Currency = "CNY"
)

type CustomValidatorRegistry

type CustomValidatorRegistry struct {
	// contains filtered or unexported fields
}

CustomValidatorRegistry stores custom validators

func NewCustomValidatorRegistry

func NewCustomValidatorRegistry() *CustomValidatorRegistry

NewCustomValidatorRegistry creates a new custom validator registry

func (*CustomValidatorRegistry) Apply

func (r *CustomValidatorRegistry) Apply(name string, value interface{}, context interface{}) error

Apply applies a custom validator

func (*CustomValidatorRegistry) Get

Get retrieves a custom validator

func (*CustomValidatorRegistry) Register

func (r *CustomValidatorRegistry) Register(name string, validator ValidatorFunc)

Register registers a custom validator

type DependencyCallbackFunc

type DependencyCallbackFunc func(
	field *Schema,
	formData map[string]interface{},
	ctx *fiber.Ctx,
) *FieldUpdate

DependencyCallbackFunc, form alanları arasındaki bağımlılık ilişkilerini yönetmek için kullanılan callback fonksiyon tipidir.

Genel Bakış

Bu fonksiyon tipi, bir alanın değeri değiştiğinde diğer alanların davranışını dinamik olarak değiştirmek için kullanılır. Örneğin, bir dropdown'da seçilen değere göre başka bir alanı göstermek/gizlemek, zorunlu hale getirmek veya seçeneklerini değiştirmek gibi işlemler yapılabilir.

Kullanım Senaryoları

- **Koşullu Alan Görünürlüğü**: Bir alanın değerine göre diğer alanları göster/gizle - **Dinamik Validasyon**: Bir alanın değerine göre diğer alanların validasyon kurallarını değiştir - **Cascade Seçenekler**: Bir dropdown'ın seçimine göre diğer dropdown'ların seçeneklerini filtrele - **Koşullu Zorunluluk**: Belirli koşullarda alanları zorunlu veya opsiyonel yap - **Dinamik Yardım Metinleri**: Bağlama göre yardım metinlerini güncelle

Parametreler

- `field`: Bağımlılık kuralının uygulanacağı hedef alan şeması - `formData`: Form verilerini içeren map (tüm alanların güncel değerleri) - `ctx`: Fiber context nesnesi (HTTP request/response bilgilerine erişim için)

Dönüş Değeri

`*FieldUpdate`: Alana uygulanacak güncellemeleri içeren nesne. nil döndürülürse hiçbir güncelleme yapılmaz.

Kullanım Örneği

```go // Ülke seçimine göre şehir alanını göster/gizle

countryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    country := formData["country"]
    if country == "TR" {
        return NewFieldUpdate().Show().MakeRequired()
    }
    return NewFieldUpdate().Hide().MakeOptional()
})

// Ürün tipine göre fiyat alanının validasyonunu değiştir

productTypeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    productType := formData["product_type"]
    if productType == "premium" {
        return NewFieldUpdate().
            SetHelpText("Premium ürünler için minimum 1000 TL").
            AddRule(ValidationRule{Type: "min", Value: 1000})
    }
    return NewFieldUpdate().SetHelpText("Standart fiyatlandırma")
})

```

Önemli Notlar

- Callback fonksiyonu her form değişikliğinde çağrılabilir, bu nedenle performans açısından hafif olmalıdır - Sonsuz döngülerden kaçınmak için dikkatli olunmalıdır (A alanı B'yi tetikler, B alanı A'yı tetikler) - formData map'i güvenli bir şekilde kontrol edilmeli, nil veya eksik değerler için kontrol yapılmalıdır - Context üzerinden veritabanı sorguları yapılabilir ancak performans etkileri göz önünde bulundurulmalıdır

Avantajlar

- Dinamik ve esnek form davranışı sağlar - Kullanıcı deneyimini iyileştirir (gereksiz alanları gizler) - Karmaşık iş kurallarını kolayca uygular - Sunucu tarafında kontrol sağlar (güvenlik)

Dezavantajlar

- Yanlış kullanımda performans sorunlarına yol açabilir - Karmaşık bağımlılık zincirleri debug edilmesi zor olabilir - Sonsuz döngü riski vardır

type DependencyResolver

type DependencyResolver struct {
	// contains filtered or unexported fields
}

DependencyResolver

Alan bağımlılıklarını çözen ve yöneten ana yapı.

## Amaç

Form alanları arasındaki bağımlılık ilişkilerini yönetir ve bir alan değiştiğinde ona bağımlı diğer alanların otomatik olarak güncellenmesini sağlar.

## Yapı Alanları

- `fields`: Tüm form alanlarının listesi - `context`: Bağımlılık çözme bağlamı (örn: "form", "filter", "detail")

## Çalışma Prensibi

1. Alanlar arası bağımlılık grafiği oluşturulur 2. Değişen alanlar tespit edilir 3. BFS algoritması ile etkilenen tüm alanlar bulunur 4. Her etkilenen alan için ilgili callback fonksiyonları çalıştırılır 5. Güncellenmiş alan bilgileri döndürülür

## Avantajlar

- **Performans**: Graf yapısı sayesinde O(V+E) karmaşıklığında çalışır - **Esneklik**: Context bazlı farklı bağımlılık kuralları tanımlanabilir - **Güvenlik**: Döngüsel bağımlılık tespiti ile sonsuz döngüler önlenir - **Modülerlik**: Her alan kendi bağımlılık callback'ini tanımlayabilir

## Dezavantajlar

- Çok karmaşık bağımlılık ağlarında performans düşebilir - Callback fonksiyonlarının doğru yazılması gerekir

## Önemli Notlar

⚠️ **Uyarı**: Döngüsel bağımlılıklar sonsuz döngüye neden olabilir. Mutlaka `DetectCircularDependencies()` ile kontrol edin.

💡 **İpucu**: Context parametresi ile aynı alanlar farklı bağlamlarda farklı davranabilir (örn: form vs filter).

func NewDependencyResolver

func NewDependencyResolver(fields []*Schema, context string) *DependencyResolver

NewDependencyResolver

Yeni bir bağımlılık çözücü oluşturur.

## Parametreler

- `fields`: Bağımlılık çözümlemesi yapılacak alan listesi - `context`: Bağımlılık çözme bağlamı (örn: "form", "filter", "detail")

## Dönüş Değeri

Yapılandırılmış `*DependencyResolver` örneği döner.

## Kullanım Örneği

```go

fields := []*Schema{
    {Key: "country", DependsOnFields: []string{}},
    {Key: "city", DependsOnFields: []string{"country"}},
    {Key: "district", DependsOnFields: []string{"city"}},
}

resolver := NewDependencyResolver(fields, "form") ```

## Önemli Notlar

- Context parametresi, aynı alanların farklı bağlamlarda farklı davranmasını sağlar - Oluşturulduktan sonra `DetectCircularDependencies()` ile kontrol yapılması önerilir

func (*DependencyResolver) DetectCircularDependencies

func (r *DependencyResolver) DetectCircularDependencies() error

DetectCircularDependencies

Alan bağımlılıkları arasında döngüsel (circular) bağımlılık olup olmadığını tespit eder.

## Amaç

Bağımlılık grafiğinde döngü (cycle) olup olmadığını kontrol eder. Döngüsel bağımlılıklar sonsuz döngülere ve stack overflow hatalarına neden olabileceği için, sistem başlatılırken veya alan tanımları değiştiğinde bu kontrolün yapılması kritik önem taşır.

## Dönüş Değeri

- `nil`: Döngüsel bağımlılık yok, sistem güvenli - `error`: Döngüsel bağımlılık tespit edildi, hata mesajında ilgili alan belirtilir

## Döngüsel Bağımlılık Nedir?

Döngüsel bağımlılık, alanların birbirine doğrudan veya dolaylı olarak bağımlı olduğu ve bir döngü oluşturduğu durumdur.

### Örnekler

**Doğrudan Döngü:** ``` Alan A -> Alan B -> Alan A ```

**Dolaylı Döngü:** ``` Alan A -> Alan B -> Alan C -> Alan A ```

**Karmaşık Döngü:** ``` Alan A -> Alan B -> Alan C

  ↓         ↓
Alan D -> Alan E -> Alan A

```

## Kullanım Örneği

```go // Alan tanımları

fields := []*Schema{
    {Key: "country", DependsOnFields: []string{"city"}},  // Hatalı!
    {Key: "city", DependsOnFields: []string{"country"}},  // Döngü!
}

resolver := NewDependencyResolver(fields, "form")

// Döngüsel bağımlılık kontrolü

if err := resolver.DetectCircularDependencies(); err != nil {
    log.Fatal(err) // "circular dependency detected involving field: country"
}

```

## Doğru Kullanım

```go // Doğru alan tanımları (tek yönlü bağımlılık)

fields := []*Schema{
    {Key: "country", DependsOnFields: []string{}},
    {Key: "city", DependsOnFields: []string{"country"}},
    {Key: "district", DependsOnFields: []string{"city"}},
}

resolver := NewDependencyResolver(fields, "form")

// Kontrol başarılı

if err := resolver.DetectCircularDependencies(); err != nil {
    log.Fatal(err)
}

// Hata yok, sistem güvenli ```

## Algoritma: DFS (Depth-First Search)

1. Her alan için DFS başlat (henüz ziyaret edilmemişse) 2. Alanı ziyaret edildi olarak işaretle 3. Alanı recursion stack'e ekle 4. Alanın bağımlılarını kontrol et:

  • Bağımlı henüz ziyaret edilmemişse, recursive DFS çağrısı yap
  • Bağımlı recursion stack'te varsa, döngü tespit edildi

5. Alanı recursion stack'ten çıkar

## Performans

- **Zaman Karmaşıklığı**: O(V + E)

  • V: Toplam alan sayısı
  • E: Toplam bağımlılık sayısı

- **Alan Karmaşıklığı**: O(V)

  • visited ve recStack map'leri için

## Ne Zaman Çağrılmalı?

1. **Sistem Başlatma**: Uygulama başlarken tüm alanlar için kontrol 2. **Alan Tanımı Değişikliği**: Yeni alan eklendiğinde veya bağımlılık değiştiğinde 3. **Geliştirme Aşaması**: Unit testlerde otomatik kontrol 4. **Deployment Öncesi**: CI/CD pipeline'da validasyon

## Önemli Notlar

**UYARI**: Bu fonksiyon mutlaka çağrılmalıdır. Döngüsel bağımlılıklar runtime'da sonsuz döngüye ve sistem çökmesine neden olabilir.

**NOT**: Hata mesajı sadece döngüye dahil olan alanlardan birini gösterir. Tüm döngüyü görmek için ek analiz gerekebilir.

**İPUCU**: Geliştirme ortamında panic kullanarak erken tespit yapılabilir: ```go

if err := resolver.DetectCircularDependencies(); err != nil {
    panic(err) // Geliştirme ortamında hemen fark edilir
}

```

## Test Örneği

```go

func TestCircularDependency(t *testing.T) {
    fields := []*Schema{
        {Key: "a", DependsOnFields: []string{"b"}},
        {Key: "b", DependsOnFields: []string{"c"}},
        {Key: "c", DependsOnFields: []string{"a"}}, // Döngü!
    }

    resolver := NewDependencyResolver(fields, "test")
    err := resolver.DetectCircularDependencies()

    assert.Error(t, err)
    assert.Contains(t, err.Error(), "circular dependency")
}

```

func (*DependencyResolver) ResolveDependencies

func (r *DependencyResolver) ResolveDependencies(
	formData map[string]interface{},
	changedFields []string,
	ctx *fiber.Ctx,
) (map[string]*FieldUpdate, error)

ResolveDependencies

Değişen alanlara bağlı tüm alanları tespit eder ve güncelleme bilgilerini döner.

## Amaç

Form verilerinde değişiklik olan alanları tespit edip, bu alanlara bağımlı olan diğer tüm alanları bulur ve her biri için ilgili callback fonksiyonlarını çalıştırarak güncellenmiş alan bilgilerini döner.

## Parametreler

- `formData`: Güncel form verilerini içeren map (alan adı -> değer) - `changedFields`: Değişiklik yapılan alan anahtarlarının listesi - `ctx`: Fiber context nesnesi (HTTP request/response bilgileri için)

## Dönüş Değerleri

- `map[string]*FieldUpdate`: Alan anahtarı -> güncelleme bilgisi map'i - `error`: Hata durumunda hata mesajı

## Çalışma Algoritması

1. **Graf Oluşturma**: Tüm alanlar arası bağımlılık grafiği oluşturulur 2. **BFS Traversal**: Değişen alanlardan başlayarak BFS ile etkilenen alanlar bulunur 3. **Callback Çalıştırma**: Her etkilenen alan için context'e uygun callback çalıştırılır 4. **Sonuç Toplama**: Tüm güncellemeler bir map'te toplanır

## Kullanım Örneği

```go // Form verisi

formData := map[string]interface{}{
    "country": "TR",
    "city": "Istanbul",
}

// Değişen alanlar changedFields := []string{"country"}

// Bağımlılıkları çöz updates, err := resolver.ResolveDependencies(formData, changedFields, ctx)

if err != nil {
    return err
}

// Güncellemeleri uygula

for fieldKey, update := range updates {
    fmt.Printf("Alan %s güncellendi: %+v\n", fieldKey, update)
}

```

## Performans

- **Zaman Karmaşıklığı**: O(V + E) - V: alan sayısı, E: bağımlılık sayısı - **Alan Karmaşıklığı**: O(V) - Visited ve affected map'leri için

## Önemli Notlar

⚠️ **Uyarı**: Callback fonksiyonları içinde hata oluşursa, bu alan için güncelleme döndürülmez ancak diğer alanlar işlenmeye devam eder.

💡 **İpucu**: Context parametresi sayesinde aynı alan farklı bağlamlarda (form, filter, detail) farklı callback'ler kullanabilir.

📌 **Not**: Döngüsel bağımlılıklar varsa sonsuz döngüye girmez, visited map'i sayesinde her alan sadece bir kez işlenir.

type DialogContentType

type DialogContentType string

DialogContentType, dialog içeriğinin tipini belirler (form veya wizard)

const (
	// DialogContentForm - Basit form içeriği
	DialogContentForm DialogContentType = "form"
	// DialogContentWizard - Multi-step wizard içeriği
	DialogContentWizard DialogContentType = "wizard"
)

type DialogField

type DialogField struct {
	*Schema
	// contains filtered or unexported fields
}

DialogField, modal/dialog içinde form veya wizard gösteren bir field tipidir

Kullanım Senaryosu: - Kullanıcıdan modal içinde veri toplamak için - Multi-step wizard formları için - Sayfa geçişlerinde kullanıcıyı bilgilendirmek için

Özellikler: - Varsayılan açık veya buton ile tetiklenebilir - Basit form veya multi-step wizard mode - Özelleştirilebilir dialog boyutu - OnComplete ve OnSkip callback'leri

Örnek Kullanım (Basit Form):

Dialog("Profil Tamamla", "profile_completion").
    DefaultOpen(true).
    DialogTitle("Profilinizi Tamamlayın").
    Content([]core.Element{
        Text("Telefon", "phone").Required(),
        Text("Adres", "address").Required(),
    }).
    OnComplete(func(ctx *fiber.Ctx, data map[string]any) error {
        // Veriyi kaydet
        return nil
    })

Örnek Kullanım (Wizard):

Dialog("Onboarding", "onboarding_wizard").
    TriggerButton("Başlangıç Rehberini Başlat").
    DialogTitle("Hoş Geldiniz!").
    Wizard([]DialogStep{
        {
            Index:   0,
            Title:   "Kişisel Bilgiler",
            Fields:  []core.Element{Text("Ad", "name").Required()},
            CanSkip: false,
        },
        {
            Index:   1,
            Title:   "Tercihler",
            Fields:  []core.Element{Switch("Bildirimler", "notifications")},
            CanSkip: true,
        },
    })

func Dialog

func Dialog(name string, key ...string) *DialogField

Dialog, yeni bir DialogField oluşturur

Parametreler:

  • name: Field'ın görüntü adı
  • key: Veritabanı anahtarı (opsiyonel)

Dönüş Değeri:

  • *DialogField: Yapılandırılmış dialog field pointer'ı

Örnek Kullanım:

field := Dialog("Profil Tamamla", "profile_completion")

func (*DialogField) Content

func (f *DialogField) Content(fields []core.Element) *DialogField

Content, basit form içeriğini ayarlar

Parametreler:

  • fields: Form field'ları

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Profil", "profile").Content([]core.Element{
    Text("Ad", "name").Required(),
    Email("Email", "email").Required(),
})

func (*DialogField) DefaultOpen

func (f *DialogField) DefaultOpen(open bool) *DialogField

DefaultOpen, dialog'un varsayılan olarak açık olup olmayacağını ayarlar

Parametreler:

  • open: true ise dialog sayfa yüklendiğinde otomatik açılır

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Profil", "profile").DefaultOpen(true)

func (*DialogField) DialogDesc

func (f *DialogField) DialogDesc(desc string) *DialogField

DialogDesc, dialog açıklamasını ayarlar

Parametreler:

  • desc: Dialog açıklaması

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Profil", "profile").DialogDesc("Lütfen bilgilerinizi güncelleyin")

func (*DialogField) DialogSize

func (f *DialogField) DialogSize(size string) *DialogField

DialogSize, dialog boyutunu ayarlar

Parametreler:

  • size: Dialog boyutu ("sm", "md", "lg", "xl", "full")

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Profil", "profile").DialogSize("lg")

func (*DialogField) DialogTitle

func (f *DialogField) DialogTitle(title string) *DialogField

DialogTitle, dialog başlığını ayarlar

Parametreler:

  • title: Dialog başlığı

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Profil", "profile").DialogTitle("Profilinizi Düzenleyin")

func (*DialogField) Extract

func (f *DialogField) Extract(resource interface{})

Extract, DialogField için veri çıkarır (core.Element interface implementasyonu)

func (*DialogField) GetContext

func (f *DialogField) GetContext() ElementContext

GetContext, DialogField'ın context'ini döndürür (core.Element interface implementasyonu)

func (*DialogField) GetKey

func (f *DialogField) GetKey() string

GetKey, DialogField'ın key'ini döndürür (core.Element interface implementasyonu)

func (*DialogField) GetView

func (f *DialogField) GetView() string

GetView, DialogField'ın view tipini döndürür (core.Element interface implementasyonu)

func (*DialogField) JsonSerialize

func (f *DialogField) JsonSerialize() map[string]any

JsonSerialize, DialogField'ı JSON uyumlu bir map'e serileştirir

Bu metod, DialogField'ın tüm özelliklerini frontend'e göndermek için JSON formatına dönüştürür.

Dönüş Değeri:

  • map[string]any: JSON uyumlu map

Örnek Kullanım:

field := Dialog("Profil", "profile").DefaultOpen(true)
json := field.JsonSerialize()
// json["view"] == "dialog"
// json["defaultOpen"] == true

func (*DialogField) OnComplete

func (f *DialogField) OnComplete(fn func(ctx *fiber.Ctx, data map[string]any) error) *DialogField

OnComplete, dialog tamamlandığında çağrılacak callback'i ayarlar

Parametreler:

  • fn: Callback fonksiyonu

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Profil", "profile").OnComplete(func(ctx *fiber.Ctx, data map[string]any) error {
    // Veriyi kaydet
    return nil
})

func (*DialogField) OnSkip

func (f *DialogField) OnSkip(fn func(ctx *fiber.Ctx) error) *DialogField

OnSkip, dialog atlandığında çağrılacak callback'i ayarlar (wizard için)

Parametreler:

  • fn: Callback fonksiyonu

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Onboarding", "onboarding").OnSkip(func(ctx *fiber.Ctx) error {
    // Atlandı işaretini kaydet
    return nil
})

func (*DialogField) TriggerButton

func (f *DialogField) TriggerButton(text string) *DialogField

TriggerButton, dialog'u açacak butonun metnini ayarlar

Parametreler:

  • text: Buton metni

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Profil", "profile").TriggerButton("Profili Düzenle")

func (*DialogField) TriggerIcon

func (f *DialogField) TriggerIcon(icon string) *DialogField

TriggerIcon, dialog butonunun ikonunu ayarlar

Parametreler:

  • icon: İkon (emoji veya icon class)

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Profil", "profile").TriggerIcon("✏️")

func (*DialogField) Wizard

func (f *DialogField) Wizard(steps []DialogStep) *DialogField

Wizard, multi-step wizard içeriğini ayarlar

Parametreler:

  • steps: Wizard adımları

Dönüş Değeri:

  • *DialogField: Method chaining için

Örnek Kullanım:

Dialog("Onboarding", "onboarding").Wizard([]DialogStep{
    {
        Index:   0,
        Title:   "Adım 1",
        Fields:  []core.Element{Text("Ad", "name")},
        CanSkip: false,
    },
})

type DialogStep

type DialogStep struct {
	Index       int            `json:"index"`       // Adım sırası (0'dan başlar)
	Title       string         `json:"title"`       // Adım başlığı
	Description string         `json:"description"` // Adım açıklaması
	Fields      []core.Element `json:"fields"`      // Adımdaki field'lar
	CanSkip     bool           `json:"can_skip"`    // Adım atlanabilir mi?
}

DialogStep, wizard mode için bir adımı temsil eder

Kullanım Senaryosu: - Multi-step form wizard'ları için - Her adım kendi field'larına sahip - Adımlar atlanabilir veya zorunlu olabilir

Örnek Kullanım:

step := DialogStep{
    Index:       0,
    Title:       "Kişisel Bilgiler",
    Description: "Lütfen kişisel bilgilerinizi girin",
    Fields: []core.Element{
        Text("Ad", "name").Required(),
        Email("Email", "email").Required(),
    },
    CanSkip: false,
}

type Displayable

type Displayable struct {
	// contains filtered or unexported fields
}

Displayable, alanların görüntüleme formatını özelleştirmesini sağlayan bir mixin'dir.

Alan değerlerinin UI'da nasıl render edileceğini kontrol eden görüntüleme callback'leri ve format string'leri için yapılandırma sağlar.

Kullanım

type TextField struct {
    fields.Base
    fields.Displayable
}

field := &TextField{}
field.SetDisplayFormat("uppercase")
field.SetDisplayCallback(func(ctx *context.Context, value any) string {
    return strings.ToUpper(value.(string))
})

Daha fazla örnek için docs/Fields.md dosyasına bakın.

func (*Displayable) GetDisplayCallback

func (d *Displayable) GetDisplayCallback() func(*context.Context, any) string

GetDisplayCallback, görüntüleme callback fonksiyonunu döndürür. Hiçbir callback ayarlanmamışsa nil döndürür.

Döndürür:

  • Görüntüleme callback fonksiyonu veya ayarlanmamışsa nil

func (*Displayable) GetDisplayFormat

func (d *Displayable) GetDisplayFormat() string

GetDisplayFormat, görüntüleme format string'ini döndürür. Hiçbir format ayarlanmamışsa boş string döndürür.

Döndürür:

  • Görüntüleme format tanımlayıcısı

func (*Displayable) SetDisplayCallback

func (d *Displayable) SetDisplayCallback(cb func(*context.Context, any) string)

SetDisplayCallback, özel bir görüntüleme callback fonksiyonu ayarlar.

Callback, context ve alan değerini alır, ve görüntüleme için değerin formatlanmış string temsilini döndürmelidir.

Parametreler:

  • cb: Alan değerini görüntüleme için formatlayan fonksiyon

Örnek:

field.SetDisplayCallback(func(ctx *context.Context, value any) string {
    timestamp, ok := value.(time.Time)
    if !ok {
        return ""
    }
    return timestamp.Format("2006-01-02 15:04:05")
})

func (*Displayable) SetDisplayFormat

func (d *Displayable) SetDisplayFormat(format string)

SetDisplayFormat, görüntüleme format string'ini ayarlar.

Format string'i, frontend'e değerin nasıl görüntüleneceği hakkında bir ipucudur (örn. "uppercase", "lowercase", "currency", "date").

Parametreler:

  • format: Görüntüleme format tanımlayıcısı

Örnek:

field.SetDisplayFormat("currency")

type Element

type Element = core.Element

Element, admin panel'deki bir UI elemanını temsil eder.

Bu tip, core.Element'in bir alias'ıdır ve tüm field türleri (Text, Number, BelongsTo, vb.) bu interface'i implement eder.

Daha fazla bilgi için pkg/core/element.go dosyasına bakın.

type ElementContext

type ElementContext = core.ElementContext

ElementContext, bir elemanın hangi bağlamda görüntüleneceğini belirtir.

Bu tip, core.ElementContext'in bir alias'ıdır ve elemanların form, liste veya detay sayfalarında görünürlüğünü kontrol eder.

Daha fazla bilgi için pkg/core/element_context.go dosyasına bakın.

type ElementType

type ElementType = core.ElementType

ElementType, bir elemanın tipini belirtir.

Bu tip, core.ElementType'ın bir alias'ıdır ve her field türünün (Text, Number, BelongsTo, vb.) hangi UI bileşenini kullanacağını belirler.

Daha fazla bilgi için pkg/core/element_type.go dosyasına bakın.

const (
	TYPE_TEXT            ElementType = core.TYPE_TEXT
	TYPE_TEXTAREA        ElementType = core.TYPE_TEXTAREA
	TYPE_RICHTEXT        ElementType = core.TYPE_RICHTEXT
	TYPE_PASSWORD        ElementType = core.TYPE_PASSWORD
	TYPE_NUMBER          ElementType = core.TYPE_NUMBER
	TYPE_MONEY           ElementType = core.TYPE_MONEY
	TYPE_TEL             ElementType = core.TYPE_TEL
	TYPE_EMAIL           ElementType = core.TYPE_EMAIL
	TYPE_AUDIO           ElementType = core.TYPE_AUDIO
	TYPE_VIDEO           ElementType = core.TYPE_VIDEO
	TYPE_DATE            ElementType = core.TYPE_DATE
	TYPE_DATETIME        ElementType = core.TYPE_DATETIME
	TYPE_FILE            ElementType = core.TYPE_FILE
	TYPE_KEY_VALUE       ElementType = core.TYPE_KEY_VALUE
	TYPE_LINK            ElementType = core.TYPE_LINK
	TYPE_COLLECTION      ElementType = core.TYPE_COLLECTION
	TYPE_DETAIL          ElementType = core.TYPE_DETAIL
	TYPE_CONNECT         ElementType = core.TYPE_CONNECT
	TYPE_POLY_LINK       ElementType = core.TYPE_POLY_LINK
	TYPE_POLY_DETAIL     ElementType = core.TYPE_POLY_DETAIL
	TYPE_POLY_COLLECTION ElementType = core.TYPE_POLY_COLLECTION
	TYPE_POLY_CONNECT    ElementType = core.TYPE_POLY_CONNECT
	TYPE_BOOLEAN         ElementType = core.TYPE_BOOLEAN
	TYPE_SELECT          ElementType = core.TYPE_SELECT
	TYPE_PANEL           ElementType = core.TYPE_PANEL
	TYPE_TABS            ElementType = core.TYPE_TABS
	TYPE_STACK           ElementType = core.TYPE_STACK
	TYPE_RELATIONSHIP    ElementType = core.TYPE_RELATIONSHIP
	TYPE_BADGE           ElementType = core.TYPE_BADGE
	TYPE_CODE            ElementType = core.TYPE_CODE
	TYPE_COLOR           ElementType = core.TYPE_COLOR
	TYPE_BOOLEAN_GROUP   ElementType = core.TYPE_BOOLEAN_GROUP
)

type FieldUpdate

type FieldUpdate struct {
	Visible     *bool                  `json:"visible,omitempty"`
	ReadOnly    *bool                  `json:"readonly,omitempty"`
	Required    *bool                  `json:"required,omitempty"`
	Disabled    *bool                  `json:"disabled,omitempty"`
	HelpText    *string                `json:"helpText,omitempty"`
	Placeholder *string                `json:"placeholder,omitempty"`
	Options     map[string]interface{} `json:"options,omitempty"`
	Value       interface{}            `json:"value,omitempty"`
	Rules       []ValidationRule       `json:"rules,omitempty"`
}

FieldUpdate, bağımlılık değişikliklerine göre bir alana uygulanacak güncellemeleri temsil eder.

Genel Bakış

Bu struct, form alanlarının dinamik davranışını kontrol etmek için kullanılır. Bir alanın görünürlüğünden validasyon kurallarına kadar tüm özelliklerini değiştirmeye olanak tanır. Pointer kullanımı sayesinde sadece değiştirilmek istenen özellikler güncellenir, diğerleri mevcut hallerini korur.

Struct Alanları

- `Visible`: Alanın görünür olup olmadığını kontrol eder (nil = değişiklik yok) - `ReadOnly`: Alanın salt okunur olup olmadığını kontrol eder (nil = değişiklik yok) - `Required`: Alanın zorunlu olup olmadığını kontrol eder (nil = değişiklik yok) - `Disabled`: Alanın devre dışı olup olmadığını kontrol eder (nil = değişiklik yok) - `HelpText`: Alanın yardım metnini günceller (nil = değişiklik yok) - `Placeholder`: Alanın placeholder metnini günceller (nil = değişiklik yok) - `Options`: Alanın seçeneklerini günceller (select, radio vb. için) - `Value`: Alanın değerini programatik olarak ayarlar - `Rules`: Alanın validasyon kurallarını günceller

Kullanım Senaryoları

- **Koşullu Görünürlük**: Bir alanı belirli koşullarda göster/gizle - **Dinamik Validasyon**: Koşullara göre validasyon kurallarını değiştir - **Cascade Seçenekler**: Üst seçime göre alt seçenekleri filtrele - **Koşullu Zorunluluk**: Belirli durumlarda alanı zorunlu yap - **Dinamik Değer Atama**: Hesaplanan değerleri alanlara otomatik ata - **Kullanıcı Rehberliği**: Bağlama göre yardım metinlerini güncelle

Kullanım Örneği

```go // Basit görünürlük kontrolü update := NewFieldUpdate().Show().MakeRequired()

// Çoklu özellik güncelleme (method chaining) update := NewFieldUpdate().

Show().
MakeRequired().
SetHelpText("Bu alan zorunludur").
SetPlaceholder("Lütfen bir değer girin")

// Dinamik seçenekler güncelleme

cities := map[string]interface{}{
    "istanbul": "İstanbul",
    "ankara": "Ankara",
    "izmir": "İzmir",
}

update := NewFieldUpdate().SetOptions(cities)

// Validasyon kuralları ekleme update := NewFieldUpdate().

MakeRequired().
AddRule(ValidationRule{Type: "min", Value: 18}).
AddRule(ValidationRule{Type: "max", Value: 65})

// Değer atama ve salt okunur yapma update := NewFieldUpdate().

SetValue("Otomatik hesaplanan değer").
MakeReadOnly()

```

Önemli Notlar

  • **Pointer Kullanımı**: Tüm boolean ve string alanlar pointer'dır. Bu sayede nil değer "değişiklik yok" anlamına gelir, false/true veya boş string ile karıştırılmaz
  • **Method Chaining**: Tüm setter metodlar *FieldUpdate döndürür, bu sayede zincirleme çağrılar yapılabilir
  • **Seçici Güncelleme**: Sadece set edilen alanlar güncellenir, diğerleri korunur
  • **JSON Serileştirme**: omitempty tag'leri sayesinde nil alanlar JSON'a dahil edilmez
  • **Thread Safety**: Bu struct thread-safe değildir, concurrent kullanımda dikkatli olunmalıdır

Avantajlar

- Esnek ve güçlü alan kontrolü sağlar - Method chaining ile okunabilir kod yazılmasını sağlar - Seçici güncelleme ile performans optimizasyonu sağlar - Type-safe alan güncellemeleri yapar - JSON serileştirme desteği ile API entegrasyonu kolaydır

Dezavantajlar

- Pointer kullanımı nil kontrollerini gerektirir - Karmaşık güncellemelerde kod okunabilirliği azalabilir - Thread-safe değildir

Best Practices

- Her zaman NewFieldUpdate() ile yeni instance oluşturun - Method chaining kullanarak okunabilir kod yazın - Nil kontrollerini ihmal etmeyin - Gereksiz güncellemelerden kaçının (performans için)

func NewFieldUpdate

func NewFieldUpdate() *FieldUpdate

NewFieldUpdate, yeni bir FieldUpdate instance'ı oluşturur.

Genel Bakış

Bu fonksiyon, FieldUpdate struct'ının yeni bir instance'ını oluşturur ve döndürür. Tüm alanlar nil/boş değerlerle başlatılır, bu sayede sadece set edilen özellikler güncelleme sırasında uygulanır.

Kullanım Senaryoları

- Bağımlılık callback fonksiyonlarında yeni güncelleme nesnesi oluşturmak - Method chaining ile zincirleme güncelleme işlemleri yapmak - Temiz ve okunabilir kod yazmak için başlangıç noktası

Dönüş Değeri

`*FieldUpdate`: Yeni oluşturulmuş, boş bir FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate() update.Show() update.MakeRequired()

// Method chaining ile kullanım (önerilen) update := NewFieldUpdate().

Show().
MakeRequired().
SetHelpText("Bu alan zorunludur")

// Bağımlılık callback'inde kullanım

field.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    if formData["country"] == "TR" {
        return NewFieldUpdate().Show().MakeRequired()
    }
    return NewFieldUpdate().Hide()
})

```

Önemli Notlar

- Her güncelleme işlemi için yeni bir instance oluşturun, mevcut instance'ları yeniden kullanmayın - Method chaining kullanarak daha okunabilir kod yazabilirsiniz - Nil döndürmek yerine boş FieldUpdate döndürmek güvenlidir (hiçbir güncelleme yapılmaz)

Best Practices

- Her zaman bu fonksiyonu kullanarak yeni instance oluşturun - Struct literal kullanmak yerine bu factory fonksiyonunu tercih edin - Method chaining ile zincirleme çağrılar yapın

func (*FieldUpdate) AddRule

func (u *FieldUpdate) AddRule(rule ValidationRule) *FieldUpdate

AddRule, mevcut validasyon kurallarına yeni bir kural ekler.

Genel Bakış

Bu metod, bir form alanının mevcut validasyon kurallarına yeni bir kural ekler. Mevcut kuralları korur ve sonuna yeni kuralı ekler. Method chaining desteği için *FieldUpdate döndürür. Kademeli kural ekleme senaryoları için idealdir.

Kullanım Senaryoları

- **Kademeli Kural Ekleme**: Koşullara göre adım adım kural ekle - **Ek Validasyon**: Mevcut kurallara ek kontroller ekle - **Koşullu Kural Ekleme**: Belirli durumlarda ekstra kurallar ekle - **Dinamik Kural Biriktirme**: Birden fazla koşula göre kuralları biriktir - **Modüler Validasyon**: Her koşul için ayrı kural ekle

Parametreler

- `rule`: Eklenecek ValidationRule - Tek bir validasyon kuralı

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().

AddRule(ValidationRule{Type: "required", Message: "Bu alan zorunludur"}).
AddRule(ValidationRule{Type: "min", Value: 3, Message: "En az 3 karakter"})

// Koşullu kural ekleme

passwordField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    update := NewFieldUpdate().
        AddRule(ValidationRule{Type: "required", Message: "Şifre zorunludur"}).
        AddRule(ValidationRule{Type: "min", Value: 8, Message: "En az 8 karakter"})

    // Güvenlik seviyesine göre ek kurallar
    securityLevel := formData["security_level"].(string)
    if securityLevel == "high" {
        update.
            AddRule(ValidationRule{Type: "uppercase", Message: "En az 1 büyük harf"}).
            AddRule(ValidationRule{Type: "lowercase", Message: "En az 1 küçük harf"}).
            AddRule(ValidationRule{Type: "number", Message: "En az 1 rakam"}).
            AddRule(ValidationRule{Type: "special", Message: "En az 1 özel karakter"})
    } else if securityLevel == "medium" {
        update.
            AddRule(ValidationRule{Type: "uppercase", Message: "En az 1 büyük harf"}).
            AddRule(ValidationRule{Type: "number", Message: "En az 1 rakam"})
    }

    return update
})

// Kademeli kural ekleme

emailField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    update := NewFieldUpdate().
        AddRule(ValidationRule{Type: "required", Message: "E-posta zorunludur"}).
        AddRule(ValidationRule{Type: "email", Message: "Geçerli bir e-posta girin"})

    // Kurumsal hesap kontrolü
    accountType := formData["account_type"].(string)
    if accountType == "corporate" {
        update.AddRule(ValidationRule{
            Type:    "domain_whitelist",
            Value:   []string{"company.com", "partner.com"},
            Message: "Sadece şirket e-postaları kabul edilir",
        })
    }

    // Benzersizlik kontrolü
    checkUnique := formData["check_unique"].(bool)
    if checkUnique {
        update.AddRule(ValidationRule{
            Type:    "unique",
            Table:   "users",
            Column:  "email",
            Message: "Bu e-posta zaten kullanılıyor",
        })
    }

    return update
})

// Çoklu koşullu kural ekleme

priceField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    update := NewFieldUpdate().
        AddRule(ValidationRule{Type: "required", Message: "Fiyat zorunludur"}).
        AddRule(ValidationRule{Type: "numeric", Message: "Geçerli bir sayı girin"}).
        AddRule(ValidationRule{Type: "min", Value: 0, Message: "Fiyat negatif olamaz"})

    // Ürün tipine göre
    productType := formData["product_type"].(string)
    if productType == "premium" {
        update.AddRule(ValidationRule{
            Type:    "min",
            Value:   1000,
            Message: "Premium ürünler minimum 1000 TL olmalıdır",
        })
    }

    // Kullanıcı rolüne göre
    userRole := ctx.Locals("user_role").(string)
    if userRole != "admin" {
        update.AddRule(ValidationRule{
            Type:    "max",
            Value:   10000,
            Message: "Maksimum 10.000 TL girebilirsiniz",
        })
    }

    // İndirim varsa
    hasDiscount := formData["has_discount"].(bool)
    if hasDiscount {
        update.AddRule(ValidationRule{
            Type:    "custom",
            Value:   "validate_discount_price",
            Message: "İndirimli fiyat normal fiyattan düşük olmalıdır",
        })
    }

    return update
})

// Method chaining ile zincirleme ekleme update := NewFieldUpdate().

MakeRequired().
AddRule(ValidationRule{Type: "min", Value: 3, Message: "En az 3 karakter"}).
AddRule(ValidationRule{Type: "max", Value: 50, Message: "En fazla 50 karakter"}).
AddRule(ValidationRule{Type: "alphanumeric", Message: "Sadece harf ve rakam"}).
SetHelpText("Kullanıcı adı 3-50 karakter, harf ve rakam içermelidir")

// Dinamik kural biriktirme

ageField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    update := NewFieldUpdate().
        AddRule(ValidationRule{Type: "required", Message: "Yaş zorunludur"}).
        AddRule(ValidationRule{Type: "numeric", Message: "Geçerli bir sayı girin"})

    // Yaş aralığı kontrolü
    serviceType := formData["service_type"].(string)
    switch serviceType {
    case "child":
        update.
            AddRule(ValidationRule{Type: "min", Value: 0, Message: "Yaş 0'dan küçük olamaz"}).
            AddRule(ValidationRule{Type: "max", Value: 12, Message: "Çocuk servisi 0-12 yaş arası"})
    case "teen":
        update.
            AddRule(ValidationRule{Type: "min", Value: 13, Message: "Genç servisi 13 yaşından başlar"}).
            AddRule(ValidationRule{Type: "max", Value: 17, Message: "Genç servisi 13-17 yaş arası"})
    case "adult":
        update.
            AddRule(ValidationRule{Type: "min", Value: 18, Message: "Yetişkin servisi 18 yaşından başlar"}).
            AddRule(ValidationRule{Type: "max", Value: 65, Message: "Yetişkin servisi 18-65 yaş arası"})
    case "senior":
        update.
            AddRule(ValidationRule{Type: "min", Value: 65, Message: "Yaşlı servisi 65 yaşından başlar"}).
            AddRule(ValidationRule{Type: "max", Value: 120, Message: "Geçerli bir yaş girin"})
    }

    return update
})

```

Önemli Notlar

- **Mevcut Kuralları Korur**: AddRule() mevcut kuralları korur ve sonuna ekler - **Sıralama**: Kurallar eklenme sırasına göre uygulanır - **Çoklu Çağrı**: Birden fazla kez çağrılabilir (method chaining) - **Performans**: Her çağrı slice'a append yapar - **Nil Kontrol**: Rules nil ise otomatik olarak initialize edilir

Best Practices

- Temel kuralları önce ekleyin (required, type checks) - Detaylı kuralları sonra ekleyin (min, max, pattern) - Pahalı kuralları en sona ekleyin (unique, custom validators) - Method chaining kullanarak okunabilir kod yazın - Koşullu ekleme için if blokları kullanın - Kullanıcı dostu hata mesajları yazın

Avantajlar

- Mevcut kuralları korur - Esnek ve modüler kural ekleme - Method chaining desteği - Koşullu kural ekleme için ideal - Okunabilir kod yazımı

Dezavantajlar

- Çok fazla çağrı performansı etkileyebilir - Kural sırası önemlidir (dikkatli olunmalı) - Duplicate kural kontrolü yoktur

AddRule vs SetRules Karşılaştırması

| Özellik | AddRule | SetRules | |---------|---------|----------| | Mevcut Kurallar | Korur ve ekler | Siler ve değiştirir | | Kullanım | Tekli ekleme | Toplu güncelleme | | Method Chaining | Evet | Evet | | Esneklik | Yüksek | Düşük | | Performans | Her çağrıda append | Tek seferde | | Kullanım Amacı | Kademeli ekleme | Tüm kuralları değiştir |

Performans İpuçları

- Çok fazla AddRule çağrısı yerine SetRules kullanmayı düşünün - Pahalı validasyonları (DB sorguları) en sona ekleyin - Gereksiz kural eklemekten kaçının - Kural sayısını makul seviyede tutun (ideal: 3-7 kural)

func (*FieldUpdate) Disable

func (u *FieldUpdate) Disable() *FieldUpdate

Disable, alanı devre dışı bırakır (pasif hale getirir).

Genel Bakış

Bu metod, bir form alanını devre dışı bırakır. Disabled özelliğini true olarak ayarlar ve method chaining desteği için *FieldUpdate döndürür. Devre dışı alanlar kullanıcı tarafından düzenlenemez ve form submit edildiğinde değerleri gönderilmez.

Kullanım Senaryoları

- **Koşullu Devre Dışı Bırakma**: Belirli koşullarda alanları pasif hale getir - **Bağımlılık Kontrolü**: Bağımlı alanları koşul sağlanmadığında devre dışı bırak - **Yetki Kısıtlaması**: Yetkisiz kullanıcılar için alanları kapat - **İş Kuralları**: İş mantığına göre alanları devre dışı bırak - **Geçici Kilitleme**: Belirli durumlarda alanları geçici olarak kilitle

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().Disable()

// Bağımlılık kontrolü

countryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    country := formData["country"]
    if country == "" {
        // Ülke seçilmediğinde şehir alanını devre dışı bırak
        return NewFieldUpdate().
            Disable().
            SetHelpText("Önce ülke seçin").
            SetValue(nil)
    }
    return NewFieldUpdate().Enable()
})

// Yetki kısıtlaması userRole := ctx.Locals("user_role").(string)

if userRole == "viewer" {
    return NewFieldUpdate().
        Disable().
        SetHelpText("Bu alanı düzenleme yetkiniz yok")
}

// İş kuralı bazlı devre dışı bırakma

statusField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    status := formData["status"]
    if status == "completed" {
        // Tamamlanmış kayıtlar düzenlenemez
        return NewFieldUpdate().
            Disable().
            MakeReadOnly().
            SetHelpText("Tamamlanmış kayıtlar düzenlenemez")
    }
    return NewFieldUpdate().Enable().MakeEditable()
})

// Koşullu form akışı

paymentMethodField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    paymentMethod := formData["payment_method"]
    if paymentMethod == "cash" {
        // Nakit ödeme için kredi kartı alanlarını devre dışı bırak
        return NewFieldUpdate().
            Disable().
            Hide().
            SetValue(nil)
    }
    return NewFieldUpdate().Enable().Show()
})

// Geçici kilitleme

processingField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    isProcessing := formData["is_processing"].(bool)
    if isProcessing {
        return NewFieldUpdate().
            Disable().
            SetHelpText("İşlem devam ediyor, lütfen bekleyin...")
    }
    return NewFieldUpdate().Enable()
})

```

Önemli Notlar

- **Form Submit**: Disabled alanların değerleri form submit edildiğinde gönderilmez - **Validasyon**: Disabled alanlar için validasyon kuralları uygulanmaz - **Görünürlük**: Disable() sadece disabled durumunu değiştirir, görünürlüğü etkilemez - **Değer Temizleme**: Devre dışı bırakılan alanların değerlerini SetValue(nil) ile temizlemeyi düşünün - **Kullanıcı Deneyimi**: Neden devre dışı olduğunu açıklayan yardım metni ekleyin

Best Practices

- Disable() ile birlikte SetHelpText() kullanarak kullanıcıyı bilgilendirin - Devre dışı bırakılan alanların değerlerini temizlemeyi düşünün - Hide() ile birlikte kullanarak gereksiz alanları tamamen gizleyin - Koşullu devre dışı bırakmada her iki durumu da (Enable/Disable) ele alın - Sunucu tarafında da aynı kontrolü uygulayın (güvenlik)

Avantajlar

- Kullanıcı hatalarını önler - Form akışını kontrol eder - Bağımlılık yönetimini kolaylaştırır - Kullanıcı deneyimini iyileştirir

Dezavantajlar

- Disabled alanların değerleri form submit'e dahil edilmez (veri kaybı riski) - Aşırı kullanımda kullanıcı deneyimini olumsuz etkiler

func (*FieldUpdate) Enable

func (u *FieldUpdate) Enable() *FieldUpdate

Enable, alanı etkinleştirir (aktif hale getirir).

Genel Bakış

Bu metod, devre dışı bırakılmış bir alanı tekrar etkinleştirir. Disabled özelliğini false olarak ayarlar ve method chaining desteği için *FieldUpdate döndürür. Etkin alanlar kullanıcı tarafından düzenlenebilir ve form submit edildiğinde değerleri gönderilir.

Kullanım Senaryoları

- **Koşullu Aktivasyon**: Belirli koşullarda alanları aktif hale getir - **Adım Bazlı Formlar**: Form adımlarına göre alanları etkinleştir - **Yetki Bazlı Erişim**: Kullanıcı yetkisine göre alanları aktif et - **Dinamik Form Akışı**: Kullanıcı seçimlerine göre alanları etkinleştir - **Bağımlılık Çözümü**: Bağımlı alanları koşul sağlandığında aktif et

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().Enable()

// Koşullu aktivasyon

agreementField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    agreed := formData["terms_agreed"].(bool)
    if agreed {
        // Sözleşme kabul edildiğinde devam butonu aktif
        return NewFieldUpdate().
            Enable().
            SetHelpText("Devam edebilirsiniz")
    }
    return NewFieldUpdate().
        Disable().
        SetHelpText("Devam etmek için sözleşmeyi kabul edin")
})

// Bağımlılık çözümü

countryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    country := formData["country"]
    if country != "" {
        // Ülke seçildiğinde şehir alanını aktif et
        return NewFieldUpdate().
            Enable().
            Show().
            SetHelpText("Lütfen şehir seçin")
    }
    return NewFieldUpdate().Disable().Hide()
})

// Adım bazlı form

stepField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    step := formData["current_step"].(int)
    if step >= 2 {
        // 2. adımda ödeme alanlarını aktif et
        return NewFieldUpdate().
            Enable().
            Show().
            MakeRequired()
    }
    return NewFieldUpdate().Disable().Hide()
})

// Yetki bazlı erişim userRole := ctx.Locals("user_role").(string)

if userRole == "admin" || userRole == "editor" {
    return NewFieldUpdate().
        Enable().
        MakeEditable().
        SetHelpText("Düzenleme yetkisine sahipsiniz")
}

```

Önemli Notlar

- **Disabled vs ReadOnly**: Disabled alanlar form submit'e dahil edilmez, ReadOnly alanlar dahil edilir - **Görünürlük**: Enable() sadece disabled durumunu değiştirir, görünürlüğü etkilemez - **Validasyon**: Etkin alanlar için validasyon kuralları uygulanır - **Form Submit**: Etkin alanların değerleri form submit edildiğinde gönderilir - **Method Chaining**: Diğer metodlarla zincirleme kullanılabilir

Best Practices

- Enable() ile birlikte Show() kullanarak tam erişim sağlayın - Etkinleştirilen alanlar için uygun yardım metni ekleyin - MakeEditable() ile birlikte kullanarak düzenleme izni verin - Koşullu aktivasyonda her iki durumu da (Enable/Disable) ele alın

Avantajlar

- Dinamik form davranışı sağlar - Kullanıcı deneyimini iyileştirir - Bağımlılık yönetimini kolaylaştırır - Koşullu erişim kontrolü sağlar

Disabled vs ReadOnly Karşılaştırması

| Özellik | Disabled | ReadOnly | |---------|----------|----------| | Görünürlük | Görünür (genelde soluk) | Görünür (normal) | | Düzenlenebilirlik | Hayır | Hayır | | Form Submit | Dahil edilmez | Dahil edilir | | Validasyon | Uygulanmaz | Uygulanmaz | | Kullanım Amacı | Geçici devre dışı | Kalıcı koruma |

func (*FieldUpdate) Hide

func (u *FieldUpdate) Hide() *FieldUpdate

Hide, alanı gizler.

Genel Bakış

Bu metod, bir form alanının kullanıcı arayüzünde gizlenmesini sağlar. Visible özelliğini false olarak ayarlar ve method chaining desteği için *FieldUpdate döndürür.

Kullanım Senaryoları

- Koşullu alan gizleme: Belirli bir değer seçildiğinde ilgisiz alanları gizle - Dinamik form yapısı: Kullanıcı seçimlerine göre gereksiz alanları gizle - Basitleştirilmiş form: Kullanıcıya sadece ilgili alanları göster - Validasyon atlama: Gizli alanlar için validasyon uygulanmaz

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().Hide()

// Koşullu gizleme

if formData["payment_method"] == "cash" {
    // Nakit ödeme seçildiğinde kredi kartı alanlarını gizle
    return NewFieldUpdate().Hide().MakeOptional()
}

// Karmaşık koşullu mantık

productTypeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    productType := formData["product_type"]
    if productType == "digital" {
        // Dijital ürünler için fiziksel ürün alanlarını gizle
        return NewFieldUpdate().Hide().MakeOptional().SetValue(nil)
    }
    return NewFieldUpdate().Show().MakeRequired()
})

// Method chaining ile birlikte kullanım update := NewFieldUpdate().

Hide().
MakeOptional().
SetValue(nil) // Gizli alan için değeri temizle

```

Önemli Notlar

- Hide() çağrıldığında alan gizlenir ve validasyon kuralları uygulanmaz - Gizli alanların değerleri form submit edildiğinde gönderilmeyebilir - Güvenlik açısından hassas alanlar için Hide() yeterli değildir, sunucu tarafı kontrolü gereklidir - Method chaining desteklenir, zincirleme çağrılar yapılabilir - Gizlenen alanları MakeOptional() ile birlikte kullanmak önerilir

Best Practices

- Hide() ile birlikte MakeOptional() kullanarak validasyon hatalarını önleyin - Gizlenen alanların değerlerini SetValue(nil) ile temizlemeyi düşünün - Koşullu gizlemede her iki durumu da (Show/Hide) ele alın - Güvenlik kritik alanlar için sunucu tarafı kontrolü yapın

func (*FieldUpdate) MakeEditable

func (u *FieldUpdate) MakeEditable() *FieldUpdate

MakeEditable, alanı düzenlenebilir hale getirir.

Genel Bakış

Bu metod, daha önce salt okunur yapılmış bir alanı tekrar düzenlenebilir hale getirir. ReadOnly özelliğini false olarak ayarlar ve method chaining desteği için *FieldUpdate döndürür.

Kullanım Senaryoları

- **Koşullu Düzenleme**: Belirli koşullarda alanları düzenlenebilir yap - **Rol Bazlı Erişim**: Yetki seviyesine göre alanları aç/kapat - **Durum Bazlı Kontrol**: Kayıt durumuna göre düzenleme izni ver - **Dinamik Form**: Kullanıcı seçimlerine göre alanları aktif et

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().MakeEditable()

// Durum bazlı düzenleme

statusField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    status := formData["status"]
    if status == "draft" {
        // Taslak durumunda tüm alanlar düzenlenebilir
        return NewFieldUpdate().
            MakeEditable().
            SetHelpText("Taslak durumunda düzenleyebilirsiniz")
    }
    return NewFieldUpdate().
        MakeReadOnly().
        SetHelpText("Sadece taslak durumunda düzenlenebilir")
})

// Rol bazlı erişim

if ctx.Locals("user_role") == "admin" {
    return NewFieldUpdate().
        MakeEditable().
        SetHelpText("Admin olarak düzenleme yetkisine sahipsiniz")
}

// Koşullu düzenleme

editModeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    editMode := formData["edit_mode"].(bool)
    if editMode {
        return NewFieldUpdate().MakeEditable().Enable()
    }
    return NewFieldUpdate().MakeReadOnly().Disable()
})

```

Önemli Notlar

- MakeEditable() çağrıldığında alan düzenlenebilir olur ancak disabled durumu değişmez - Düzenlenebilir alanlar için validasyon kuralları uygulanır - Sunucu tarafında da aynı yetki kontrolü yapılmalıdır - Method chaining desteklenir

Best Practices

- Düzenleme izni verirken uygun yardım metni ekleyin - Sunucu tarafında yetki kontrolü yapın (güvenlik) - Enable() ile birlikte kullanarak tam erişim sağlayın - Koşullu düzenlemede her iki durumu da (Editable/ReadOnly) ele alın

func (*FieldUpdate) MakeOptional

func (u *FieldUpdate) MakeOptional() *FieldUpdate

MakeOptional, alanı opsiyonel (zorunlu olmayan) hale getirir.

Genel Bakış

Bu metod, daha önce zorunlu yapılmış bir alanı opsiyonel hale getirir. Required özelliğini false olarak ayarlar ve method chaining desteği için *FieldUpdate döndürür.

Kullanım Senaryoları

- **Koşullu Opsiyonellik**: Belirli durumlarda alanları opsiyonel yap - **Basitleştirilmiş Form**: Kullanıcı deneyimini iyileştirmek için gereksiz zorunlulukları kaldır - **Dinamik İş Kuralları**: Koşullara göre zorunluluk durumunu değiştir - **Adım Bazlı Formlar**: Farklı adımlarda farklı zorunluluk seviyeleri

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().MakeOptional()

// Koşullu opsiyonellik

accountTypeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    accountType := formData["account_type"]
    if accountType == "personal" {
        // Bireysel hesaplar için şirket adı opsiyonel
        return NewFieldUpdate().
            MakeOptional().
            SetHelpText("Bireysel hesaplar için opsiyonel")
    }
    return NewFieldUpdate().
        MakeRequired().
        SetHelpText("Kurumsal hesaplar için zorunlu")
})

// Gizli alanlar için

visibilityField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    visible := formData["show_field"].(bool)
    if !visible {
        // Gizli alanlar opsiyonel olmalı
        return NewFieldUpdate().Hide().MakeOptional()
    }
    return NewFieldUpdate().Show().MakeRequired()
})

// Basitleştirilmiş form akışı

quickModeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    quickMode := formData["quick_mode"].(bool)
    if quickMode {
        // Hızlı mod: detaylı alanlar opsiyonel
        return NewFieldUpdate().
            MakeOptional().
            SetHelpText("Hızlı modda bu alan opsiyoneldir")
    }
    return NewFieldUpdate().
        MakeRequired().
        SetHelpText("Detaylı modda bu alan zorunludur")
})

```

Önemli Notlar

- MakeOptional() çağrıldığında alan için validasyon zorunluluğu kaldırılır - Opsiyonel alanlar boş bırakılabilir - Gizli alanlar her zaman opsiyonel yapılmalıdır - Method chaining desteklenir

Best Practices

- Hide() ile birlikte kullanarak tutarlılık sağlayın - Opsiyonel alanlar için açıklayıcı yardım metni ekleyin - Koşullu zorunlulukta her iki durumu da (Required/Optional) ele alın - Kullanıcı deneyimini önceliklendirin

Avantajlar

- Kullanıcı deneyimini iyileştirir - Form doldurma süresini kısaltır - Esnek form yapısı sağlar - Gereksiz zorunlulukları kaldırır

func (*FieldUpdate) MakeReadOnly

func (u *FieldUpdate) MakeReadOnly() *FieldUpdate

MakeReadOnly, alanı salt okunur (read-only) hale getirir.

Genel Bakış

Bu metod, bir form alanının kullanıcı tarafından düzenlenemez ancak görüntülenebilir olmasını sağlar. ReadOnly özelliğini true olarak ayarlar ve method chaining desteği için *FieldUpdate döndürür.

Kullanım Senaryoları

- **Hesaplanan Değerler**: Otomatik hesaplanan alanları göster ancak düzenlemeye izin verme - **Sistem Alanları**: Sistem tarafından yönetilen alanları koruma altına al - **Onay Sonrası Kilitleme**: Onaylanmış kayıtların belirli alanlarını kilitle - **Referans Bilgileri**: Referans amaçlı gösterilen ancak değiştirilmemesi gereken bilgiler - **Audit Trail**: Değişiklik geçmişi için orijinal değerleri koruma

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().MakeReadOnly()

// Hesaplanan toplam alanı

quantityField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    quantity := formData["quantity"].(float64)
    price := formData["price"].(float64)
    total := quantity * price

    // Toplam alanını hesapla ve salt okunur yap
    return NewFieldUpdate().
        SetValue(total).
        MakeReadOnly().
        SetHelpText(fmt.Sprintf("Otomatik hesaplanan: %.2f TL", total))
})

// Onaylanmış kayıtlar için

statusField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    status := formData["status"]
    if status == "approved" {
        // Onaylandıktan sonra fiyat alanını kilitle
        return NewFieldUpdate().
            MakeReadOnly().
            SetHelpText("Onaylanmış kayıtlarda fiyat değiştirilemez")
    }
    return NewFieldUpdate().MakeEditable()
})

// Sistem alanları createdAtField := NewFieldUpdate().

MakeReadOnly().
SetHelpText("Sistem tarafından otomatik oluşturuldu")

```

Önemli Notlar

- **Görünürlük**: ReadOnly alanlar görünür kalır ancak düzenlenemez - **Validasyon**: ReadOnly alanlar için validasyon kuralları uygulanmaz (değer değişmediği için) - **Form Submit**: ReadOnly alanların değerleri form submit edildiğinde gönderilir - **Güvenlik**: Sunucu tarafında da kontrol yapılmalıdır, sadece client-side koruma yeterli değildir - **Disabled vs ReadOnly**: Disabled alanlar form submit'e dahil edilmez, ReadOnly alanlar dahil edilir

Best Practices

- Hesaplanan değerler için SetValue() ile birlikte kullanın - Kullanıcıya neden düzenleyemediğini açıklayan yardım metni ekleyin - Sunucu tarafında da aynı kontrolü uygulayın (güvenlik) - Geçici kilitleme durumları için koşullu kullanın

func (*FieldUpdate) MakeRequired

func (u *FieldUpdate) MakeRequired() *FieldUpdate

MakeRequired, alanı zorunlu hale getirir.

Genel Bakış

Bu metod, bir form alanının doldurulmasını zorunlu kılar. Required özelliğini true olarak ayarlar ve method chaining desteği için *FieldUpdate döndürür. Zorunlu alanlar için validasyon kuralları otomatik olarak uygulanır.

Kullanım Senaryoları

- **Koşullu Zorunluluk**: Belirli bir seçim yapıldığında ilgili alanları zorunlu yap - **Dinamik Validasyon**: Kullanıcı akışına göre zorunlu alanları değiştir - **İş Kuralları**: İş mantığına göre alanları zorunlu hale getir - **Adım Bazlı Formlar**: Her adımda farklı alanları zorunlu yap - **Rol Bazlı Zorunluluk**: Kullanıcı rolüne göre zorunlu alanları belirle

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().MakeRequired()

// Koşullu zorunluluk

shippingTypeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    shippingType := formData["shipping_type"]
    if shippingType == "express" {
        // Ekspres kargo için telefon numarası zorunlu
        return NewFieldUpdate().
            Show().
            MakeRequired().
            SetHelpText("Ekspres kargo için telefon numarası zorunludur")
    }
    return NewFieldUpdate().MakeOptional()
})

// İş kuralı bazlı zorunluluk

companyField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    hasCompany := formData["has_company"].(bool)
    if hasCompany {
        // Şirket varsa vergi numarası zorunlu
        return NewFieldUpdate().
            Show().
            MakeRequired().
            SetHelpText("Kurumsal müşteriler için vergi numarası zorunludur").
            SetPlaceholder("10 haneli vergi numarası")
    }
    return NewFieldUpdate().Hide().MakeOptional()
})

// Çoklu alan kontrolü

paymentMethodField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    paymentMethod := formData["payment_method"]
    if paymentMethod == "credit_card" {
        // Kredi kartı seçildiğinde kart bilgileri zorunlu
        return NewFieldUpdate().
            Show().
            MakeRequired().
            AddRule(ValidationRule{Type: "credit_card"})
    }
    return NewFieldUpdate().Hide().MakeOptional()
})

// Rol bazlı zorunluluk userRole := ctx.Locals("user_role").(string)

if userRole == "premium" {
    return NewFieldUpdate().
        MakeRequired().
        SetHelpText("Premium üyeler için bu alan zorunludur")
}

```

Önemli Notlar

- **Validasyon**: Zorunlu alanlar boş bırakıldığında validasyon hatası verir - **Görünürlük**: Gizli alanlar zorunlu yapılsa bile validasyon uygulanmaz - **Kullanıcı Deneyimi**: Zorunlu alanlar için açıklayıcı yardım metni ekleyin - **Form Submit**: Zorunlu alanlar doldurulmadan form submit edilemez - **API Validasyonu**: Sunucu tarafında da aynı zorunluluk kontrolü yapılmalıdır

Best Practices

- Zorunlu alanlar için SetHelpText() ile açıklama ekleyin - Show() ile birlikte kullanarak görünürlüğü sağlayın - Kullanıcıya neden zorunlu olduğunu açıklayın - Sunucu tarafında da validasyon yapın (güvenlik) - Gereksiz zorunluluktan kaçının (kullanıcı deneyimi için)

Avantajlar

- Veri bütünlüğünü sağlar - İş kurallarını zorlar - Kullanıcı hatalarını önler - Dinamik form davranışı sağlar

Dezavantajlar

- Aşırı kullanımda kullanıcı deneyimini olumsuz etkiler - Karmaşık koşullu mantıkta hata yapma riski artar

func (*FieldUpdate) SetHelpText

func (u *FieldUpdate) SetHelpText(text string) *FieldUpdate

SetHelpText, alanın yardım metnini ayarlar.

Genel Bakış

Bu metod, bir form alanının altında veya yanında gösterilen yardım metnini dinamik olarak günceller. HelpText özelliğini verilen string ile ayarlar ve method chaining desteği için *FieldUpdate döndürür. Yardım metinleri kullanıcıya alan hakkında ek bilgi, format gereksinimleri veya örnekler sağlar.

Kullanım Senaryoları

- **Bağlamsal Yardım**: Kullanıcı seçimlerine göre ilgili yardım metni göster - **Format Açıklaması**: Beklenen veri formatını açıkla (örn: "DD/MM/YYYY formatında") - **Validasyon Rehberi**: Validasyon kurallarını kullanıcıya açıkla - **Durum Bildirimi**: Alan durumu hakkında bilgi ver (örn: "Hesaplanıyor...") - **Hata Önleme**: Yaygın hataları önlemek için uyarılar ver - **Örnek Gösterme**: Geçerli değer örnekleri göster

Parametreler

- `text`: Gösterilecek yardım metni (string)

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().SetHelpText("Bu alan zorunludur")

// Bağlamsal yardım

countryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    country := formData["country"]
    if country == "TR" {
        return NewFieldUpdate().
            SetHelpText("11 haneli TC Kimlik Numaranızı girin (örn: 12345678901)")
    } else if country == "US" {
        return NewFieldUpdate().
            SetHelpText("9 haneli SSN numaranızı girin (örn: 123-45-6789)")
    }
    return NewFieldUpdate().SetHelpText("Kimlik numaranızı girin")
})

// Format açıklaması

dateField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    return NewFieldUpdate().
        SetHelpText("Tarih formatı: GG/AA/YYYY (örn: 15/03/2024)")
})

// Validasyon rehberi

passwordField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    return NewFieldUpdate().
        SetHelpText("En az 8 karakter, 1 büyük harf, 1 küçük harf ve 1 rakam içermelidir")
})

// Durum bildirimi

calculatingField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    isCalculating := formData["is_calculating"].(bool)
    if isCalculating {
        return NewFieldUpdate().
            SetHelpText("⏳ Hesaplama yapılıyor, lütfen bekleyin...").
            Disable()
    }
    return NewFieldUpdate().
        SetHelpText("Toplam tutar otomatik hesaplanmıştır").
        Enable()
})

// Koşullu uyarı

amountField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    amount := formData["amount"].(float64)
    if amount > 10000 {
        return NewFieldUpdate().
            SetHelpText("⚠️ Yüksek tutar: Ek onay gerekebilir")
    }
    return NewFieldUpdate().SetHelpText("Tutar giriniz")
})

// Çoklu dil desteği language := ctx.Locals("language").(string)

if language == "tr" {
    return NewFieldUpdate().SetHelpText("E-posta adresinizi girin")
} else {
    return NewFieldUpdate().SetHelpText("Enter your email address")
}

```

Önemli Notlar

- **Markdown Desteği**: Bazı UI framework'leri markdown formatını destekleyebilir - **Uzunluk**: Yardım metinleri kısa ve öz olmalıdır (ideal: 1-2 cümle) - **Emoji Kullanımı**: Dikkat çekmek için emoji kullanılabilir ancak aşırıya kaçılmamalı - **Dinamik Güncelleme**: Yardım metni form durumuna göre dinamik olarak güncellenebilir - **Erişilebilirlik**: Screen reader'lar için anlamlı metinler yazın

Best Practices

- Kısa, açık ve anlaşılır metinler yazın - Örnekler vererek kullanıcıyı yönlendirin - Hata mesajları yerine önleyici bilgiler verin - Teknik jargondan kaçının, sade dil kullanın - Çoklu dil desteği için i18n kullanmayı düşünün - Kullanıcının mevcut bağlamına uygun metinler gösterin

Avantajlar

- Kullanıcı deneyimini iyileştirir - Hata oranını azaltır - Form doldurma süresini kısaltır - Kullanıcı güvenini artırır - Destek taleplerini azaltır

func (*FieldUpdate) SetOptions

func (u *FieldUpdate) SetOptions(options map[string]interface{}) *FieldUpdate

SetOptions, alanın seçeneklerini ayarlar (select, radio, checkbox gibi alanlar için).

Genel Bakış

Bu metod, select, radio button, checkbox gibi seçim alanlarının seçeneklerini dinamik olarak günceller. Options özelliğini verilen map ile ayarlar ve method chaining desteği için *FieldUpdate döndürür. Bu özellik, cascade dropdown'lar ve dinamik seçim listeleri için kritik öneme sahiptir.

Kullanım Senaryoları

- **Cascade Dropdown**: Üst seçime göre alt dropdown seçeneklerini filtrele - **Dinamik Seçenekler**: Kullanıcı seçimlerine göre seçenekleri değiştir - **Veritabanı Sorguları**: Context üzerinden veritabanından seçenekleri çek - **Koşullu Seçenekler**: İş kurallarına göre farklı seçenekler göster - **Filtrelenmiş Listeler**: Belirli kriterlere göre seçenekleri filtrele - **Rol Bazlı Seçenekler**: Kullanıcı rolüne göre farklı seçenekler sun

Parametreler

- `options`: Seçenekleri içeren map[string]interface{}

  • Key: Seçeneğin değeri (value)
  • Value: Seçeneğin görünen metni (label) veya karmaşık nesne

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım

cities := map[string]interface{}{
    "istanbul": "İstanbul",
    "ankara": "Ankara",
    "izmir": "İzmir",
}

update := NewFieldUpdate().SetOptions(cities)

// Cascade dropdown - Ülkeye göre şehirler

countryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    country := formData["country"].(string)

    var cities map[string]interface{}
    switch country {
    case "TR":
        cities = map[string]interface{}{
            "istanbul": "İstanbul",
            "ankara": "Ankara",
            "izmir": "İzmir",
            "bursa": "Bursa",
        }
    case "US":
        cities = map[string]interface{}{
            "new_york": "New York",
            "los_angeles": "Los Angeles",
            "chicago": "Chicago",
        }
    default:
        cities = map[string]interface{}{}
    }

    return NewFieldUpdate().
        SetOptions(cities).
        Show().
        Enable().
        SetValue(nil) // Önceki seçimi temizle
})

// Veritabanından dinamik seçenekler

categoryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    categoryID := formData["category_id"].(int)

    // Veritabanından alt kategorileri çek
    var subcategories []Subcategory
    db := ctx.Locals("db").(*gorm.DB)
    db.Where("category_id = ?", categoryID).Find(&subcategories)

    // Map'e dönüştür
    options := make(map[string]interface{})
    for _, sub := range subcategories {
        options[fmt.Sprintf("%d", sub.ID)] = sub.Name
    }

    return NewFieldUpdate().
        SetOptions(options).
        Show().
        MakeRequired().
        SetHelpText(fmt.Sprintf("%d alt kategori bulundu", len(options)))
})

// Karmaşık seçenek nesneleri

productField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    options := map[string]interface{}{
        "1": map[string]interface{}{
            "label": "Premium Paket",
            "price": 1000,
            "description": "Tüm özellikler dahil",
            "icon": "star",
        },
        "2": map[string]interface{}{
            "label": "Standart Paket",
            "price": 500,
            "description": "Temel özellikler",
            "icon": "check",
        },
    }

    return NewFieldUpdate().SetOptions(options)
})

// Filtrelenmiş seçenekler

priceRangeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    priceRange := formData["price_range"].(string)

    var products []Product
    db := ctx.Locals("db").(*gorm.DB)

    switch priceRange {
    case "low":
        db.Where("price < ?", 100).Find(&products)
    case "medium":
        db.Where("price BETWEEN ? AND ?", 100, 500).Find(&products)
    case "high":
        db.Where("price > ?", 500).Find(&products)
    }

    options := make(map[string]interface{})
    for _, p := range products {
        options[fmt.Sprintf("%d", p.ID)] = fmt.Sprintf("%s - %.2f TL", p.Name, p.Price)
    }

    return NewFieldUpdate().SetOptions(options)
})

// Rol bazlı seçenekler userRole := ctx.Locals("user_role").(string) var statusOptions map[string]interface{}

if userRole == "admin" {
    statusOptions = map[string]interface{}{
        "draft": "Taslak",
        "pending": "Beklemede",
        "approved": "Onaylandı",
        "rejected": "Reddedildi",
        "archived": "Arşivlendi",
    }
} else {
    statusOptions = map[string]interface{}{
        "draft": "Taslak",
        "pending": "Beklemede",
    }
}

return NewFieldUpdate().SetOptions(statusOptions) ```

Önemli Notlar

- **Map Formatı**: Key-value çiftleri şeklinde olmalıdır - **Değer Temizleme**: Seçenekler değiştiğinde mevcut değeri SetValue(nil) ile temizleyin - **Performans**: Büyük seçenek listeleri için pagination veya lazy loading düşünün - **Veritabanı Sorguları**: Context üzerinden DB erişimi yapılabilir ancak performans etkileri göz önünde bulundurulmalıdır - **Boş Seçenekler**: Boş map göndermek seçenekleri temizler

Best Practices

- Cascade dropdown'larda üst seçim değiştiğinde alt seçimi temizleyin - Veritabanı sorgularını optimize edin (index, limit kullanın) - Büyük listelerde arama/filtreleme özelliği ekleyin - Seçenek sayısını kullanıcıya bildirin (yardım metni ile) - Hata durumlarını ele alın (veritabanı hatası, boş sonuç vb.) - Cache mekanizması kullanarak performansı artırın

Avantajlar

- Dinamik ve esnek seçim listeleri sağlar - Cascade dropdown'ları kolayca uygular - Kullanıcı deneyimini iyileştirir - İş kurallarını kolayca uygular - Veritabanı entegrasyonu kolaydır

Dezavantajlar

- Büyük seçenek listeleri performans sorunlarına yol açabilir - Veritabanı sorguları her değişiklikte çalışabilir (performans) - Karmaşık bağımlılık zincirleri debug edilmesi zor olabilir

Performans İpuçları

- Veritabanı sorgularını cache'leyin - Lazy loading kullanın (büyük listeler için) - Pagination ekleyin (1000+ seçenek için) - Debounce mekanizması kullanın (arama için) - Index'leri optimize edin

func (*FieldUpdate) SetPlaceholder

func (u *FieldUpdate) SetPlaceholder(text string) *FieldUpdate

SetPlaceholder, alanın placeholder (yer tutucu) metnini ayarlar.

Genel Bakış

Bu metod, bir form alanının içinde gösterilen placeholder metnini dinamik olarak günceller. Placeholder özelliğini verilen string ile ayarlar ve method chaining desteği için *FieldUpdate döndürür. Placeholder metinleri, alan boşken kullanıcıya ne girmesi gerektiği hakkında ipucu verir.

Kullanım Senaryoları

- **Format Örneği**: Beklenen format için örnek göster (örn: "ö[email protected]") - **Değer Önerisi**: Tipik değer örnekleri göster (örn: "Ahmet Yılmaz") - **Arama İpucu**: Arama alanlarında ne aranabileceğini göster - **Dinamik İpuçları**: Kullanıcı seçimlerine göre farklı örnekler göster - **Birim Belirtme**: Sayısal alanlar için birim göster (örn: "0.00 TL")

Parametreler

- `text`: Gösterilecek placeholder metni (string)

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().SetPlaceholder("Adınızı girin")

// Format örneği emailField := NewFieldUpdate().

SetPlaceholder("[email protected]").
SetHelpText("Geçerli bir e-posta adresi girin")

// Dinamik placeholder

searchTypeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    searchType := formData["search_type"]
    switch searchType {
    case "name":
        return NewFieldUpdate().SetPlaceholder("Örn: Ahmet Yılmaz")
    case "email":
        return NewFieldUpdate().SetPlaceholder("Örn: [email protected]")
    case "phone":
        return NewFieldUpdate().SetPlaceholder("Örn: 0532 123 45 67")
    default:
        return NewFieldUpdate().SetPlaceholder("Arama...")
    }
})

// Birim belirtme priceField := NewFieldUpdate().

SetPlaceholder("0.00 TL").
SetHelpText("Ürün fiyatını girin")

// Bağlamsal örnek

countryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    country := formData["country"]
    if country == "TR" {
        return NewFieldUpdate().
            SetPlaceholder("İstanbul, Ankara, İzmir...").
            SetHelpText("Türkiye'deki bir şehir seçin")
    } else if country == "US" {
        return NewFieldUpdate().
            SetPlaceholder("New York, Los Angeles, Chicago...").
            SetHelpText("Select a US city")
    }
    return NewFieldUpdate().SetPlaceholder("Şehir seçin...")
})

// Arama alanı searchField := NewFieldUpdate().

SetPlaceholder("Ürün adı, kategori veya marka ara...").
SetHelpText("En az 3 karakter girin")

// Sayısal alan quantityField := NewFieldUpdate().

SetPlaceholder("1").
SetHelpText("Sipariş miktarını girin (minimum: 1)")

// Tarih alanı dateField := NewFieldUpdate().

SetPlaceholder("GG/AA/YYYY").
SetHelpText("Doğum tarihinizi girin")

// Çoklu dil desteği language := ctx.Locals("language").(string)

if language == "tr" {
    return NewFieldUpdate().SetPlaceholder("Mesajınızı yazın...")
} else {
    return NewFieldUpdate().SetPlaceholder("Type your message...")
}

```

Önemli Notlar

- **Görünürlük**: Placeholder sadece alan boşken görünür, değer girildiğinde kaybolur - **Erişilebilirlik**: Placeholder, label'ın yerini tutmamalıdır (her ikisi de olmalı) - **Uzunluk**: Kısa ve öz olmalıdır (ideal: 2-5 kelime) - **Renk**: Genelde soluk renkte gösterilir, asıl değerle karıştırılmamalı - **Validasyon**: Placeholder metni validasyon kuralı değildir, sadece ipucudur

Best Practices

- Gerçekçi ve anlamlı örnekler kullanın - "Örn:" veya "..." gibi önekler ekleyerek placeholder olduğunu belirtin - Label ile tekrar etmeyin, ek bilgi verin - Kısa ve öz tutun (uzun metinler kesilir) - Birim veya format bilgisi içeren örnekler verin - Çoklu dil desteği için i18n kullanın

Placeholder vs HelpText Karşılaştırması

| Özellik | Placeholder | HelpText | |---------|-------------|----------| | Konum | Alan içinde | Alan dışında (altında/yanında) | | Görünürlük | Sadece boşken | Her zaman | | Uzunluk | Kısa (2-5 kelime) | Orta (1-2 cümle) | | Amaç | Örnek göster | Açıklama yap | | Erişilebilirlik | Düşük | Yüksek |

Avantajlar

- Kullanıcıya hızlı ipucu verir - Form alanını temiz tutar - Örnek göstererek anlaşılırlığı artırır - Kullanıcı hatalarını azaltır

func (*FieldUpdate) SetRules

func (u *FieldUpdate) SetRules(rules []ValidationRule) *FieldUpdate

SetRules, alanın validasyon kurallarını ayarlar.

Genel Bakış

Bu metod, bir form alanının tüm validasyon kurallarını tek seferde ayarlar. Mevcut kuralları tamamen değiştirir. Rules özelliğini verilen slice ile günceller ve method chaining desteği için *FieldUpdate döndürür. Dinamik validasyon senaryoları için kritik öneme sahiptir.

Kullanım Senaryoları

- **Koşullu Validasyon**: Kullanıcı seçimlerine göre farklı validasyon kuralları uygula - **Dinamik Kural Setleri**: İş kurallarına göre validasyon kurallarını değiştir - **Rol Bazlı Validasyon**: Kullanıcı rolüne göre farklı validasyon seviyeleri - **Adım Bazlı Validasyon**: Form adımlarına göre farklı kurallar uygula - **Toplu Kural Güncelleme**: Birden fazla kuralı aynı anda güncelle

Parametreler

- `rules`: ValidationRule slice'ı - Uygulanacak tüm validasyon kuralları

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım

rules := []ValidationRule{
    {Type: "required", Message: "Bu alan zorunludur"},
    {Type: "min", Value: 3, Message: "En az 3 karakter olmalıdır"},
    {Type: "max", Value: 50, Message: "En fazla 50 karakter olabilir"},
}

update := NewFieldUpdate().SetRules(rules)

// Koşullu validasyon - Kullanıcı tipine göre

userTypeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    userType := formData["user_type"].(string)

    var rules []ValidationRule
    if userType == "corporate" {
        // Kurumsal kullanıcılar için sıkı kurallar
        rules = []ValidationRule{
            {Type: "required", Message: "Vergi numarası zorunludur"},
            {Type: "length", Value: 10, Message: "Vergi numarası 10 haneli olmalıdır"},
            {Type: "numeric", Message: "Sadece rakam içermelidir"},
            {Type: "tax_number", Message: "Geçerli bir vergi numarası değil"},
        }
    } else {
        // Bireysel kullanıcılar için esnek kurallar
        rules = []ValidationRule{
            {Type: "length", Value: 11, Message: "TC Kimlik No 11 haneli olmalıdır"},
            {Type: "numeric", Message: "Sadece rakam içermelidir"},
        }
    }

    return NewFieldUpdate().
        SetRules(rules).
        MakeRequired().
        SetHelpText(fmt.Sprintf("%s için kimlik bilgisi", userType))
})

// Adım bazlı validasyon

stepField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    step := formData["current_step"].(int)

    var emailRules []ValidationRule
    if step == 1 {
        // İlk adımda basit validasyon
        emailRules = []ValidationRule{
            {Type: "required", Message: "E-posta zorunludur"},
            {Type: "email", Message: "Geçerli bir e-posta adresi girin"},
        }
    } else if step == 2 {
        // İkinci adımda detaylı validasyon
        emailRules = []ValidationRule{
            {Type: "required", Message: "E-posta zorunludur"},
            {Type: "email", Message: "Geçerli bir e-posta adresi girin"},
            {Type: "unique", Table: "users", Column: "email", Message: "Bu e-posta zaten kullanılıyor"},
            {Type: "domain_whitelist", Value: []string{"company.com", "partner.com"}, Message: "Sadece şirket e-postaları kabul edilir"},
        }
    }

    return NewFieldUpdate().SetRules(emailRules)
})

// Rol bazlı validasyon userRole := ctx.Locals("user_role").(string) var priceRules []ValidationRule

if userRole == "admin" {
    // Admin için sınırsız
    priceRules = []ValidationRule{
        {Type: "required", Message: "Fiyat zorunludur"},
        {Type: "numeric", Message: "Geçerli bir sayı girin"},
        {Type: "min", Value: 0, Message: "Fiyat negatif olamaz"},
    }
} else if userRole == "manager" {
    // Manager için sınırlı
    priceRules = []ValidationRule{
        {Type: "required", Message: "Fiyat zorunludur"},
        {Type: "numeric", Message: "Geçerli bir sayı girin"},
        {Type: "min", Value: 0, Message: "Fiyat negatif olamaz"},
        {Type: "max", Value: 10000, Message: "Maksimum 10.000 TL girebilirsiniz"},
    }
} else {
    // Normal kullanıcı için çok sınırlı
    priceRules = []ValidationRule{
        {Type: "required", Message: "Fiyat zorunludur"},
        {Type: "numeric", Message: "Geçerli bir sayı girin"},
        {Type: "min", Value: 0, Message: "Fiyat negatif olamaz"},
        {Type: "max", Value: 1000, Message: "Maksimum 1.000 TL girebilirsiniz"},
    }
}

return NewFieldUpdate().

SetRules(priceRules).
SetHelpText(fmt.Sprintf("Rol: %s - Fiyat limitleri uygulanıyor", userRole))

// Ürün tipine göre validasyon

productTypeField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    productType := formData["product_type"].(string)

    var descriptionRules []ValidationRule
    if productType == "premium" {
        // Premium ürünler için detaylı açıklama zorunlu
        descriptionRules = []ValidationRule{
            {Type: "required", Message: "Premium ürünler için açıklama zorunludur"},
            {Type: "min", Value: 100, Message: "En az 100 karakter olmalıdır"},
            {Type: "max", Value: 5000, Message: "En fazla 5000 karakter olabilir"},
            {Type: "rich_text", Message: "Zengin metin formatı gereklidir"},
        }
    } else {
        // Standart ürünler için basit açıklama
        descriptionRules = []ValidationRule{
            {Type: "min", Value: 20, Message: "En az 20 karakter olmalıdır"},
            {Type: "max", Value: 500, Message: "En fazla 500 karakter olabilir"},
        }
    }

    return NewFieldUpdate().SetRules(descriptionRules)
})

// Boş kural seti (tüm validasyonları kaldır) update := NewFieldUpdate().SetRules([]ValidationRule{}) ```

Önemli Notlar

- **Mevcut Kuralları Değiştirir**: SetRules() mevcut tüm kuralları siler ve yenileriyle değiştirir - **Boş Slice**: Boş slice göndermek tüm validasyon kurallarını kaldırır - **Kural Sırası**: Kurallar verilen sırada uygulanır - **Performans**: Çok fazla kural performansı etkileyebilir - **Sunucu Tarafı**: Client-side validasyon yeterli değildir, sunucu tarafında da validasyon yapın

ValidationRule Yapısı

```go

type ValidationRule struct {
    Type    string      // Kural tipi: "required", "min", "max", "email", "numeric" vb.
    Value   interface{} // Kural değeri (min/max için sayı, pattern için regex vb.)
    Message string      // Hata mesajı
    Table   string      // Unique kontrolü için tablo adı
    Column  string      // Unique kontrolü için kolon adı
}

```

Yaygın Kural Tipleri

- `required`: Alan zorunludur - `min`: Minimum değer/uzunluk - `max`: Maximum değer/uzunluk - `email`: E-posta formatı - `numeric`: Sayısal değer - `alpha`: Sadece harf - `alphanumeric`: Harf ve rakam - `url`: URL formatı - `regex`: Regex pattern - `unique`: Veritabanında benzersiz - `length`: Sabit uzunluk - `in`: Belirli değerlerden biri - `not_in`: Belirli değerlerden hiçbiri

Best Practices

- Kullanıcı dostu hata mesajları yazın - Gereksiz kurallardan kaçının (performans) - Kuralları mantıksal sıraya göre düzenleyin (required önce, detaylı kurallar sonra) - Sunucu tarafında da aynı kuralları uygulayın - Karmaşık kurallar için custom validator yazın - Hata mesajlarında örnek verin

Avantajlar

- Dinamik ve esnek validasyon sağlar - İş kurallarını kolayca uygular - Kullanıcı deneyimini iyileştirir - Veri bütünlüğünü sağlar - Toplu kural güncellemesi yapar

Dezavantajlar

- Mevcut kuralları tamamen değiştirir (dikkatli kullanılmalı) - Çok fazla kural performansı etkileyebilir - Karmaşık kural setleri yönetimi zorlaştırabilir

SetRules vs AddRule Karşılaştırması

| Özellik | SetRules | AddRule | |---------|----------|---------| | Mevcut Kurallar | Siler ve değiştirir | Korur ve ekler | | Kullanım | Toplu güncelleme | Tekli ekleme | | Performans | Tek seferde | Her çağrıda | | Esneklik | Düşük | Yüksek | | Kullanım Amacı | Tüm kuralları değiştir | Kural ekle |

func (*FieldUpdate) SetValue

func (u *FieldUpdate) SetValue(value interface{}) *FieldUpdate

SetValue, alanın değerini programatik olarak ayarlar.

Genel Bakış

Bu metod, bir form alanının değerini programatik olarak ayarlar. Value özelliğini verilen değer ile günceller ve method chaining desteği için *FieldUpdate döndürür. Bu özellik, hesaplanan değerler, otomatik doldurma ve değer senkronizasyonu için kullanılır.

Kullanım Senaryoları

- **Hesaplanan Değerler**: Diğer alanların değerlerine göre otomatik hesaplama yap - **Otomatik Doldurma**: Kullanıcı seçimlerine göre alanları otomatik doldur - **Değer Senkronizasyonu**: Bir alanın değerini diğer alanlara kopyala - **Varsayılan Değerler**: Koşullara göre varsayılan değerler ata - **Değer Temizleme**: Belirli koşullarda alanları temizle (nil) - **Format Dönüşümü**: Bir formattan diğerine dönüştür

Parametreler

- `value`: Atanacak değer (interface{} - herhangi bir tip olabilir)

  • string, int, float64, bool, nil, map, slice vb.

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().SetValue("Yeni değer")

// Değer temizleme update := NewFieldUpdate().SetValue(nil)

// Hesaplanan değer - Toplam hesaplama

quantityField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    quantity := formData["quantity"].(float64)
    price := formData["price"].(float64)
    total := quantity * price

    // Toplam alanını güncelle
    return NewFieldUpdate().
        SetValue(total).
        MakeReadOnly().
        SetHelpText(fmt.Sprintf("Toplam: %.2f TL", total))
})

// Otomatik doldurma - Şehir seçimine göre posta kodu

cityField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    city := formData["city"].(string)

    // Şehir kodlarını map'ten al
    cityCodes := map[string]string{
        "istanbul": "34",
        "ankara": "06",
        "izmir": "35",
    }

    postalCode := cityCodes[city]
    return NewFieldUpdate().
        SetValue(postalCode).
        SetHelpText(fmt.Sprintf("%s için posta kodu: %s", city, postalCode))
})

// Değer senkronizasyonu - E-posta'yı kullanıcı adına kopyala

emailField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    email := formData["email"].(string)
    autoFillUsername := formData["auto_fill_username"].(bool)

    if autoFillUsername {
        // E-posta'nın @ öncesi kısmını kullanıcı adı olarak ata
        username := strings.Split(email, "@")[0]
        return NewFieldUpdate().
            SetValue(username).
            SetHelpText("E-posta adresinizden otomatik oluşturuldu")
    }
    return nil
})

// Cascade seçim temizleme

countryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    // Ülke değiştiğinde şehir seçimini temizle
    return NewFieldUpdate().
        SetValue(nil).
        SetHelpText("Lütfen yeni ülkeye göre şehir seçin")
})

// Format dönüşümü - Telefon numarası formatlama

phoneField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    phone := formData["phone"].(string)

    // Sadece rakamları al
    digits := regexp.MustCompile(`\D`).ReplaceAllString(phone, "")

    // Formatla: (0532) 123 45 67
    if len(digits) == 11 {
        formatted := fmt.Sprintf("(%s) %s %s %s",
            digits[0:4], digits[4:7], digits[7:9], digits[9:11])
        return NewFieldUpdate().
            SetValue(formatted).
            SetHelpText("Telefon numarası formatlandı")
    }
    return nil
})

// Koşullu varsayılan değer

paymentMethodField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    paymentMethod := formData["payment_method"].(string)

    if paymentMethod == "installment" {
        // Taksitli ödeme seçildiğinde varsayılan taksit sayısı
        return NewFieldUpdate().
            SetValue(3).
            SetHelpText("Varsayılan: 3 taksit")
    }
    return NewFieldUpdate().SetValue(nil)
})

// Veritabanından değer çekme

productField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    productID := formData["product_id"].(int)

    // Ürün fiyatını veritabanından çek
    var product Product
    db := ctx.Locals("db").(*gorm.DB)
    db.First(&product, productID)

    // Fiyat alanını otomatik doldur
    return NewFieldUpdate().
        SetValue(product.Price).
        MakeReadOnly().
        SetHelpText(fmt.Sprintf("Ürün fiyatı: %.2f TL", product.Price))
})

// Karmaşık nesne değeri

addressField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    addressData := map[string]interface{}{
        "street": "Atatürk Caddesi",
        "city": "İstanbul",
        "postal_code": "34000",
        "country": "TR",
    }

    return NewFieldUpdate().SetValue(addressData)
})

```

Önemli Notlar

- **Tip Güvenliği**: interface{} kullanıldığı için tip dönüşümlerine dikkat edin - **Nil Değer**: nil göndermek alanı temizler - **Validasyon**: SetValue ile atanan değerler de validasyon kurallarına tabidir - **Kullanıcı Girişi**: Programatik değer ataması kullanıcı girişini ezer - **ReadOnly ile Kullanım**: Hesaplanan değerler için MakeReadOnly() ile birlikte kullanın

Best Practices

- Hesaplanan değerler için MakeReadOnly() kullanın - Tip dönüşümlerinde hata kontrolü yapın - Cascade seçimlerde önceki değeri temizleyin (nil) - Kullanıcıya değerin nereden geldiğini açıklayın (yardım metni) - Veritabanı sorgularında hata kontrolü yapın - Format dönüşümlerinde validasyon yapın

Avantajlar

- Otomatik hesaplama sağlar - Kullanıcı deneyimini iyileştirir - Veri tutarlılığını sağlar - Form doldurma süresini kısaltır - Hata oranını azaltır

Dezavantajlar

- Yanlış kullanımda kullanıcı girişini ezebilir - Tip güvenliği yoktur (interface{}) - Karmaşık hesaplamalarda performans sorunları olabilir

Güvenlik Notları

- Kullanıcı girişini doğrudan kullanmadan önce sanitize edin - Veritabanı sorgularında SQL injection'a dikkat edin - Hassas bilgileri (şifre, kredi kartı) SetValue ile atamayın - Sunucu tarafında da aynı hesaplamaları yapın (güvenlik)

func (*FieldUpdate) Show

func (u *FieldUpdate) Show() *FieldUpdate

Show, alanı görünür hale getirir.

Genel Bakış

Bu metod, bir form alanının kullanıcı arayüzünde görünür olmasını sağlar. Visible özelliğini true olarak ayarlar ve method chaining desteği için *FieldUpdate döndürür.

Kullanım Senaryoları

- Koşullu alan görünürlüğü: Belirli bir değer seçildiğinde ilgili alanları göster - Dinamik form yapısı: Kullanıcı seçimlerine göre form alanlarını göster/gizle - Wizard formlar: Adım adım form akışında ilgili alanları göster - Koşullu validasyon: Görünür olan alanlar için validasyon uygula

Dönüş Değeri

`*FieldUpdate`: Method chaining için güncellenmiş FieldUpdate pointer'ı

Kullanım Örneği

```go // Basit kullanım update := NewFieldUpdate().Show()

// Koşullu görünürlük

if formData["has_company"] == true {
    return NewFieldUpdate().Show().MakeRequired()
}

// Çoklu alan kontrolü

countryField.OnChange(func(field *Schema, formData map[string]interface{}, ctx *fiber.Ctx) *FieldUpdate {
    country := formData["country"]
    if country == "TR" {
        // Türkiye seçildiğinde TC Kimlik No alanını göster
        return NewFieldUpdate().Show().MakeRequired().SetHelpText("11 haneli TC Kimlik No")
    }
    return NewFieldUpdate().Hide()
})

// Method chaining ile birlikte kullanım update := NewFieldUpdate().

Show().
MakeRequired().
Enable().
SetHelpText("Bu alan artık görünür ve zorunlu")

```

Önemli Notlar

- Show() çağrıldığında alan görünür olur ancak disabled durumu değişmez - Görünür olan alanlar için validasyon kuralları uygulanır - Hide() ile gizlenen alanlar için validasyon atlanır - Method chaining desteklenir, zincirleme çağrılar yapılabilir

Best Practices

- Show() ile birlikte MakeRequired() veya MakeOptional() kullanarak validasyon durumunu belirtin - Görünür hale getirilen alanlara uygun yardım metni ekleyin - Koşullu görünürlükte her iki durumu da (Show/Hide) ele alın

type Filterable

type Filterable struct {
	// contains filtered or unexported fields
}

Filterable, alanların filtrelenebilir olmasını sağlayan bir mixin'dir.

Filtrelenebilir davranış, filtre seçenekleri ve özel filtre callback'leri için yapılandırma sağlar. Bu callback'ler veritabanı sorgusunu değiştirebilir.

Kullanım

type SelectField struct {
    fields.Base
    fields.Filterable
}

field := &SelectField{}
field.SetFilterable(true)
field.SetFilterOptions(map[string]string{
    "active": "Aktif",
    "inactive": "İnaktif",
})
field.SetFilterCallback(func(db *gorm.DB, value any) *gorm.DB {
    return db.Where("status = ?", value)
})

Daha fazla örnek için docs/Fields.md dosyasına bakın.

func (*Filterable) GetFilterCallback

func (f *Filterable) GetFilterCallback() func(*gorm.DB, any) *gorm.DB

GetFilterCallback, filtre callback fonksiyonunu döndürür. Hiçbir callback ayarlanmamışsa nil döndürür.

Döndürür:

  • Filtre callback fonksiyonu veya ayarlanmamışsa nil

func (*Filterable) GetFilterOptions

func (f *Filterable) GetFilterOptions() map[string]string

GetFilterOptions, filtre seçeneklerini döndürür. Hiçbir seçenek yapılandırılmamışsa boş bir map döndürür.

Döndürür:

  • Filtre seçenekleri için değer-etiket eşlemesi

func (*Filterable) IsFilterable

func (f *Filterable) IsFilterable() bool

IsFilterable, alanın filtrelenebilir olup olmadığını döndürür.

Döndürür:

  • Alan filtrelenebilirse true, değilse false

func (*Filterable) SetFilterCallback

func (f *Filterable) SetFilterCallback(cb func(*gorm.DB, any) *gorm.DB)

SetFilterCallback, özel bir filtre callback fonksiyonu ayarlar.

Callback, GORM veritabanı örneğini ve filtre değerini alır, ve filtre sorgusu uygulanmış değiştirilmiş bir veritabanı örneği döndürmelidir.

Parametreler:

  • cb: Özel filtre mantığı için veritabanı sorgusunu değiştiren fonksiyon

Örnek:

field.SetFilterCallback(func(db *gorm.DB, value any) *gorm.DB {
    status, ok := value.(string)
    if !ok {
        return db
    }
    return db.Where("status = ?", status)
})

func (*Filterable) SetFilterOptions

func (f *Filterable) SetFilterOptions(options map[string]string)

SetFilterOptions, kullanılabilir filtre seçeneklerini ayarlar.

Seçenekler, kullanıcıların önceden tanımlanmış değerlere göre filtreleme yapmasına izin veren bir açılır liste veya onay kutusu listesi olarak UI'da gösterilir.

Parametreler:

  • options: Filtre seçenekleri için değer-etiket eşlemesi

Örnek:

field.SetFilterOptions(map[string]string{
    "draft": "Taslak",
    "published": "Yayınlandı",
    "archived": "Arşivlendi",
})

func (*Filterable) SetFilterable

func (f *Filterable) SetFilterable(filterable bool)

SetFilterable, alanın filtrelenebilir olup olmadığını ayarlar.

Parametreler:

  • filterable: Filtrelemeyi etkinleştirmek için true, devre dışı bırakmak için false

Örnek:

field.SetFilterable(true)

type GormConfig

type GormConfig struct {
	// Anahtar Yapılandırması
	PrimaryKey    bool   `json:"-"` // Birincil anahtar mı?
	AutoIncrement bool   `json:"-"` // Otomatik artış mı?
	IDType        string `json:"-"` // ID tipi: "uuid" (shared/uuid), "snowflake" (github.com/bwmarrin/snowflake), "ulid" (github.com/oklog/ulid)

	// Sütun Yapılandırması
	Column string `json:"-"` // Özel sütun adı (varsayılan: Key'den türetilir)
	Type   string `json:"-"` // SQL tipi (örn: "varchar(255)", "text", "decimal(10,2)")
	Size   int    `json:"-"` // Sütun boyutu (VARCHAR için)

	// Sayısal Hassasiyet
	Precision int `json:"-"` // Ondalık hassasiyet (DECIMAL tipi için)
	Scale     int `json:"-"` // Ondalık ölçek (DECIMAL tipi için)

	// İndeks Yapılandırması
	Index         bool   `json:"-"` // Normal indeks oluştur
	UniqueIndex   bool   `json:"-"` // Benzersiz indeks oluştur
	FullTextIndex bool   `json:"-"` // Fulltext indeks oluştur
	IndexName     string `json:"-"` // Özel indeks adı

	// Varsayılan Değer
	Default interface{} `json:"-"` // Varsayılan değer

	// Kısıtlamalar
	NotNull    bool   `json:"-"` // NOT NULL kısıtlaması
	Comment    string `json:"-"` // Sütun yorumu
	SoftDelete bool   `json:"-"` // Soft delete desteği (DeletedAt alanı)

	// İlişki Yapılandırması (Foreign Key)
	ForeignKey      string `json:"-"` // Foreign key alanı (örn: "AuthorID")
	References      string `json:"-"` // Referans tablo.alan (örn: "users.id")
	OnDelete        string `json:"-"` // ON DELETE davranışı (CASCADE, SET NULL, vb.)
	OnUpdate        string `json:"-"` // ON UPDATE davranışı
	ManyToManyTable string `json:"-"` // Many-to-many ara tablo adı
	JoinForeignKey  string `json:"-"` // Join tablosundaki foreign key
	JoinReferences  string `json:"-"` // Join tablosundaki referans
}

GormConfig, alan için GORM veritabanı yapılandırmasını tanımlar. Bu yapı, alan tanımlarından otomatik migration ve model oluşturma için kullanılır.

func NewGormConfig

func NewGormConfig() *GormConfig

NewGormConfig, varsayılan değerlerle yeni bir GormConfig oluşturur.

func (*GormConfig) ToGormTag

func (g *GormConfig) ToGormTag() string

ToGormTag, GormConfig'i GORM struct tag string'ine dönüştürür.

func (*GormConfig) WithAutoIncrement

func (g *GormConfig) WithAutoIncrement() *GormConfig

WithAutoIncrement, otomatik artış olarak işaretler.

func (*GormConfig) WithColumn

func (g *GormConfig) WithColumn(name string) *GormConfig

WithColumn, özel sütun adı belirler.

func (*GormConfig) WithComment

func (g *GormConfig) WithComment(comment string) *GormConfig

WithComment, sütun yorumu ekler.

func (*GormConfig) WithDefault

func (g *GormConfig) WithDefault(value interface{}) *GormConfig

WithDefault, varsayılan değer belirler.

func (*GormConfig) WithForeignKey

func (g *GormConfig) WithForeignKey(fk, references string) *GormConfig

WithForeignKey, foreign key ilişkisi tanımlar.

func (*GormConfig) WithFullTextIndex

func (g *GormConfig) WithFullTextIndex(name ...string) *GormConfig

WithFullTextIndex, fulltext indeks oluşturur.

func (*GormConfig) WithIDType

func (g *GormConfig) WithIDType(idType string) *GormConfig

WithIDType, ID tipini belirler (uuid, snowflake, ulid).

func (*GormConfig) WithIndex

func (g *GormConfig) WithIndex(name ...string) *GormConfig

WithIndex, normal indeks oluşturur.

func (*GormConfig) WithManyToMany

func (g *GormConfig) WithManyToMany(tableName string) *GormConfig

WithManyToMany, many-to-many ilişki için ara tablo tanımlar.

func (*GormConfig) WithNotNull

func (g *GormConfig) WithNotNull() *GormConfig

WithNotNull, NOT NULL kısıtlaması ekler.

func (*GormConfig) WithOnDelete

func (g *GormConfig) WithOnDelete(action string) *GormConfig

WithOnDelete, ON DELETE davranışını belirler.

func (*GormConfig) WithOnUpdate

func (g *GormConfig) WithOnUpdate(action string) *GormConfig

WithOnUpdate, ON UPDATE davranışını belirler.

func (*GormConfig) WithPrecision

func (g *GormConfig) WithPrecision(precision, scale int) *GormConfig

WithPrecision, ondalık hassasiyeti belirler.

func (*GormConfig) WithPrimaryKey

func (g *GormConfig) WithPrimaryKey() *GormConfig

WithPrimaryKey, birincil anahtar olarak işaretler.

func (*GormConfig) WithSize

func (g *GormConfig) WithSize(size int) *GormConfig

WithSize, sütun boyutunu belirler.

func (*GormConfig) WithSnowflake

func (g *GormConfig) WithSnowflake() *GormConfig

WithSnowflake, Snowflake tipinde ID kullanır.

func (*GormConfig) WithSoftDelete

func (g *GormConfig) WithSoftDelete() *GormConfig

WithSoftDelete, soft delete desteği ekler.

func (*GormConfig) WithType

func (g *GormConfig) WithType(sqlType string) *GormConfig

WithType, SQL tipini belirler.

func (*GormConfig) WithULID

func (g *GormConfig) WithULID() *GormConfig

WithULID, ULID tipinde ID kullanır.

func (*GormConfig) WithUUID

func (g *GormConfig) WithUUID() *GormConfig

WithUUID, UUID tipinde ID kullanır.

func (*GormConfig) WithUniqueIndex

func (g *GormConfig) WithUniqueIndex(name ...string) *GormConfig

WithUniqueIndex, benzersiz indeks oluşturur.

type HasManyField

type HasManyField struct {
	Schema
	RelatedResourceSlug string
	RelatedResource     interface{} // resource.Resource interface (interface{} to avoid circular import)
	ForeignKeyColumn    string
	OwnerKeyColumn      string
	QueryCallback       func(query interface{}) interface{}
	LoadingStrategy     LoadingStrategy
	GormRelationConfig  *RelationshipGormConfig
	FullDataMode        bool // true: raw data + title, false (default): minimal format (id + title)
}

HasManyField, one-to-many ilişkiyi temsil eder (örn. Author -> Posts).

HasMany ilişkisi, bir kaydın birden fazla ilişkili kayda sahip olduğunu belirtir. Bu, veritabanında ilişkili tabloda foreign key ile temsil edilir.

Kullanım Senaryoları

- **Author -> Posts**: Bir yazar birden fazla yazıya sahiptir - **Category -> Products**: Bir kategori birden fazla ürüne sahiptir - **User -> Comments**: Bir kullanıcı birden fazla yoruma sahiptir

Özellikler

- **Tip Güvenliği**: Resource instance veya string slug kullanılabilir - **Foreign Key Özelleştirme**: İlişkili tablodaki foreign key sütunu özelleştirilebilir - **Owner Key Özelleştirme**: Ana tablodaki referans sütunu özelleştirilebilir - **Eager/Lazy Loading**: Yükleme stratejisi seçimi - **GORM Yapılandırması**: Foreign key ve references özelleştirme

Kullanım Örneği

// String slug ile
field := fields.HasMany("Posts", "posts", "posts").
    ForeignKey("author_id").
    WithEagerLoad()

// Resource instance ile (tip güvenli)
field := fields.HasMany("Posts", "posts", blog.NewPostResource()).
    ForeignKey("author_id").
    WithEagerLoad()

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func HasMany

func HasMany(name, key string, relatedResource interface{}) *HasManyField

HasMany, yeni bir HasMany ilişki alanı oluşturur.

Bu fonksiyon, hem string slug hem de resource instance kabul eder. Resource instance kullanımı tip güvenliği sağlar ve refactoring'i kolaylaştırır.

Parametreler

- **name**: Alanın görünen adı (örn. "Posts", "Yazılar") - **key**: İlişki key'i (örn. "posts") - **relatedResource**: İlgili resource (string slug veya resource instance)

String Slug Kullanımı

field := fields.HasMany("Posts", "posts", "posts")

**Avantajlar:** - Basit ve hızlı - Circular import sorunu yok

**Dezavantajlar:** - Tip güvenliği yok - Refactoring zor - IDE desteği sınırlı

Resource Instance Kullanımı (Önerilen)

field := fields.HasMany("Posts", "posts", blog.NewPostResource())

**Avantajlar:** - ✅ Tip güvenliği (derleme zamanı kontrolü) - ✅ Refactoring desteği (resource adı değişirse otomatik güncellenir) - ✅ IDE desteği (autocomplete, go-to-definition) - ✅ Tablo adı otomatik alınır (resource.Slug())

**Dezavantajlar:** - Circular import'a dikkat edilmeli

Varsayılan Değerler

- **ForeignKeyColumn**: slug + "_id" (örn. "posts_id") - **OwnerKeyColumn**: "id" (ana tablonun primary key'i) - **LoadingStrategy**: EAGER_LOADING (N+1 sorgu problemini önler)

Döndürür:

  • Yapılandırılmış HasManyField pointer'ı

Daha fazla bilgi için docs/Relationships.md ve .docs/RESOURCE_BASED_RELATIONSHIPS.md dosyalarına bakın.

func (*HasManyField) AutoOptions

func (h *HasManyField) AutoOptions(displayField string) *HasManyField

AutoOptions, ilişkili tablodan otomatik options oluşturmayı etkinleştirir.

Bu metod, HasMany ilişkisinde ilişkili kayıtların otomatik olarak yüklenmesini ve frontend'de multi-select combobox'ta gösterilmesini sağlar.

Parametreler

- **displayField**: Option label'ı için kullanılacak sütun adı (örn. "title", "name")

Kullanım Örneği

// Author resource'unda Posts ilişkisi
field := fields.HasMany("Posts", "posts", "posts").
    AutoOptions("title").  // Post'ların "title" sütunu label olarak kullanılır
    ForeignKey("author_id").
    WithEagerLoad()

Backend Response Formatı

AutoOptions etkinleştirildiğinde, backend response'unda options otomatik olarak eklenir:

{
  "posts": {
    "key": "posts",
    "type": "relationship",
    "view": "has-many-field",
    "data": [1, 2, 3],
    "props": {
      "related_resource": "posts",
      "options": {
        "1": "First Post",
        "2": "Second Post",
        "3": "Third Post"
      }
    }
  }
}

Frontend Rendering

Frontend'de HasManyField componenti otomatik olarak: - Pre-loaded options'ları multi-select combobox'ta gösterir - Search fonksiyonu ile filtreleme yapar - Seçili değerleri chips olarak gösterir - Kullanıcı yeni kayıtlar seçebilir veya mevcut seçimleri kaldırabilir

Önemli Notlar

- displayField sütunu, ilişkili tabloda mevcut olmalıdır - Büyük veri setleri için (10,000+ kayıt) performans sorunları olabilir - Best practice: AutoOptions sadece küçük-orta veri setleri için kullanın - Null değerler için otomatik fallback kontrolü yapılır

Döndürür:

  • HasManyField pointer'ı (method chaining için)

func (*HasManyField) Count

func (h *HasManyField) Count() int64

Count returns the count of related resources

func (*HasManyField) Extract

func (h *HasManyField) Extract(resource interface{})

Extract, HasMany ilişkisi için özel veri çıkarma metodudur.

Bu metod, Schema'nın genel Extract metodunu override eder ve HasMany ilişkisi için özel işlem yapar. İlişkili kayıtları JSON tag'lere göre serialize eder.

İşleyiş

  1. Schema'nın Extract metodunu çağırır (mevcut davranışı korumak için)
  2. Eğer Data nil ise, boş array olarak ayarlar
  3. Eğer Data bir slice ise: a. Her kayıt için JSON marshaling yapar (JSON tag'ler otomatik kullanılır) b. JSON'dan map[string]interface{}'e unmarshal eder c. Bu map'leri data array'ine ekler

JSON Tag Kullanımı

Model'de tanımlı JSON tag'ler otomatik olarak kullanılır:

type Address struct {
    ID             uint   `json:"id"`
    OrganizationID uint   `json:"organization_id"`
    Name           string `json:"name"`
}

Sonuç: {"id": 1, "organization_id": 16, "name": "Adres"}

Parametreler

- resource: Veri çıkarılacak kaynak (struct veya map)

Kullanım Örneği

// Organization model'inde Addresses field'ı var
type Organization struct {
    ID        uint
    Name      string
    Addresses []Address
}

// HasMany field Extract çağrıldığında
field := fields.HasMany("Addresses", "addresses", "addresses")
field.Extract(&organization)
// field.Data artık [{"id": 1, "organization_id": 16, ...}] gibi JSON tag'lere göre serialize edilmiş kayıtlar içerir

func (*HasManyField) ForeignKey

func (h *HasManyField) ForeignKey(key string) *HasManyField

ForeignKey, foreign key sütun adını ayarlar.

Bu metod, ilişkili tablodaki foreign key sütununun adını özelleştirir. Varsayılan olarak slug + "_id" kullanılır.

Parametreler

- **key**: Foreign key sütun adı (örn. "author_id", "user_id", "category_id")

Kullanım Örneği

field := fields.HasMany("Posts", "posts", "posts").
    ForeignKey("author_id")
// Posts tablosunda "author_id" sütunu foreign key olarak kullanılır

Önemli Notlar

- Foreign key sütunu, ilişkili tabloda mevcut olmalıdır - Genellikle "parent_table_id" formatında olur (örn. "author_id", "category_id") - GORM tarafından otomatik olarak ilişki kurulumu için kullanılır

Döndürür:

  • HasManyField pointer'ı (method chaining için)

func (*HasManyField) GetDisplayKey

func (h *HasManyField) GetDisplayKey() string

GetDisplayKey returns the display key (not used for HasMany)

func (*HasManyField) GetForeignKeyColumn

func (h *HasManyField) GetForeignKeyColumn() string

GetForeignKeyColumn, foreign key sütun adını döndürür.

Bu metod, HasMany ilişkisinde kullanılan foreign key sütununun adını döndürür. Foreign key, ilişkili tablodaki referans sütunudur.

Dönüş Değeri

- Foreign key sütun adı (örn. "author_id", "user_id", "category_id")

Kullanım Örneği

field := fields.HasMany("Posts", "posts", "posts").ForeignKey("author_id")
foreignKey := field.GetForeignKeyColumn() // "author_id"

Döndürür:

  • Foreign key sütun adı

func (*HasManyField) GetLoadingStrategy

func (h *HasManyField) GetLoadingStrategy() LoadingStrategy

GetLoadingStrategy returns the loading strategy

func (*HasManyField) GetOwnerKeyColumn

func (h *HasManyField) GetOwnerKeyColumn() string

GetOwnerKeyColumn, owner key sütun adını döndürür.

Bu metod, HasMany ilişkisinde kullanılan owner key sütununun adını döndürür. Owner key, ana tablodaki referans sütunudur (genellikle primary key).

Dönüş Değeri

- Owner key sütun adı (örn. "id", "uuid")

Kullanım Örneği

field := fields.HasMany("Posts", "posts", "posts").OwnerKey("id")
ownerKey := field.GetOwnerKeyColumn() // "id"

Döndürür:

  • Owner key sütun adı

func (*HasManyField) GetQueryCallback

func (h *HasManyField) GetQueryCallback() func(interface{}) interface{}

GetQueryCallback returns the query callback

func (*HasManyField) GetRelatedResource

func (h *HasManyField) GetRelatedResource() interface{}

GetRelatedResource, ilişkili resource instance'ını döndürür.

Bu metod, RelatedResource'a erişim sağlar.

Dönüş Değeri

- interface{}: Resource instance'ı (resource.Resource interface) - nil: RelatedResource set edilmemişse

Kullanım Örneği

// Extract metodunda
if h.GetRelatedResource() == nil {
    // RelatedResource set edilmemiş, minimal format kullan
    return
}

Döndürür:

  • Resource instance'ı veya nil

func (*HasManyField) GetRelatedResourceSlug

func (h *HasManyField) GetRelatedResourceSlug() string

GetRelatedResourceSlug, ilişkili resource'un slug'ını döndürür.

Bu metod, RelatedResourceSlug'a erişim sağlar. Genellikle field_handler.go'da resource registry'den resource instance'ı almak için kullanılır.

Dönüş Değeri

- string: Resource slug'ı (örn. "users", "posts", "addresses")

Kullanım Örneği

// field_handler.go'da
if relField, ok := element.(*fields.HasManyField); ok {
    slug := relField.GetRelatedResourceSlug()
    relatedResource := resource.Get(slug)
    relField.SetRelatedResource(relatedResource)
}

Döndürür:

  • Resource slug'ı

func (*HasManyField) GetRelatedTableName

func (h *HasManyField) GetRelatedTableName() string

GetRelatedTableName, ilişkili tablo adını döndürür.

Bu metod, HasMany ilişkisinde kullanılan ilişkili tablonun adını döndürür. Raw SQL sorguları için kullanılır.

Dönüş Değeri

- İlişkili tablo adı (örn. "posts", "comments", "orders")

Kullanım Örneği

field := fields.HasMany("Posts", "posts", "posts")
tableName := field.GetRelatedTableName() // "posts"

Döndürür:

  • İlişkili tablo adı

func (*HasManyField) GetRelationshipName

func (h *HasManyField) GetRelationshipName() string

GetRelationshipName returns the relationship name

func (*HasManyField) GetRelationshipType

func (h *HasManyField) GetRelationshipType() string

GetRelationshipType returns the relationship type

func (*HasManyField) GetSearchableColumns

func (h *HasManyField) GetSearchableColumns() []string

GetSearchableColumns returns the searchable columns (not used for HasMany)

func (*HasManyField) GetTypes

func (h *HasManyField) GetTypes() map[string]string

GetTypes returns the type mappings (not used for HasMany)

func (*HasManyField) IsRequired

func (h *HasManyField) IsRequired() bool

IsRequired returns whether the field is required

func (*HasManyField) Label

func (h *HasManyField) Label(label string) Element

Label sets the field label while preserving HasMany concrete type in fluent chains.

func (*HasManyField) OwnerKey

func (h *HasManyField) OwnerKey(key string) *HasManyField

OwnerKey, owner key sütun adını ayarlar.

Bu metod, ana tablodaki referans sütununun adını özelleştirir. Varsayılan olarak "id" (primary key) kullanılır.

Parametreler

- **key**: Owner key sütun adı (örn. "id", "uuid", "author_id")

Kullanım Örneği

field := fields.HasMany("Posts", "posts", "posts").
    ForeignKey("author_id").
    OwnerKey("id")
// Authors tablosundaki "id" sütunu ile Posts tablosundaki "author_id" sütunu eşleştirilir

Önemli Notlar

- Owner key sütunu, ana tabloda mevcut olmalıdır - Genellikle primary key kullanılır ("id") - Özel durumlar için farklı sütunlar kullanılabilir (örn. "uuid")

Döndürür:

  • HasManyField pointer'ı (method chaining için)

func (*HasManyField) Placeholder

func (h *HasManyField) Placeholder(placeholder string) Element

Placeholder sets the field placeholder while preserving HasMany concrete type in fluent chains.

func (*HasManyField) Query

func (h *HasManyField) Query(fn func(interface{}) interface{}) *HasManyField

Query sets the query callback for customizing relationship query

func (*HasManyField) ResolveRelationship

func (h *HasManyField) ResolveRelationship(item interface{}) (interface{}, error)

ResolveRelationship resolves the relationship by loading all related resources

func (*HasManyField) Searchable

func (h *HasManyField) Searchable() Element

Searchable marks the element as searchable (implements Element interface)

func (*HasManyField) SetRelatedResource

func (h *HasManyField) SetRelatedResource(res interface{}) *HasManyField

SetRelatedResource, ilişkili resource instance'ını set eder.

Bu metod, RelatedResource'u runtime'da set etmek için kullanılır. Genellikle field_handler.go'da Extract çağrılmadan önce kullanılır.

Kullanım Senaryoları

- Circular dependency önlemek için string slug kullanıldığında - Runtime'da resource registry'den resource instance'ı alındığında - Field handler'da Extract öncesi RelatedResource'u set etmek

Parametreler

- res: Resource instance'ı (resource.Resource interface)

Kullanım Örneği

// field_handler.go'da Extract öncesi
if relField, ok := element.(*fields.HasManyField); ok {
    if relField.RelatedResource == nil {
        relatedResource := resource.Get(relField.RelatedResourceSlug)
        relField.SetRelatedResource(relatedResource)
    }
}
element.Extract(item)

Döndürür:

  • HasManyField pointer'ı (method chaining için)

func (*HasManyField) ValidateRelationship

func (h *HasManyField) ValidateRelationship(value interface{}) error

ValidateRelationship validates the relationship

func (*HasManyField) WithEagerLoad

func (h *HasManyField) WithEagerLoad() *HasManyField

WithEagerLoad sets the loading strategy to eager loading

func (*HasManyField) WithFullData

func (h *HasManyField) WithFullData() *HasManyField

WithFullData, ilişkili kayıtların tam verilerini (raw data + title) döndürmesini sağlar.

Bu metod, Extract metodunun davranışını değiştirir: - Varsayılan (FullDataMode=false): Minimal format (sadece id + title) - WithFullData() çağrıldığında (FullDataMode=true): Full format (tüm raw data + title)

Kullanım Senaryoları

- Frontend'de ilişkili kayıtların detaylı bilgilerini göstermek - Relationship field'larında tüm veriyi kullanmak - Custom rendering için ek field'lara ihtiyaç duymak

Kullanım Örneği

// Minimal format (varsayılan): {"id": 1, "title": "Adres 1"}
fields.HasMany("Addresses", "addresses", "addresses")

// Full format: {"ID": 1, "Name": "Adres 1", "City": "İstanbul", ..., "title": "Adres 1"}
fields.HasMany("Addresses", "addresses", "addresses").
    WithFullData()

Döndürür:

  • HasManyField pointer'ı (method chaining için)

func (*HasManyField) WithLazyLoad

func (h *HasManyField) WithLazyLoad() *HasManyField

WithLazyLoad sets the loading strategy to lazy loading

type HasOneField

type HasOneField struct {
	Schema
	RelatedResourceSlug string
	RelatedResource     interface{} // resource.Resource interface (interface{} to avoid circular import)
	ForeignKeyColumn    string
	OwnerKeyColumn      string
	QueryCallback       func(query interface{}) interface{}
	LoadingStrategy     LoadingStrategy
	GormRelationConfig  *RelationshipGormConfig
	// contains filtered or unexported fields
}

HasOneField, one-to-one ilişkiyi temsil eder (örn. User -> Profile).

HasOne ilişkisi, bir kaydın tek bir ilişkili kayda sahip olduğunu belirtir. Bu, veritabanında ilişkili tabloda foreign key ile temsil edilir.

Kullanım Senaryoları

- **User -> Profile**: Bir kullanıcının bir profili vardır - **Country -> Capital**: Bir ülkenin bir başkenti vardır - **Order -> Invoice**: Bir siparişin bir faturası vardır

Özellikler

- **Tip Güvenliği**: Resource instance veya string slug kullanılabilir - **Foreign Key Özelleştirme**: İlişkili tablodaki foreign key sütunu özelleştirilebilir - **Owner Key Özelleştirme**: Ana tablodaki referans sütunu özelleştirilebilir - **Eager/Lazy Loading**: Yükleme stratejisi seçimi - **GORM Yapılandırması**: Foreign key ve references özelleştirme - **Hover Card**: Index ve detail sayfalarında hover card desteği

Kullanım Örneği

// String slug ile
field := fields.HasOne("Profile", "profile", "profiles").
    ForeignKey("user_id").
    WithEagerLoad()

// Resource instance ile (tip güvenli)
field := fields.HasOne("Profile", "profile", user.NewProfileResource()).
    ForeignKey("user_id").
    WithEagerLoad()

// Hover card ile
field := fields.HasOne("Profile", "profile", "profiles").
    ForeignKey("user_id").
    WithHoverCard(fields.NewHoverCardConfig().
        WithAvatar("avatar", "").
        WithGrid([]fields.HoverCardGridField{
            {Key: "bio", Label: "Bio", Type: "text"},
            {Key: "location", Label: "Konum", Type: "text", Icon: "map-pin"},
        }, "2-column"))

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func HasOne

func HasOne(name, key string, relatedResource interface{}) *HasOneField

HasOne, yeni bir HasOne ilişki alanı oluşturur.

Bu fonksiyon, hem string slug hem de resource instance kabul eder. Resource instance kullanımı tip güvenliği sağlar ve refactoring'i kolaylaştırır.

Parametreler

- **name**: Alanın görünen adı (örn. "Profile", "Profil") - **key**: İlişki key'i (örn. "profile") - **relatedResource**: İlgili resource (string slug veya resource instance)

String Slug Kullanımı

field := fields.HasOne("Profile", "profile", "profiles")

Resource Instance Kullanımı (Önerilen)

field := fields.HasOne("Profile", "profile", user.NewProfileResource())

**Avantajlar:** - ✅ Tip güvenliği (derleme zamanı kontrolü) - ✅ Refactoring desteği - ✅ IDE desteği (autocomplete, go-to-definition)

Varsayılan Değerler

- **ForeignKeyColumn**: slug + "_id" (örn. "profiles_id") - **OwnerKeyColumn**: "id" (ana tablonun primary key'i) - **LoadingStrategy**: EAGER_LOADING (N+1 sorgu problemini önler)

Döndürür:

  • Yapılandırılmış HasOneField pointer'ı

func (*HasOneField) AutoOptions

func (h *HasOneField) AutoOptions(displayField string) *HasOneField

AutoOptions, ilişkili tablodan otomatik seçenek üretimini etkinleştirir.

Bu method, HasOne ilişkisinde ilişkili kayıtların otomatik olarak seçenek listesi olarak sunulmasını sağlar. Frontend'de dropdown veya select bileşenlerinde kullanılır.

Parametreler

- **displayField**: Seçenek etiketinde gösterilecek sütun adı (örn. "name", "title")

Kullanım Senaryoları

- **Profil Seçimi**: Kullanıcı profili seçerken profil adlarını gösterme - **Başkent Seçimi**: Ülke başkentlerini dropdown'da listeleme - **Fatura Seçimi**: Sipariş için fatura seçerken fatura numaralarını gösterme

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles").
    AutoOptions("full_name").
    ForeignKey("user_id")

Önemli Notlar

- displayField, ilişkili tabloda mevcut bir sütun olmalıdır - Büyük veri setlerinde performans sorunlarına neden olabilir - Sayfalama ve arama özellikleri ile birlikte kullanılması önerilir

Döndürür:

  • Yapılandırılmış HasOneField pointer'ı (method chaining için)

func (*HasOneField) Extract

func (h *HasOneField) Extract(resource interface{})

Extract, resource'dan değeri çıkarır ve işler.

Bu method, HasOne ilişkisinde ilişkili resource'un ID değerini çıkarır. Eğer ilişkili veri bir struct ise, struct'ın ID alanını bulup değer olarak ayarlar. Bu, frontend'e gönderilecek veriyi hazırlar ve sadece ID'yi döndürür.

Çalışma Mantığı

1. Schema.Extract() ile temel extraction yapılır 2. Eğer veri nil ise, işlem sonlandırılır 3. Eğer veri pointer ise, dereference edilir 4. Eğer veri struct ise, ID veya Id alanı aranır 5. Bulunan ID değeri Data alanına atanır

Kullanım Senaryoları

- **API Response**: Frontend'e sadece ilişkili kaydın ID'sini gönderme - **Form Data**: Edit formlarında mevcut ilişkili kaydın ID'sini gösterme - **Serialization**: JSON response'da nested struct yerine ID kullanma - **Data Transformation**: Struct'tan primitive değere dönüşüm

Örnek Veri Dönüşümü

**Giriş (Struct):**

user := User{
    ID: 1,
    Profile: Profile{
        ID: 42,
        FullName: "John Doe",
        Avatar: "avatar.jpg",
    },
}

**Çıkış (ID):**

field.Data = 42  // Sadece Profile ID'si

Desteklenen Veri Tipleri

**Struct:**

Profile{ID: 42, FullName: "John"} → 42

**Pointer to Struct:**

&Profile{ID: 42, FullName: "John"} → 42

**Nil Pointer:**

var profile *Profile = nil → nil

**Primitive (ID zaten var):**

42 → 42 (değişmez)

ID Alan İsimleri

Method, aşağıdaki alan isimlerini sırayla arar: 1. "ID" (büyük harf, Go convention) 2. "Id" (camelCase, alternatif)

Kullanım Örneği

// Resource tanımı
type User struct {
    ID      uint
    Profile Profile
}

type Profile struct {
    ID       uint
    FullName string
}

// Field tanımı
field := fields.HasOne("Profile", "profile", "profiles")

// Extract çağrısı
user := User{
    ID: 1,
    Profile: Profile{ID: 42, FullName: "John"},
}
field.Extract(user)

// Sonuç
fmt.Println(field.Data) // Output: 42

JSON Serialization

Extract sonrası JSON response:

{
    "id": 1,
    "profile": 42  // Struct yerine sadece ID
}

Reflection Kullanımı

Bu method, Go'nun reflection paketini kullanır: - reflect.ValueOf(): Değeri reflection value'ya çevirir - v.Kind(): Değerin tipini kontrol eder (Ptr, Struct) - v.Elem(): Pointer'ı dereference eder - v.FieldByName(): Struct alanını isimle bulur - idField.Interface(): Reflection value'yu interface{}'e çevirir

Önemli Notlar

- ID alanı bulunamazsa, Data değişmeden kalır - ID alanı private ise (küçük harfle başlıyorsa) erişilemez - ID alanı exported olmalıdır (büyük harfle başlamalı) - Nil pointer'lar güvenli şekilde işlenir

Performans

- Reflection kullanımı nedeniyle normal field access'ten yavaştır - Ancak, serialization için gereklidir - Büyük veri setlerinde dikkat edilmeli - Cache mekanizması ile optimize edilebilir

Hata Durumları

Method, aşağıdaki durumlarda sessizce başarısız olur: - ID alanı bulunamazsa (Data değişmez) - ID alanı private ise (erişilemez) - Veri tipi desteklenmiyorsa (Data değişmez)

Alternatif Yaklaşımlar

**Manuel ID Extraction:**

if user.Profile.ID != 0 {
    field.Data = user.Profile.ID
}

**Interface Method:**

type IDGetter interface {
    GetID() uint
}

**Struct Tag:**

Profile Profile `json:"profile_id,omitempty"`

Uyarılar

- Reflection kullanımı runtime overhead ekler - Type assertion başarısız olabilir - ID alanı yoksa sessizce başarısız olur - Panic riski düşük ama mevcut (invalid reflection operations)

Parametreler:

  • resource: Extract edilecek resource (struct veya pointer)

func (*HasOneField) ForeignKey

func (h *HasOneField) ForeignKey(key string) *HasOneField

ForeignKey, foreign key sütun adını ayarlar.

Bu method, ilişkili tablodaki foreign key sütununun adını özelleştirmenizi sağlar. Varsayılan olarak, foreign key "{slug}_id" formatında oluşturulur.

Parametreler

- **key**: Foreign key sütun adı (örn. "user_id", "owner_id", "parent_id")

Kullanım Senaryoları

- **Özel İsimlendirme**: Standart dışı foreign key isimleri kullanma - **Legacy Veritabanları**: Mevcut veritabanı şemalarına uyum sağlama - **Çoklu İlişkiler**: Aynı tabloya birden fazla ilişki tanımlama

Kullanım Örneği

// Standart kullanım
field := fields.HasOne("Profile", "profile", "profiles").
    ForeignKey("user_id")

// Özel isimlendirme
field := fields.HasOne("Manager", "manager", "users").
    ForeignKey("manager_user_id")

// Legacy veritabanı
field := fields.HasOne("Invoice", "invoice", "invoices").
    ForeignKey("order_fk")

GORM Entegrasyonu

Bu ayar, GORM'un `foreignKey` tag'i ile senkronize edilir:

type User struct {
    ID      uint
    Profile Profile `gorm:"foreignKey:user_id"`
}

Önemli Notlar

- Foreign key sütunu ilişkili tabloda mevcut olmalıdır - Sütun tipi, owner key ile uyumlu olmalıdır (genellikle uint veya int) - Index eklenmesi performans için önerilir - Foreign key constraint'leri veritabanı seviyesinde tanımlanmalıdır

Döndürür:

  • Yapılandırılmış HasOneField pointer'ı (method chaining için)

func (*HasOneField) GetDisplayKey

func (h *HasOneField) GetDisplayKey() string

GetDisplayKey, display key'i döndürür (HasOne için kullanılmaz).

Bu method, HasOne ilişkisinde kullanılmaz ve boş string döndürür. Display key, genellikle HasMany ve BelongsToMany gibi çoklu kayıt ilişkilerinde hangi alanın gösterileceğini belirtmek için kullanılır.

Dönüş Değeri

- Boş string ("") - HasOne için display key kavramı geçerli değildir

Neden Kullanılmaz?

HasOne ilişkisi tek bir kayıt döndürdüğü için, display key'e ihtiyaç yoktur. Display key, çoklu kayıtların listesinde hangi alanın gösterileceğini belirlemek için kullanılır.

Display Key Kullanılan İlişkiler

**HasMany:** - Birden fazla kayıt döndürür - Her kayıt için display key ile gösterim yapılır - Örnek: User -> Posts (post.title gösterilir)

**BelongsToMany:** - Çok-çok ilişkide birden fazla kayıt - Pivot tablo üzerinden display key kullanılır - Örnek: User -> Roles (role.name gösterilir)

**MorphMany:** - Polimorfik bir-çok ilişki - Display key ile kayıtlar listelenir - Örnek: Post -> Comments (comment.body gösterilir)

HasOne vs HasMany Karşılaştırması

**HasOne (Bu Method):**

field := fields.HasOne("Profile", "profile", "profiles")
displayKey := field.GetDisplayKey() // "" (boş)
// Tek kayıt döndürür, display key gerekmez

**HasMany:**

field := fields.HasMany("Posts", "posts", "posts").
    DisplayKey("title")
displayKey := field.GetDisplayKey() // "title"
// Birden fazla kayıt, her biri title ile gösterilir

Interface Implementation

Bu method, Relationship interface'ini implement eder:

type Relationship interface {
    GetDisplayKey() string  // Bu method
    GetSearchableColumns() []string
    // ... diğer method'lar
}

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles")
displayKey := field.GetDisplayKey()
fmt.Println(displayKey) // Output: "" (boş string)

// Tip kontrolü
if displayKey == "" {
    fmt.Println("Display key not used for HasOne")
}

JSON Serialization

API response'da bu alan genellikle dahil edilmez:

{
    "name": "Profile",
    "key": "profile",
    "type": "relationship",
    "relationship_type": "hasOne",
    "related_resource": "profiles"
    // display_key yok (boş olduğu için)
}

Alternatif Yaklaşımlar

HasOne için display key yerine, ilişkili kaydın tamamı döndürülür:

// API Response
{
    "id": 1,
    "name": "John",
    "profile": {
        "id": 42,
        "full_name": "John Doe",
        "avatar": "avatar.jpg"
    }
}

Önemli Notlar

- Her zaman boş string döndürür - HasOne için display key kavramı geçerli değildir - Çoklu kayıt ilişkilerinde (HasMany, BelongsToMany) kullanılır - Interface uyumluluğu için implement edilmiştir

Best Practices

HasOne ilişkisinde display key kullanmayın:

// Yanlış (etkisiz)
field := fields.HasOne("Profile", "profile", "profiles").
    DisplayKey("full_name") // HasOne'da DisplayKey method'u yok

// Doğru
field := fields.HasOne("Profile", "profile", "profiles")
// Display key gerekmez, tüm profile objesi döndürülür

Performans

- O(1) kompleksitesi (sabit string dönüşü) - Bellek allocation yok - Çok hızlı çalışır

Döndürür:

  • Boş string ("") - HasOne için kullanılmaz

func (*HasOneField) GetForeignKeyColumn

func (h *HasOneField) GetForeignKeyColumn() string

GetForeignKeyColumn, foreign key sütun adını döndürür.

Bu metod, HasOne ilişkisinde kullanılan foreign key sütununun adını döndürür. Foreign key, ilişkili tablodaki referans sütunudur.

Dönüş Değeri

- Foreign key sütun adı (örn. "user_id", "order_id", "country_id")

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles").ForeignKey("user_id")
foreignKey := field.GetForeignKeyColumn() // "user_id"

Döndürür:

  • Foreign key sütun adı

func (*HasOneField) GetHoverCard

func (h *HasOneField) GetHoverCard() *HoverCardConfig

GetHoverCard, hover card konfigürasyonunu döndürür.

Bu metod, hover card konfigürasyonunu alır.

Döndürür:

  • HoverCardConfig pointer'ı (nil olabilir)

func (*HasOneField) GetLoadingStrategy

func (h *HasOneField) GetLoadingStrategy() LoadingStrategy

GetLoadingStrategy, yükleme stratejisini döndürür.

Bu method, HasOne ilişkisinin yükleme stratejisini (eager veya lazy loading) döndürür. Eğer strateji ayarlanmamışsa, varsayılan olarak EAGER_LOADING döndürür.

Dönüş Değeri

- LoadingStrategy: EAGER_LOADING veya LAZY_LOADING - Varsayılan: EAGER_LOADING (N+1 sorgu problemini önlemek için)

Loading Strategy Tipleri

**EAGER_LOADING:** - İlişkili kayıtlar ana kayıtlarla birlikte yüklenir - N+1 sorgu problemini önler - Liste görünümlerinde önerilir - Performanslı toplu yükleme

**LAZY_LOADING:** - İlişkili kayıtlar sadece gerektiğinde yüklenir - İsteğe bağlı yükleme - Tek kayıt görünümlerinde kullanılabilir - N+1 problem riski vardır

Kullanım Senaryoları

- **Query Optimization**: Sorgu stratejisini belirleme - **Preload Decision**: Preload yapılıp yapılmayacağına karar verme - **Performance Tuning**: Performans optimizasyonu için strateji seçimi - **Dynamic Loading**: Runtime'da yükleme stratejisini kontrol etme - **Debugging**: Yükleme stratejisini loglama ve debug etme

Kullanım Örneği

// Eager loading ile field
field := fields.HasOne("Profile", "profile", "profiles").
    WithEagerLoad()
strategy := field.GetLoadingStrategy()
fmt.Println(strategy) // Output: EAGER_LOADING

// Lazy loading ile field
field := fields.HasOne("Profile", "profile", "profiles").
    WithLazyLoad()
strategy := field.GetLoadingStrategy()
fmt.Println(strategy) // Output: LAZY_LOADING

// Varsayılan (strateji ayarlanmamış)
field := fields.HasOne("Profile", "profile", "profiles")
strategy := field.GetLoadingStrategy()
fmt.Println(strategy) // Output: EAGER_LOADING (varsayılan)

Strateji Bazlı Query Execution

func loadRelationships(fields []*HasOneField, items []interface{}) {
    for _, field := range fields {
        strategy := field.GetLoadingStrategy()

        switch strategy {
        case EAGER_LOADING:
            // Tüm kayıtları tek sorguda yükle
            preloadRelationships(field, items)

        case LAZY_LOADING:
            // Her kayıt için ayrı ayrı yükle (gerektiğinde)
            // Hiçbir şey yapma, isteğe bağlı yükleme
        }
    }
}

Eager Loading Implementation

if field.GetLoadingStrategy() == EAGER_LOADING {
    // GORM Preload kullan
    db.Preload(field.Key).Find(&users)

    // Veya manuel batch loading
    ownerIDs := extractOwnerIDs(users)
    profiles := loadProfilesByOwnerIDs(ownerIDs)
    mapProfilesToUsers(users, profiles)
}

Lazy Loading Implementation

if field.GetLoadingStrategy() == LAZY_LOADING {
    // İlişki sadece erişildiğinde yüklenir
    // Hiçbir şey yapma, manuel yükleme gerekir
    for _, user := range users {
        if needsProfile(user) {
            profile, _ := field.ResolveRelationship(user)
            user.Profile = profile
        }
    }
}

Varsayılan Davranış

Strateji ayarlanmamışsa (boş string), varsayılan olarak EAGER_LOADING döndürülür:

field := fields.HasOne("Profile", "profile", "profiles")
// LoadingStrategy field'ı boş string

strategy := field.GetLoadingStrategy()
// EAGER_LOADING döndürür (varsayılan)

Bu, N+1 sorgu problemini önlemek için güvenli bir varsayılandır.

Performans Karşılaştırması

**100 Kullanıcı + Profilleri:**

**Eager Loading:** - Sorgu sayısı: 2 (users + profiles) - Süre: ~50ms - Bellek: Yüksek (tüm veriler)

**Lazy Loading:** - Sorgu sayısı: 101 (users + 100 profile sorgusu) - Süre: ~500ms (10x yavaş) - Bellek: Düşük (sadece gerekli veriler)

Strateji Seçim Rehberi

**Eager Loading Kullan:** - Liste görünümlerinde (index, table) - İlişkili veri kesinlikle gerekli - Birden fazla kayıt işlenirken - API response'larında - Export/raporlama işlemlerinde

**Lazy Loading Kullan:** - Tek kayıt görünümlerinde (show, detail) - İlişkili veri nadiren gerekli - Bellek kısıtlı ortamlarda - Çok büyük ilişkili veri setlerinde - Koşullu veri yükleme senaryolarında

Dynamic Strategy Selection

Runtime'da strateji değiştirilebilir:

func getLoadingStrategy(context Context) LoadingStrategy {
    if context.IsBulkOperation() {
        return EAGER_LOADING
    }
    if context.IsSingleRecord() {
        return LAZY_LOADING
    }
    return EAGER_LOADING // Varsayılan
}

Monitoring ve Logging

strategy := field.GetLoadingStrategy()
log.Info("Loading relationship",
    "field", field.Name,
    "strategy", strategy,
    "record_count", len(items))

if strategy == LAZY_LOADING {
    log.Warn("Lazy loading may cause N+1 queries",
        "field", field.Name)
}

Testing

// Test eager loading
field := fields.HasOne("Profile", "profile", "profiles").
    WithEagerLoad()
assert.Equal(t, EAGER_LOADING, field.GetLoadingStrategy())

// Test lazy loading
field = fields.HasOne("Profile", "profile", "profiles").
    WithLazyLoad()
assert.Equal(t, LAZY_LOADING, field.GetLoadingStrategy())

// Test default
field = fields.HasOne("Profile", "profile", "profiles")
assert.Equal(t, EAGER_LOADING, field.GetLoadingStrategy())

Önemli Notlar

- Varsayılan strateji EAGER_LOADING'dir (güvenli seçim) - Boş string kontrolü yapılır ve varsayılan döndürülür - Strateji WithEagerLoad() veya WithLazyLoad() ile ayarlanır - Liste görünümlerinde mutlaka eager loading kullanın - N+1 problemini önlemek için varsayılan eager'dır

Best Practices

**Liste Görünümlerinde:**

field := fields.HasOne("Profile", "profile", "profiles").
    WithEagerLoad() // Açıkça belirt

**Tek Kayıt Görünümlerinde:**

field := fields.HasOne("Profile", "profile", "profiles").
    WithLazyLoad() // Gerektiğinde yükle

**Varsayılana Güvenme:**

// Kötü: Strateji belirsiz
field := fields.HasOne("Profile", "profile", "profiles")

// İyi: Strateji açıkça belirtilmiş
field := fields.HasOne("Profile", "profile", "profiles").
    WithEagerLoad()

Performans İpuçları

- Production'da eager loading tercih edin - Lazy loading sadece gerektiğinde kullanın - Sorgu sayısını monitor edin - N+1 problemini tespit edin ve düzeltin - Cache mekanizması ile optimize edin

Uyarılar

- Lazy loading N+1 sorgu problemine yol açar - Liste görünümlerinde lazy loading kullanmayın - Varsayılan eager olsa da açıkça belirtmek daha iyidir - Strateji değişikliği tüm sorguları etkiler

Döndürür:

  • LoadingStrategy: EAGER_LOADING veya LAZY_LOADING (varsayılan: EAGER_LOADING)

func (*HasOneField) GetOwnerKeyColumn

func (h *HasOneField) GetOwnerKeyColumn() string

GetOwnerKeyColumn, owner key sütun adını döndürür.

Bu metod, HasOne ilişkisinde kullanılan owner key sütununun adını döndürür. Owner key, ana tablodaki referans sütunudur (genellikle primary key).

Dönüş Değeri

- Owner key sütun adı (örn. "id", "uuid")

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles").OwnerKey("id")
ownerKey := field.GetOwnerKeyColumn() // "id"

Döndürür:

  • Owner key sütun adı

func (*HasOneField) GetQueryCallback

func (h *HasOneField) GetQueryCallback() func(interface{}) interface{}

GetQueryCallback, query callback fonksiyonunu döndürür.

Bu method, ilişki sorgusunu özelleştirmek için tanımlanmış callback fonksiyonunu döndürür. Eğer callback tanımlanmamışsa, varsayılan olarak sorguyu değiştirmeyen bir fonksiyon döndürür.

Dönüş Değeri

- Query callback fonksiyonu: func(interface{}) interface{} - Callback yoksa: Sorguyu olduğu gibi döndüren varsayılan fonksiyon

Çalışma Mantığı

1. QueryCallback field'ını kontrol eder 2. Eğer nil ise, varsayılan pass-through fonksiyon döndürür 3. Eğer tanımlıysa, kullanıcı tarafından ayarlanan callback'i döndürür

Kullanım Senaryoları

- **Query Execution**: İlişki yüklenirken callback'i uygulama - **Dynamic Filtering**: Runtime'da sorgu özelleştirme - **Middleware**: Sorgu pipeline'ına ekleme - **Logging**: Sorgu loglaması için callback kullanma - **Testing**: Mock callback'ler ile test etme

Kullanım Örneği

// Callback tanımlı field
field := fields.HasOne("Profile", "profile", "profiles").
    Query(func(q interface{}) interface{} {
        return q.(*gorm.DB).Where("status = ?", "active")
    })

// Callback'i al ve kullan
callback := field.GetQueryCallback()
query := db.Model(&Profile{})
query = callback(query).(*gorm.DB)
query.Find(&profiles)

Varsayılan Callback

Callback tanımlanmamışsa, varsayılan fonksiyon döndürülür:

func(q interface{}) interface{} {
    return q  // Sorguyu olduğu gibi döndür
}

Bu, callback kontrolü yapmadan güvenle kullanılabilir:

// Her zaman çalışır (nil check gerekmez)
callback := field.GetQueryCallback()
query = callback(query)

Callback Tanımlama

Query method'u ile callback tanımlanır:

field.Query(func(q interface{}) interface{} {
    db := q.(*gorm.DB)
    return db.Where("verified = ?", true).
        Order("created_at DESC")
})

Callback Uygulama

**Eager Loading'de:**

func loadRelationship(field *HasOneField, ownerID uint) interface{} {
    query := db.Model(&Profile{}).
        Where("user_id = ?", ownerID)

    // Callback uygula
    callback := field.GetQueryCallback()
    query = callback(query).(*gorm.DB)

    var profile Profile
    query.First(&profile)
    return profile
}

**Lazy Loading'de:**

func (h *HasOneField) ResolveRelationship(item interface{}) (interface{}, error) {
    ownerValue := extractFieldValue(item, h.OwnerKeyColumn)

    query := db.Model(relatedModel).
        Where(fmt.Sprintf("%s = ?", h.ForeignKeyColumn), ownerValue)

    // Callback uygula
    callback := h.GetQueryCallback()
    query = callback(query).(*gorm.DB)

    var result interface{}
    err := query.First(&result).Error
    return result, err
}

Callback Chaining

Birden fazla callback zincirleme yapılabilir:

baseCallback := field.GetQueryCallback()
enhancedCallback := func(q interface{}) interface{} {
    // Önce base callback uygula
    q = baseCallback(q)
    // Sonra ek işlemler
    return q.(*gorm.DB).Limit(10)
}

Type Safety

Callback içinde type assertion kullanılır:

callback := func(q interface{}) interface{} {
    db, ok := q.(*gorm.DB)
    if !ok {
        return q  // Type assertion başarısız, olduğu gibi döndür
    }
    return db.Where("active = ?", true)
}

Testing

Test'lerde mock callback kullanılabilir:

// Test setup
mockCallback := func(q interface{}) interface{} {
    // Mock davranış
    return q
}

field := fields.HasOne("Profile", "profile", "profiles").
    Query(mockCallback)

// Test
callback := field.GetQueryCallback()
assert.NotNil(t, callback)

Önemli Notlar

- Method her zaman nil olmayan bir fonksiyon döndürür - Varsayılan callback sorguyu değiştirmez (pass-through) - Callback nil kontrolü yapmanıza gerek yoktur - Type assertion başarısız olursa panic riski vardır - Callback içinde error handling yapılmalıdır

Best Practices

**Güvenli Type Assertion:**

callback := func(q interface{}) interface{} {
    db, ok := q.(*gorm.DB)
    if !ok {
        log.Warn("Type assertion failed")
        return q
    }
    return db.Where("active = ?", true)
}

**Error Handling:**

callback := func(q interface{}) interface{} {
    defer func() {
        if r := recover(); r != nil {
            log.Error("Callback panic:", r)
        }
    }()
    return q.(*gorm.DB).Where("active = ?", true)
}

**Logging:**

callback := func(q interface{}) interface{} {
    log.Debug("Applying query callback")
    db := q.(*gorm.DB)
    return db.Where("active = ?", true)
}

Performans

- O(1) kompleksitesi (field access veya varsayılan fonksiyon dönüşü) - Minimal bellek allocation - Callback execution overhead callback içeriğine bağlıdır

Uyarılar

- Callback içinde panic oluşursa uygulama çökebilir - Type assertion başarısız olursa runtime error oluşur - Callback'te yapılan değişiklikler tüm sorguları etkiler - Thread-safety callback implementasyonuna bağlıdır

Döndürür:

  • Query callback fonksiyonu (her zaman nil olmayan)

func (*HasOneField) GetRelatedResourceSlug

func (h *HasOneField) GetRelatedResourceSlug() string

GetRelatedResource, ilişkili resource'un slug'ını döndürür.

Bu method, HasOne ilişkisinde ilişkili resource'un slug değerini döndürür. Slug, resource'u sistem içinde tanımlayan benzersiz string identifier'dır.

Dönüş Değeri

- İlişkili resource'un slug'ı (örn. "profiles", "invoices", "capitals")

Kullanım Senaryoları

- **Resource Lookup**: İlişkili resource'u slug ile bulma - **API Routing**: İlişkili resource'un endpoint'ini oluşturma - **Dynamic Loading**: Runtime'da ilişkili resource'u yükleme - **Validation**: İlişki tanımının doğruluğunu kontrol etme - **Metadata**: İlişki bilgilerini metadata olarak saklama

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles")
slug := field.GetRelatedResource()
fmt.Println(slug) // Output: "profiles"

// Resource lookup
relatedResource := resourceRegistry.Get(field.GetRelatedResource())

// API endpoint oluşturma
endpoint := fmt.Sprintf("/api/%s", field.GetRelatedResource())
// Output: "/api/profiles"

// Dynamic query
tableName := field.GetRelatedResource()
db.Table(tableName).Where("user_id = ?", userID).First(&profile)

Slug Formatı

Slug genellikle aşağıdaki formatlarda olur: - **Plural Form**: "profiles", "invoices", "users" - **Kebab Case**: "user-profiles", "order-items" - **Snake Case**: "user_profiles", "order_items"

Resource Instance vs String Slug

HasOne oluşturulurken iki yöntem kullanılabilir:

**String Slug:**

field := fields.HasOne("Profile", "profile", "profiles")
field.GetRelatedResource() // "profiles"

**Resource Instance:**

field := fields.HasOne("Profile", "profile", user.NewProfileResource())
field.GetRelatedResource() // "profiles" (resource'un Slug() method'undan)

JSON Serialization

API response'da kullanımı:

{
    "name": "Profile",
    "key": "profile",
    "type": "relationship",
    "relationship_type": "hasOne",
    "related_resource": "profiles"  // Bu method'un dönüş değeri
}

Interface Implementation

Bu method, Relationship interface'ini implement eder:

type Relationship interface {
    GetRelationshipType() string
    GetRelatedResource() string  // Bu method
    GetRelationshipName() string
}

Resource Registry Entegrasyonu

// Resource registry'den ilişkili resource'u al
type ResourceRegistry struct {
    resources map[string]Resource
}

func (r *ResourceRegistry) Get(slug string) Resource {
    return r.resources[slug]
}

// Kullanım
relatedResource := registry.Get(field.GetRelatedResource())

Önemli Notlar

- Slug değeri HasOne oluşturulurken ayarlanır - Değer değiştirilemez (immutable) - Boş string olabilir (fallback durumunda) - Case-sensitive: "profiles" ≠ "Profiles"

Hata Durumları

Eğer HasOne oluşturulurken geçersiz bir değer verilirse: - String değilse ve Slug() method'u yoksa: boş string döner - Nil değer: boş string döner

Performans

- O(1) kompleksitesi (field access) - Bellek allocation yok - Çok hızlı çalışır

Döndürür:

  • İlişkili resource'un slug'ı (string)

func (*HasOneField) GetRelatedTableName

func (h *HasOneField) GetRelatedTableName() string

GetRelatedTableName, ilişkili tablo adını döndürür.

Bu metod, HasOne ilişkisinde kullanılan ilişkili tablonun adını döndürür. Raw SQL sorguları için kullanılır.

Dönüş Değeri

- İlişkili tablo adı (örn. "profiles", "invoices", "capitals")

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles")
tableName := field.GetRelatedTableName() // "profiles"

Döndürür:

  • İlişkili tablo adı

func (*HasOneField) GetRelationshipName

func (h *HasOneField) GetRelationshipName() string

GetRelationshipName, ilişkinin adını döndürür.

Bu method, HasOne ilişkisinin görünen adını (display name) döndürür. Bu ad, kullanıcı arayüzünde gösterilir ve ilişkiyi tanımlar.

Dönüş Değeri

- İlişkinin görünen adı (örn. "Profile", "Invoice", "Capital")

Kullanım Senaryoları

- **UI Rendering**: Form etiketlerinde ve tablo başlıklarında gösterme - **Validation Messages**: Hata mesajlarında ilişki adını kullanma - **Logging**: Log mesajlarında ilişkiyi tanımlama - **API Documentation**: API dokümantasyonunda ilişki açıklaması - **Debugging**: Debug çıktılarında ilişkiyi belirleme

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles")
name := field.GetRelationshipName()
fmt.Println(name) // Output: "Profile"

// UI rendering
label := fmt.Sprintf("%s:", field.GetRelationshipName())
// Output: "Profile:"

// Validation message
errMsg := fmt.Sprintf("%s is required", field.GetRelationshipName())
// Output: "Profile is required"

// Form field
<label>{field.GetRelationshipName()}</label>
<select name="profile_id">...</select>

Name vs Key vs Slug

HasOne ilişkisinde üç farklı identifier vardır:

**Name (GetRelationshipName):** - Görünen ad, kullanıcı dostu - Örnek: "Profile", "User Profile", "Kullanıcı Profili" - Kullanım: UI, mesajlar, dokümantasyon

**Key:** - Programatik identifier, struct field adı - Örnek: "profile", "userProfile", "user_profile" - Kullanım: Kod içinde, JSON keys, form names

**Slug (GetRelatedResource):** - Resource identifier, tablo/endpoint adı - Örnek: "profiles", "user-profiles", "user_profiles" - Kullanım: Routing, database, API endpoints

Çoklu Dil Desteği (i18n)

Name değeri, çoklu dil desteği için kullanılabilir:

// İngilizce
field := fields.HasOne("Profile", "profile", "profiles")

// Türkçe
field := fields.HasOne("Profil", "profile", "profiles")

// Runtime çeviri
name := i18n.Translate(field.GetRelationshipName())

JSON Serialization

API response'da kullanımı:

{
    "name": "Profile",  // Bu method'un dönüş değeri
    "key": "profile",
    "type": "relationship",
    "relationship_type": "hasOne",
    "related_resource": "profiles"
}

Interface Implementation

Bu method, Relationship interface'ini implement eder:

type Relationship interface {
    GetRelationshipType() string
    GetRelatedResource() string
    GetRelationshipName() string  // Bu method
}

UI Kullanım Örnekleri

**Form Label:**

<div class="form-group">
    <label>{field.GetRelationshipName()}</label>
    <select name="profile_id">
        <option value="">Select {field.GetRelationshipName()}</option>
    </select>
</div>

**Table Header:**

<th>{field.GetRelationshipName()}</th>

**Validation Error:**

errors := map[string]string{
    "profile": fmt.Sprintf("%s is required", field.GetRelationshipName()),
}

Önemli Notlar

- Name değeri HasOne oluşturulurken ayarlanır - Değer değiştirilemez (immutable) - Boş string olabilir (ancak önerilmez) - Kullanıcı dostu olmalıdır (başlık formatında)

Best Practices

**İyi Örnekler:** - "Profile" (kısa, açık) - "User Profile" (açıklayıcı) - "Invoice Details" (detaylı) - "Kullanıcı Profili" (yerelleştirilmiş)

**Kötü Örnekler:** - "profile" (küçük harf, programatik) - "PROFILE" (tamamı büyük harf) - "prof" (kısaltma, belirsiz) - "user_profile" (snake_case, programatik)

Performans

- O(1) kompleksitesi (field access) - Bellek allocation yok - Çok hızlı çalışır

Döndürür:

  • İlişkinin görünen adı (string)

func (*HasOneField) GetRelationshipType

func (h *HasOneField) GetRelationshipType() string

GetRelationshipType, ilişki tipini döndürür.

Bu method, HasOne ilişkisinin tipini string olarak döndürür. İlişki tipi, sistem içinde ilişki türünü tanımlamak ve işlemek için kullanılır.

Dönüş Değeri

- "hasOne": HasOne ilişki tipini belirten sabit string

Kullanım Senaryoları

- **Tip Kontrolü**: İlişki tipini runtime'da kontrol etme - **Routing**: İlişki tipine göre farklı işlemler yapma - **Serialization**: JSON/XML çıktısında ilişki tipini belirtme - **Validation**: İlişki tipine özel validasyon kuralları uygulama - **Logging**: Log mesajlarında ilişki tipini gösterme

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles")
relType := field.GetRelationshipType()
fmt.Println(relType) // Output: "hasOne"

// Tip kontrolü
if field.GetRelationshipType() == "hasOne" {
    // HasOne'a özel işlemler
}

// Switch case ile routing
switch field.GetRelationshipType() {
case "hasOne":
    // HasOne işlemleri
case "hasMany":
    // HasMany işlemleri
case "belongsTo":
    // BelongsTo işlemleri
}

İlişki Tipleri

Sistemdeki diğer ilişki tipleri: - "hasOne": Bir-bir ilişki (bu method) - "hasMany": Bir-çok ilişki - "belongsTo": Ters bir-bir veya ters bir-çok ilişki - "belongsToMany": Çok-çok ilişki - "morphTo": Polimorfik ilişki - "morphOne": Polimorfik bir-bir ilişki - "morphMany": Polimorfik bir-çok ilişki

JSON Serialization

API response'da kullanımı:

{
    "name": "Profile",
    "key": "profile",
    "type": "relationship",
    "relationship_type": "hasOne",
    "related_resource": "profiles"
}

Interface Implementation

Bu method, Relationship interface'ini implement eder:

type Relationship interface {
    GetRelationshipType() string
    GetRelatedResource() string
    GetRelationshipName() string
}

Önemli Notlar

- Dönüş değeri her zaman "hasOne" string'idir - Değer değiştirilemez (immutable) - Case-sensitive: "hasOne" (camelCase) - Boş string döndürmez

Performans

- O(1) kompleksitesi (sabit string dönüşü) - Bellek allocation yok - Çok hızlı çalışır

Döndürür:

  • "hasOne" string sabiti

func (*HasOneField) GetSearchableColumns

func (h *HasOneField) GetSearchableColumns() []string

GetSearchableColumns, aranabilir sütunları döndürür (HasOne için kullanılmaz).

Bu method, HasOne ilişkisinde kullanılmaz ve boş slice döndürür. Searchable columns, genellikle HasMany ve BelongsToMany gibi çoklu kayıt ilişkilerinde hangi sütunlarda arama yapılacağını belirtmek için kullanılır.

Dönüş Değeri

- Boş string slice ([]string{}) - HasOne için searchable columns kavramı geçerli değildir

Neden Kullanılmaz?

HasOne ilişkisi tek bir kayıt döndürdüğü için, searchable columns'a ihtiyaç yoktur. Searchable columns, çoklu kayıtların listesinde arama yapmak için kullanılır.

Searchable Columns Kullanılan İlişkiler

**HasMany:** - Birden fazla kayıt döndürür - Kayıtlar arasında arama yapılabilir - Örnek: User -> Posts (title, body sütunlarında ara)

**BelongsToMany:** - Çok-çok ilişkide birden fazla kayıt - İlişkili kayıtlarda arama yapılabilir - Örnek: User -> Roles (name, description sütunlarında ara)

**MorphMany:** - Polimorfik bir-çok ilişki - Searchable columns ile kayıtlar filtrelenir - Örnek: Post -> Comments (body, author sütunlarında ara)

HasOne vs HasMany Karşılaştırması

**HasOne (Bu Method):**

field := fields.HasOne("Profile", "profile", "profiles")
columns := field.GetSearchableColumns() // [] (boş)
// Tek kayıt döndürür, arama gerekmez

**HasMany:**

field := fields.HasMany("Posts", "posts", "posts").
    SearchableColumns("title", "body", "excerpt")
columns := field.GetSearchableColumns() // ["title", "body", "excerpt"]
// Birden fazla kayıt, arama yapılabilir

Interface Implementation

Bu method, Relationship interface'ini implement eder:

type Relationship interface {
    GetDisplayKey() string
    GetSearchableColumns() []string  // Bu method
    // ... diğer method'lar
}

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles")
columns := field.GetSearchableColumns()
fmt.Println(len(columns)) // Output: 0 (boş slice)

// Tip kontrolü
if len(columns) == 0 {
    fmt.Println("Searchable columns not used for HasOne")
}

JSON Serialization

API response'da bu alan genellikle dahil edilmez:

{
    "name": "Profile",
    "key": "profile",
    "type": "relationship",
    "relationship_type": "hasOne",
    "related_resource": "profiles"
    // searchable_columns yok (boş olduğu için)
}

Alternatif Yaklaşımlar

HasOne için arama yerine, ilişkili kaydın tamamı döndürülür ve frontend'de filtreleme yapılabilir:

// API Response
{
    "id": 1,
    "name": "John",
    "profile": {
        "id": 42,
        "full_name": "John Doe",
        "bio": "Software Developer"
    }
}

// Frontend'de filtreleme
if (user.profile.full_name.includes(searchTerm)) {
    // Göster
}

Global Search

HasOne ilişkisi global search'e dahil edilebilir:

field := fields.HasOne("Profile", "profile", "profiles").
    Searchable() // Global search'e dahil et

// Ancak bu, ilişkili kaydın kendisini değil,
// ilişkinin varlığını aranabilir yapar

Önemli Notlar

- Her zaman boş slice döndürür - HasOne için searchable columns kavramı geçerli değildir - Çoklu kayıt ilişkilerinde (HasMany, BelongsToMany) kullanılır - Interface uyumluluğu için implement edilmiştir - Nil değil, boş slice döndürür ([]string{})

Best Practices

HasOne ilişkisinde searchable columns kullanmayın:

// Yanlış (etkisiz)
field := fields.HasOne("Profile", "profile", "profiles").
    SearchableColumns("full_name", "bio") // HasOne'da bu method yok

// Doğru
field := fields.HasOne("Profile", "profile", "profiles")
// Searchable columns gerekmez, tek kayıt döndürülür

Performans

- O(1) kompleksitesi (sabit slice dönüşü) - Minimal bellek allocation (boş slice) - Çok hızlı çalışır

Döndürür:

  • Boş string slice ([]string{}) - HasOne için kullanılmaz

func (*HasOneField) GetTypes

func (h *HasOneField) GetTypes() map[string]string

GetTypes, tip eşlemelerini döndürür (HasOne için kullanılmaz).

Bu method, HasOne ilişkisinde kullanılmaz ve boş map döndürür. Type mappings, genellikle form field'larında input tiplerini ve validasyon kurallarını tanımlamak için kullanılır.

Dönüş Değeri

- Boş map (map[string]string{}) - HasOne için type mappings kavramı geçerli değildir

Neden Kullanılmaz?

HasOne ilişkisi bir relationship field'dır ve primitive tip mapping'e ihtiyaç duymaz. Type mappings, genellikle Text, Number, Email gibi primitive field'larda input tipini ve validasyon kurallarını belirtmek için kullanılır.

Type Mappings Kullanılan Field'lar

**Text Field:**

field := fields.Text("Name", "name")
types := field.GetTypes()
// {"input": "text", "validation": "string"}

**Number Field:**

field := fields.Number("Age", "age")
types := field.GetTypes()
// {"input": "number", "validation": "integer"}

**Email Field:**

field := fields.Email("Email", "email")
types := field.GetTypes()
// {"input": "email", "validation": "email"}

**Date Field:**

field := fields.Date("Birth Date", "birth_date")
types := field.GetTypes()
// {"input": "date", "validation": "date"}

HasOne vs Primitive Fields Karşılaştırması

**HasOne (Bu Method):**

field := fields.HasOne("Profile", "profile", "profiles")
types := field.GetTypes() // {} (boş map)
// İlişki field'ı, tip mapping gerekmez

**Text Field:**

field := fields.Text("Name", "name")
types := field.GetTypes() // {"input": "text", "validation": "string"}
// Primitive field, tip mapping gerekir

Interface Implementation

Bu method, Field interface'ini implement eder:

type Field interface {
    GetTypes() map[string]string
    // ... diğer method'lar
}

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles")
types := field.GetTypes()
fmt.Println(len(types)) // Output: 0 (boş map)

// Tip kontrolü
if len(types) == 0 {
    fmt.Println("Type mappings not used for HasOne")
}

JSON Serialization

API response'da bu alan genellikle dahil edilmez:

{
    "name": "Profile",
    "key": "profile",
    "type": "relationship",
    "relationship_type": "hasOne",
    "related_resource": "profiles"
    // types yok (boş olduğu için)
}

Type Mappings Kullanım Alanları

Type mappings, aşağıdaki alanlarda kullanılır:

**Frontend Rendering:** - HTML input type belirleme - Form validation kuralları - Input maskeleme (telefon, kredi kartı vb.)

**Backend Validation:** - Veri tipi kontrolü - Format validasyonu - Type casting

**Database Schema:** - Sütun tipi belirleme - Migration oluşturma - Index stratejisi

HasOne İçin Alternatif

HasOne ilişkisinde tip bilgisi farklı şekilde saklanır:

// İlişki tipi
field.GetRelationshipType() // "hasOne"

// Field tipi
field.Type // TYPE_RELATIONSHIP

// View component
field.View // "has-one-field"

Frontend Component Selection

Frontend'de component seçimi View field'ına göre yapılır:

// HasOne için
switch field.View {
case "has-one-field":
    return <HasOneSelect field={field} />
case "text-field":
    return <TextInput field={field} />
case "number-field":
    return <NumberInput field={field} />
}

Type Mappings Örneği (Diğer Field'lar)

**Text Field:**

{
    "input": "text",
    "validation": "string",
    "html_type": "text",
    "db_type": "VARCHAR"
}

**Number Field:**

{
    "input": "number",
    "validation": "integer",
    "html_type": "number",
    "db_type": "INT"
}

**Email Field:**

{
    "input": "email",
    "validation": "email",
    "html_type": "email",
    "db_type": "VARCHAR"
}

Önemli Notlar

- Her zaman boş map döndürür - HasOne için type mappings kavramı geçerli değildir - Primitive field'larda (Text, Number, Email) kullanılır - Interface uyumluluğu için implement edilmiştir - Nil değil, boş map döndürür (map[string]string{})

Best Practices

HasOne ilişkisinde type mappings kullanmayın:

// Yanlış (etkisiz)
types := field.GetTypes()
if types["input"] == "text" {
    // HasOne için bu kontrol anlamsız
}

// Doğru
if field.GetRelationshipType() == "hasOne" {
    // HasOne'a özel işlemler
}

Field Type Kontrolü

Field tipini kontrol etmek için doğru method'ları kullanın:

// HasOne için
if field.Type == TYPE_RELATIONSHIP {
    relType := field.GetRelationshipType() // "hasOne"
}

// Primitive field için
if field.Type == TYPE_TEXT {
    types := field.GetTypes() // {"input": "text", ...}
}

Migration ve Schema

HasOne için database schema bilgisi farklı şekilde alınır:

// Foreign key bilgisi
foreignKey := field.ForeignKeyColumn // "user_id"
ownerKey := field.OwnerKeyColumn     // "id"

// Migration
ALTER TABLE profiles
ADD CONSTRAINT fk_profiles_user_id
FOREIGN KEY (user_id) REFERENCES users(id);

Performans

- O(1) kompleksitesi (boş map dönüşü) - Minimal bellek allocation (boş map) - Çok hızlı çalışır

Interface Uyumluluğu

Bu method, Field interface'ini implement etmek için gereklidir:

type Field interface {
    GetTypes() map[string]string  // Tüm field'lar implement etmeli
    GetName() string
    GetKey() string
    // ... diğer method'lar
}

HasOne bir Field olduğu için bu method'u implement etmelidir, ancak relationship field'lar için type mappings kullanılmaz.

Debugging

Field tipini debug ederken:

fmt.Printf("Field: %s\n", field.Name)
fmt.Printf("Type: %s\n", field.Type)
fmt.Printf("View: %s\n", field.View)

if field.Type == TYPE_RELATIONSHIP {
    fmt.Printf("Relationship Type: %s\n", field.GetRelationshipType())
    fmt.Printf("Related Resource: %s\n", field.GetRelatedResource())
} else {
    fmt.Printf("Types: %+v\n", field.GetTypes())
}

Uyarılar

- HasOne için GetTypes() kullanmayın (her zaman boş) - Tip bilgisi için GetRelationshipType() kullanın - Frontend component seçimi için View field'ını kullanın - Database schema için ForeignKeyColumn ve OwnerKeyColumn kullanın

Döndürür:

  • Boş map (map[string]string{}) - HasOne için kullanılmaz

func (*HasOneField) HoverCard

func (h *HasOneField) HoverCard(hoverStruct interface{}) *HasOneField

HoverCard, hover card struct'ını ayarlar ve hover card'ı etkinleştirir.

Bu metod, hover card için kullanılacak struct'ı belirler ve hover card özelliğini aktif eder.

Parametreler

- **hoverStruct**: Hover card verisi için kullanılacak struct (örn. &ProfileHoverCard{})

Kullanım Örneği

type ProfileHoverCard struct {
    Avatar string `json:"avatar"`
    Bio    string `json:"bio"`
    Location string `json:"location"`
}

field := fields.HasOne("Profile", "profile", "profiles").
    ForeignKey("user_id").
    HoverCard(&ProfileHoverCard{})

Döndürür:

  • HasOneField pointer'ı (method chaining için)

func (*HasOneField) IsRequired

func (h *HasOneField) IsRequired() bool

IsRequired, alanın zorunlu olup olmadığını döndürür.

Bu method, HasOne ilişkisinin zorunlu (required) olarak işaretlenip işaretlenmediğini kontrol eder. Zorunlu alan, form validasyonunda ve veri kaydında mutlaka doldurulması gereken alandır.

Dönüş Değeri

- true: Alan zorunludur, mutlaka doldurulmalıdır - false: Alan opsiyoneldir, boş bırakılabilir

Kullanım Senaryoları

- **Form Validation**: Form gönderilmeden önce zorunlu alan kontrolü - **API Validation**: Request payload validasyonu - **Database Constraints**: NOT NULL constraint kontrolü - **UI Rendering**: Zorunlu alanları görsel olarak işaretleme (*) - **Error Messages**: Zorunlu alan hata mesajları

Kullanım Örneği

// Zorunlu HasOne field
field := fields.HasOne("Profile", "profile", "profiles").
    Required()

// Zorunluluk kontrolü
if field.IsRequired() {
    fmt.Println("Profile is required")
}

// Form validation
if field.IsRequired() && profileID == 0 {
    return errors.New("Profile is required")
}

Required Method ile Kullanım

Alanı zorunlu yapmak için Required() method'u kullanılır:

field := fields.HasOne("Profile", "profile", "profiles").
    Required() // IsRequired field'ını true yapar

fmt.Println(field.IsRequired()) // Output: true

Validation Implementation

func validateField(field *HasOneField, value interface{}) error {
    if field.IsRequired() {
        if value == nil {
            return fmt.Errorf("%s is required", field.Name)
        }

        // ID kontrolü
        if id, ok := value.(uint); ok && id == 0 {
            return fmt.Errorf("%s is required", field.Name)
        }
    }
    return nil
}

Frontend Integration

Frontend'de zorunlu alanlar otomatik olarak işaretlenir:

// API Response
{
    "name": "Profile",
    "key": "profile",
    "type": "relationship",
    "required": true  // Bu method'un dönüş değeri
}

// Frontend Rendering
<label>
    Profile {field.required && <span className="text-red-500">*</span>}
</label>
<select name="profile_id" required={field.required}>
    <option value="">Select Profile</option>
</select>

Form Validation Örneği

// Backend validation
func validateUserForm(data map[string]interface{}, fields []*HasOneField) error {
    for _, field := range fields {
        if field.IsRequired() {
            value, exists := data[field.Key]
            if !exists || value == nil {
                return fmt.Errorf("%s is required", field.Name)
            }
        }
    }
    return nil
}

// Kullanım
err := validateUserForm(formData, userFields)
if err != nil {
    return err
}

Database Constraints

Zorunlu alan, veritabanında NOT NULL constraint ile eşleşir:

// Migration
if field.IsRequired() {
    // Foreign key NOT NULL olmalı
    ALTER TABLE profiles
    ADD CONSTRAINT fk_profiles_user_id
    FOREIGN KEY (user_id) REFERENCES users(id)
    NOT NULL;
}

Error Messages

Zorunlu alan için hata mesajları:

if field.IsRequired() && value == nil {
    return map[string]string{
        field.Key: fmt.Sprintf("%s is required", field.Name),
    }
}

// Örnek çıktı
{
    "profile": "Profile is required"
}

UI Rendering

**Form Label:**

<label htmlFor="profile_id">
    {field.Name}
    {field.IsRequired() && <span className="text-red-500">*</span>}
</label>

**Input Field:**

<select
    id="profile_id"
    name="profile_id"
    required={field.IsRequired()}
    className={field.IsRequired() ? "required" : ""}
>
    <option value="">Select {field.Name}</option>
</select>

**Validation Message:**

{errors.profile && (
    <span className="error">
        {field.Name} is required
    </span>
)}

API Validation

// Request handler
func createUser(c *gin.Context) {
    var data map[string]interface{}
    c.BindJSON(&data)

    // Validate required fields
    for _, field := range userResource.Fields() {
        if hasOneField, ok := field.(*HasOneField); ok {
            if hasOneField.IsRequired() {
                value, exists := data[hasOneField.Key]
                if !exists || value == nil {
                    c.JSON(400, gin.H{
                        "error": fmt.Sprintf("%s is required", hasOneField.Name),
                    })
                    return
                }
            }
        }
    }

    // Create user
    // ...
}

Testing

// Test required field
func TestHasOneRequired(t *testing.T) {
    field := fields.HasOne("Profile", "profile", "profiles").
        Required()

    assert.True(t, field.IsRequired())
}

// Test optional field
func TestHasOneOptional(t *testing.T) {
    field := fields.HasOne("Profile", "profile", "profiles")

    assert.False(t, field.IsRequired())
}

Önemli Notlar

- Schema.IsRequired field'ından değer okunur - Varsayılan olarak false'dur (opsiyonel) - Required() method'u ile true yapılır - Frontend ve backend validasyonunda kullanılır - Database constraint'leri ile senkronize olmalıdır

Best Practices

**Zorunlu İlişkiler:**

// İyi: Açıkça required olarak işaretle
field := fields.HasOne("Profile", "profile", "profiles").
    Required()

// Kötü: Varsayılana güvenme
field := fields.HasOne("Profile", "profile", "profiles")
// IsRequired() false döner

**Validation:**

// İyi: Hem frontend hem backend validation
// Frontend: HTML5 required attribute
// Backend: IsRequired() kontrolü

// Kötü: Sadece frontend validation
// Güvenlik riski, bypass edilebilir

**Error Messages:**

// İyi: Kullanıcı dostu mesaj
if field.IsRequired() && value == nil {
    return fmt.Errorf("%s is required", field.Name)
}

// Kötü: Teknik mesaj
if field.IsRequired() && value == nil {
    return errors.New("validation failed: nil value")
}

Database Migration

// Required field için migration
if field.IsRequired() {
    sql := fmt.Sprintf(`
        ALTER TABLE %s
        MODIFY COLUMN %s INT NOT NULL
    `, tableName, field.ForeignKeyColumn)
    db.Exec(sql)
}

Conditional Required

Bazı durumlarda koşullu zorunluluk gerekebilir:

// Örnek: Profil sadece verified kullanıcılar için zorunlu
func validateProfile(user User, profileID uint) error {
    field := fields.HasOne("Profile", "profile", "profiles")

    if user.Verified && field.IsRequired() {
        if profileID == 0 {
            return errors.New("Profile is required for verified users")
        }
    }
    return nil
}

Performans

- O(1) kompleksitesi (field access) - Bellek allocation yok - Çok hızlı çalışır

Uyarılar

- Required field'lar mutlaka doldurulmalıdır - Frontend validation bypass edilebilir, backend validation şarttır - Database constraint'leri ile senkronize olmalıdır - Migration'larda NOT NULL constraint eklenmelidir - Mevcut verilerde NULL değer varsa migration başarısız olur

Döndürür:

  • true: Alan zorunludur
  • false: Alan opsiyoneldir

func (*HasOneField) OwnerKey

func (h *HasOneField) OwnerKey(key string) *HasOneField

OwnerKey, owner key sütun adını ayarlar.

Bu method, ana tablodaki (parent table) referans sütununun adını özelleştirmenizi sağlar. Varsayılan olarak, owner key "id" (primary key) olarak ayarlanır.

Parametreler

- **key**: Owner key sütun adı (örn. "id", "uuid", "code")

Kullanım Senaryoları

- **UUID Primary Key**: UUID kullanan tablolarda - **Composite Keys**: Birleşik anahtar kullanımında - **Custom Primary Keys**: Özel primary key isimlendirmelerinde - **Legacy Sistemler**: Standart dışı primary key yapılarında

Kullanım Örneği

// UUID primary key
field := fields.HasOne("Profile", "profile", "profiles").
    ForeignKey("user_uuid").
    OwnerKey("uuid")

// Özel primary key
field := fields.HasOne("Invoice", "invoice", "invoices").
    ForeignKey("order_code").
    OwnerKey("order_code")

// Composite key senaryosu
field := fields.HasOne("Detail", "detail", "details").
    ForeignKey("parent_id").
    OwnerKey("custom_id")

GORM Entegrasyonu

Bu ayar, GORM'un `references` tag'i ile senkronize edilir:

type User struct {
    UUID    string  `gorm:"primaryKey"`
    Profile Profile `gorm:"foreignKey:user_uuid;references:uuid"`
}

Önemli Notlar

- Owner key sütunu ana tabloda mevcut olmalıdır - Genellikle primary key veya unique key olmalıdır - Foreign key ile aynı veri tipinde olmalıdır - Index'lenmiş olması performans için kritiktir

Uyarılar

- Owner key değiştirilirse, foreign key ile uyumlu olduğundan emin olun - Non-unique owner key kullanımı veri tutarsızlığına yol açabilir - Migration'larda bu ilişkiyi doğru tanımladığınızdan emin olun

Döndürür:

  • Yapılandırılmış HasOneField pointer'ı (method chaining için)

func (*HasOneField) Query

func (h *HasOneField) Query(fn func(interface{}) interface{}) *HasOneField

Query, ilişki sorgusunu özelleştirmek için callback fonksiyonu ayarlar.

Bu method, ilişkili kayıtlar yüklenirken uygulanacak özel sorgu koşullarını tanımlamanızı sağlar. Filtreleme, sıralama, eager loading gibi işlemler için kullanılır.

Parametreler

- **fn**: Sorgu callback fonksiyonu - GORM query nesnesini alır ve değiştirilmiş query döndürür

Kullanım Senaryoları

- **Filtreleme**: Sadece aktif kayıtları yükleme - **Sıralama**: İlişkili kayıtları belirli bir sıraya göre getirme - **Eager Loading**: İlişkili kayıtların alt ilişkilerini de yükleme - **Soft Delete**: Silinmiş kayıtları dahil etme veya hariç tutma - **Performans**: Select ile sadece gerekli sütunları çekme

Kullanım Örnekleri

// Sadece aktif profilleri yükle
field := fields.HasOne("Profile", "profile", "profiles").
    Query(func(q interface{}) interface{} {
        return q.(*gorm.DB).Where("status = ?", "active")
    })

// Profili ülke bilgisi ile birlikte yükle
field := fields.HasOne("Profile", "profile", "profiles").
    Query(func(q interface{}) interface{} {
        return q.(*gorm.DB).Preload("Country")
    })

// Sadece belirli sütunları çek (performans optimizasyonu)
field := fields.HasOne("Profile", "profile", "profiles").
    Query(func(q interface{}) interface{} {
        return q.(*gorm.DB).Select("id", "full_name", "avatar")
    })

// Sıralama ekle
field := fields.HasOne("Invoice", "invoice", "invoices").
    Query(func(q interface{}) interface{} {
        return q.(*gorm.DB).Order("created_at DESC")
    })

// Birden fazla koşul
field := fields.HasOne("Profile", "profile", "profiles").
    Query(func(q interface{}) interface{} {
        db := q.(*gorm.DB)
        return db.Where("verified = ?", true).
            Where("status = ?", "active").
            Order("updated_at DESC")
    })

GORM Entegrasyonu

Callback fonksiyonu, GORM'un *gorm.DB tipini alır ve değiştirir:

func(q interface{}) interface{} {
    db := q.(*gorm.DB)
    // GORM query chain'i burada
    return db.Where(...).Order(...)
}

Önemli Notlar

- Callback fonksiyonu her ilişki yüklemesinde çalışır - Type assertion kullanırken dikkatli olun (panic riski) - Performans için sadece gerekli sütunları Select ile çekin - N+1 sorgu problemini önlemek için Preload kullanın

Performans İpuçları

- **Select**: Sadece gerekli sütunları çekin - **Index**: Where koşullarında kullanılan sütunları index'leyin - **Preload**: Alt ilişkileri tek sorguda yükleyin - **Omit**: Gereksiz büyük sütunları (BLOB, TEXT) hariç tutun

Uyarılar

- Callback içinde panic oluşursa uygulama çökebilir - Type assertion başarısız olursa runtime error oluşur - Karmaşık sorgular performansı etkileyebilir - Callback'te yapılan değişiklikler tüm yüklemeleri etkiler

Döndürür:

  • Yapılandırılmış HasOneField pointer'ı (method chaining için)

func (*HasOneField) ResolveHoverCard

func (h *HasOneField) ResolveHoverCard(resolver HoverCardResolver) *HasOneField

ResolveHoverCard, hover card verilerini çözmek için callback fonksiyonunu ayarlar.

Bu metod, hover card açıldığında çağrılacak resolver fonksiyonunu belirler. Resolver, ilişkili kaydın hover card verilerini döndürür.

Parametreler

- **resolver**: Hover card resolver callback fonksiyonu

Kullanım Örneği

field := fields.HasOne("Profile", "profile", "profiles").
    ForeignKey("user_id").
    HoverCard(&ProfileHoverCard{}).
    ResolveHoverCard(func(ctx context.Context, record interface{}, relatedID interface{}, field fields.Field) (interface{}, error) {
        // İlişkili kaydı veritabanından al
        profile := &Profile{}
        if err := db.First(profile, relatedID).Error; err != nil {
            return nil, err
        }

        // Hover card verisini döndür
        return &ProfileHoverCard{
            Avatar: profile.Avatar,
            Bio: profile.Bio,
            Location: profile.Location,
        }, nil
    })

API Endpoint

Frontend, hover card açıldığında şu endpoint'e istek atar:

GET /api/resource/{resource}/resolver/{field_name}?id={related_id}
POST /api/resource/{resource}/resolver/{field_name} (body: {id: related_id})

Döndürür:

  • HasOneField pointer'ı (method chaining için)

func (*HasOneField) ResolveRelationship

func (h *HasOneField) ResolveRelationship(item interface{}) (interface{}, error)

ResolveRelationship, ilişkiyi çözerek ilişkili kaydı yükler.

Bu method, HasOne ilişkisinde tek bir ilişkili kaydı veritabanından yükler. Gerçek implementasyonda, bu method veritabanı sorgusunu çalıştırır ve ilişkili resource'u döndürür.

Çalışma Mantığı

1. Item parametresini kontrol eder (nil kontrolü) 2. Item'dan owner key değerini çıkarır (örn. user.ID) 3. İlişkili tabloda foreign key ile sorgu yapar 4. Tek bir ilişkili kaydı bulur ve döndürür 5. Hata durumunda error döndürür

Parametreler

- **item**: Ana kayıt (owner record) - ilişkinin sahibi olan kayıt

Dönüş Değerleri

- **interface{}**: İlişkili kayıt (tek bir record) veya nil - **error**: Hata durumunda error, başarılı ise nil

Kullanım Senaryoları

- **Lazy Loading**: İlişkili kaydı isteğe bağlı yükleme - **Dynamic Resolution**: Runtime'da ilişki çözümleme - **API Endpoints**: İlişkili veriyi ayrı endpoint'te sunma - **Conditional Loading**: Belirli koşullarda ilişki yükleme - **Manual Preloading**: Özel preload stratejileri

Kullanım Örneği (Teorik)

// Field tanımı
field := fields.HasOne("Profile", "profile", "profiles").
    ForeignKey("user_id").
    OwnerKey("id")

// Ana kayıt
user := User{ID: 1, Name: "John"}

// İlişkiyi çözümle
profile, err := field.ResolveRelationship(user)
if err != nil {
    log.Fatal(err)
}

// Sonuç
fmt.Printf("Profile: %+v\n", profile)
// Output: Profile: &Profile{ID: 42, UserID: 1, FullName: "John Doe"}

Gerçek Implementasyon (Örnek)

func (h *HasOneField) ResolveRelationship(item interface{}) (interface{}, error) {
    if item == nil {
        return nil, nil
    }

    // Owner key değerini çıkar
    ownerValue := extractFieldValue(item, h.OwnerKeyColumn)
    if ownerValue == nil {
        return nil, nil
    }

    // İlişkili resource'u bul
    relatedResource := resourceRegistry.Get(h.RelatedResourceSlug)
    if relatedResource == nil {
        return nil, fmt.Errorf("related resource not found: %s", h.RelatedResourceSlug)
    }

    // Veritabanı sorgusu
    var result interface{}
    query := db.Model(relatedResource.Model()).
        Where(fmt.Sprintf("%s = ?", h.ForeignKeyColumn), ownerValue)

    // Query callback uygula
    if h.QueryCallback != nil {
        query = h.QueryCallback(query).(*gorm.DB)
    }

    // Tek kayıt bul
    err := query.First(&result).Error
    if err != nil {
        if errors.Is(err, gorm.ErrRecordNotFound) {
            return nil, nil // İlişkili kayıt yok
        }
        return nil, err
    }

    return result, nil
}

SQL Sorgusu

Method, aşağıdaki gibi bir SQL sorgusu oluşturur:

SELECT * FROM profiles
WHERE user_id = 1
LIMIT 1

Hata Durumları

**Nil Item:** - Input: nil - Output: (nil, nil)

**Kayıt Bulunamadı:** - Input: User{ID: 999} - Output: (nil, nil) // Error değil, sadece nil

**Veritabanı Hatası:** - Input: User{ID: 1} - Output: (nil, error) // Bağlantı hatası, syntax error vb.

**Birden Fazla Kayıt:** - Input: User{ID: 1} - Output: İlk kaydı döndürür (LIMIT 1)

Performans Optimizasyonu

**Select Specific Columns:**

field.Query(func(q interface{}) interface{} {
    return q.(*gorm.DB).Select("id", "full_name", "avatar")
})

**Index Kullanımı:**

CREATE INDEX idx_profiles_user_id ON profiles(user_id);

**Cache Stratejisi:**

// Cache'den kontrol et
if cached := cache.Get(cacheKey); cached != nil {
    return cached, nil
}

// Veritabanından yükle
result, err := field.ResolveRelationship(item)
if err == nil && result != nil {
    cache.Set(cacheKey, result, 5*time.Minute)
}

Eager Loading vs Lazy Loading

**Lazy Loading (Bu Method):** - Her kayıt için ayrı sorgu - N+1 problem riski - İsteğe bağlı yükleme

**Eager Loading (Preload):** - Tek sorguda tüm ilişkiler - Performanslı - Toplu yükleme

Önemli Notlar

- Şu anki implementasyon placeholder'dır (nil, nil döndürür) - Gerçek implementasyon veritabanı erişimi gerektirir - Query callback uygulanmalıdır - Error handling kritiktir - Nil item güvenli şekilde işlenir

Best Practices

- Eager loading tercih edin (liste görünümlerinde) - Lazy loading sadece gerektiğinde kullanın - Query callback ile filtreleme yapın - Index'leri doğru tanımlayın - Cache mekanizması kullanın - Error'ları loglamayı unutmayın

Uyarılar

- N+1 sorgu problemine dikkat edin - Nil pointer dereference riskine karşı kontrol yapın - Veritabanı bağlantı havuzunu yönetin - Timeout ayarlarını yapılandırın - Transaction içinde çalışırken dikkatli olun

Döndürür:

  • İlişkili kayıt (interface{}) veya nil
  • Hata durumunda error, başarılı ise nil

func (*HasOneField) Searchable

func (h *HasOneField) Searchable() Element

Searchable, alanı aranabilir olarak işaretler (Element interface'ini implement eder).

Bu method, HasOne ilişkisini global search (genel arama) özelliğine dahil eder. Global search, kullanıcıların tüm kayıtlar arasında arama yapmasını sağlar.

Çalışma Mantığı

Method, GlobalSearch field'ını true olarak ayarlar ve Element interface'ini döndürür. Bu, field'ın global search sorgularına dahil edilmesini sağlar.

Dönüş Değeri

- Element interface'i (method chaining için)

Kullanım Senaryoları

- **Global Search**: Tüm kayıtlarda arama yapılabilir hale getirme - **Quick Search**: Hızlı arama özelliğine dahil etme - **Search Bar**: Arama çubuğunda ilişki araması - **Filter Integration**: Filtreleme sistemine entegrasyon - **Admin Panel**: Yönetim panelinde arama özelliği

Kullanım Örneği

// Searchable HasOne field
field := fields.HasOne("Profile", "profile", "profiles").
    Searchable()

// Method chaining ile diğer özellikler
field := fields.HasOne("Profile", "profile", "profiles").
    Searchable().
    WithEagerLoad().
    ForeignKey("user_id")

Global Search Davranışı

HasOne ilişkisi searchable olarak işaretlendiğinde:

**İlişki Varlığı Aranır:** - İlişkili kayıt var mı yok mu kontrol edilir - İlişkili kaydın ID'si aranabilir

**İlişkili Kayıt İçeriği Aranmaz:** - HasOne için ilişkili kaydın içeriği (örn. profile.full_name) aranmaz - Sadece ilişkinin varlığı aranabilir

HasOne vs HasMany Searchable Karşılaştırması

**HasOne (Bu Method):**

field := fields.HasOne("Profile", "profile", "profiles").
    Searchable()
// İlişki varlığı aranır (profile var mı?)

**HasMany:**

field := fields.HasMany("Posts", "posts", "posts").
    Searchable().
    SearchableColumns("title", "body")
// İlişkili kayıtların içeriği aranır (post title, body)

Search Query Implementation (Örnek)

func buildSearchQuery(fields []Field, searchTerm string) *gorm.DB {
    query := db.Model(&User{})

    for _, field := range fields {
        if !field.IsSearchable() {
            continue
        }

        if hasOneField, ok := field.(*HasOneField); ok {
            // HasOne için ilişki varlığı kontrolü
            query = query.Or(
                db.Joins(hasOneField.Key).
                    Where(fmt.Sprintf("%s.id IS NOT NULL", hasOneField.Key)),
            )
        }
    }

    return query
}

Frontend Integration

Frontend'de searchable field'lar otomatik olarak arama formuna eklenir:

// API Response
{
    "fields": [
        {
            "name": "Profile",
            "key": "profile",
            "type": "relationship",
            "searchable": true  // Bu method ile ayarlanır
        }
    ]
}

// Frontend Search Form
<SearchBar>
    <input placeholder="Search users with profile..." />
</SearchBar>

Element Interface Implementation

Bu method, Element interface'ini implement eder:

type Element interface {
    Searchable() Element
    IsSearchable() bool
    // ... diğer method'lar
}

IsSearchable Kontrolü

Searchable olup olmadığını kontrol etmek için:

if field.GlobalSearch {
    // Field searchable
    includeInSearch(field)
}

Kullanım Örnekleri

**Basit Kullanım:**

field := fields.HasOne("Profile", "profile", "profiles").
    Searchable()

**Diğer Özelliklerle Birlikte:**

field := fields.HasOne("Profile", "profile", "profiles").
    Searchable().
    WithEagerLoad().
    ForeignKey("user_id").
    Required()

**Koşullu Searchable:**

field := fields.HasOne("Profile", "profile", "profiles")
if config.EnableProfileSearch {
    field.Searchable()
}

Search Query Örnekleri

**İlişki Varlığı Araması:**

// Profili olan kullanıcıları bul
db.Joins("Profile").
    Where("profiles.id IS NOT NULL").
    Find(&users)

**İlişki Yokluğu Araması:**

// Profili olmayan kullanıcıları bul
db.Joins("LEFT JOIN profiles ON profiles.user_id = users.id").
    Where("profiles.id IS NULL").
    Find(&users)

Performans Considerations

**Index Kullanımı:**

CREATE INDEX idx_profiles_user_id ON profiles(user_id);

**Join Optimizasyonu:**

// Efficient join
db.Joins("Profile").Find(&users)

// Inefficient (N+1)
for _, user := range users {
    db.Model(&user).Association("Profile").Find(&user.Profile)
}

Önemli Notlar

- GlobalSearch field'ı true olarak ayarlanır - Element interface'i döndürülür (method chaining için) - HasOne için sadece ilişki varlığı aranır, içerik aranmaz - Frontend'de otomatik olarak arama formuna eklenir - Search query'lerde JOIN kullanılır

Best Practices

**Searchable Kullanımı:**

// İyi: İlişki varlığı önemli
field := fields.HasOne("Profile", "profile", "profiles").
    Searchable() // Profili olan/olmayan kullanıcıları bul

// Kötü: İlişki içeriği aranmak isteniyorsa
// HasOne searchable ile içerik aranamaz
// İlişkili resource'da ayrı field'lar tanımlayın

**Index Tanımlama:**

// Migration'da index ekle
CREATE INDEX idx_profiles_user_id ON profiles(user_id);

**Query Optimization:**

// Eager loading ile birlikte kullan
field := fields.HasOne("Profile", "profile", "profiles").
    Searchable().
    WithEagerLoad()

Alternatif Yaklaşımlar

İlişkili kayıt içeriğinde arama yapmak için:

// Profile resource'da searchable field'lar tanımla
profileResource := resource.New("profiles").
    Fields(
        fields.Text("Full Name", "full_name").Searchable(),
        fields.Text("Bio", "bio").Searchable(),
    )

// User resource'da HasOne tanımla
userResource := resource.New("users").
    Fields(
        fields.HasOne("Profile", "profile", profileResource).
            WithEagerLoad(),
    )

Uyarılar

- HasOne searchable ile sadece ilişki varlığı aranır - İlişkili kayıt içeriği aranmaz (full_name, bio vb.) - Search query'lerde JOIN kullanılır (performans etkisi) - Index'lerin doğru tanımlandığından emin olun - Büyük veri setlerinde performans test edin

Döndürür:

  • Element interface'i (method chaining için)

func (*HasOneField) ValidateRelationship

func (h *HasOneField) ValidateRelationship(value interface{}) error

ValidateRelationship, ilişkinin geçerliliğini doğrular.

Bu method, HasOne ilişkisinde en fazla bir ilişkili kaydın var olduğunu doğrular. Gerçek implementasyonda, veritabanı constraint'lerini ve iş kurallarını kontrol eder.

Çalışma Mantığı

1. Value parametresini kontrol eder (nil, tip, format) 2. İlişkili kayıt sayısını kontrol eder (en fazla 1 olmalı) 3. Foreign key constraint'lerini doğrular 4. İş kurallarını uygular (required, unique, vb.) 5. Hata durumunda error döndürür

Parametreler

- **value**: Doğrulanacak değer (genellikle ilişkili kaydın ID'si)

Dönüş Değeri

- **error**: Validasyon hatası varsa error, geçerli ise nil

Kullanım Senaryoları

- **Form Validation**: Kullanıcı input'unu doğrulama - **API Validation**: Request payload'unu kontrol etme - **Data Integrity**: Veri tutarlılığını sağlama - **Business Rules**: İş kurallarını uygulama - **Constraint Checking**: Veritabanı constraint'lerini kontrol etme

Kullanım Örneği (Teorik)

field := fields.HasOne("Profile", "profile", "profiles").
    ForeignKey("user_id").
    Required()

// Validasyon
err := field.ValidateRelationship(profileID)
if err != nil {
    return fmt.Errorf("validation failed: %w", err)
}

Gerçek Implementasyon (Örnek)

func (h *HasOneField) ValidateRelationship(value interface{}) error {
    // Nil kontrolü
    if value == nil {
        if h.IsRequired() {
            return fmt.Errorf("%s is required", h.Name)
        }
        return nil
    }

    // Tip kontrolü
    id, ok := value.(uint)
    if !ok {
        return fmt.Errorf("%s must be a valid ID", h.Name)
    }

    // ID geçerliliği
    if id == 0 {
        return fmt.Errorf("%s ID cannot be zero", h.Name)
    }

    // İlişkili kayıt var mı?
    var count int64
    err := db.Model(relatedModel).
        Where("id = ?", id).
        Count(&count).Error
    if err != nil {
        return fmt.Errorf("failed to validate %s: %w", h.Name, err)
    }

    if count == 0 {
        return fmt.Errorf("%s with ID %d does not exist", h.Name, id)
    }

    // Birden fazla kayıt kontrolü (HasOne için)
    if count > 1 {
        return fmt.Errorf("%s has multiple records (expected one)", h.Name)
    }

    // Foreign key constraint kontrolü
    if h.ForeignKeyColumn != "" {
        // Foreign key'in başka bir kayıt tarafından kullanılıp kullanılmadığını kontrol et
        var existingCount int64
        err := db.Model(relatedModel).
            Where(fmt.Sprintf("%s = ?", h.ForeignKeyColumn), ownerID).
            Where("id != ?", id).
            Count(&existingCount).Error
        if err != nil {
            return err
        }

        if existingCount > 0 {
            return fmt.Errorf("%s already has a related record", h.Name)
        }
    }

    return nil
}

Validasyon Kuralları

**Required Kontrolü:**

if value == nil && field.IsRequired() {
    return errors.New("field is required")
}

**Tip Kontrolü:**

if _, ok := value.(uint); !ok {
    return errors.New("invalid type")
}

**Existence Kontrolü:**

var count int64
db.Model(&Profile{}).Where("id = ?", value).Count(&count)
if count == 0 {
    return errors.New("record not found")
}

**Uniqueness Kontrolü:**

var count int64
db.Model(&Profile{}).Where("user_id = ?", userID).Count(&count)
if count > 1 {
    return errors.New("multiple records found")
}

Hata Mesajları

**Required Error:** - "Profile is required" - "Profile cannot be empty"

**Type Error:** - "Profile must be a valid ID" - "Profile has invalid type"

**Not Found Error:** - "Profile with ID 42 does not exist" - "Profile not found"

**Duplicate Error:** - "Profile already exists for this user" - "User already has a profile"

Custom Validation

Özel validasyon kuralları eklenebilir:

field := fields.HasOne("Profile", "profile", "profiles").
    Validate(func(value interface{}) error {
        id := value.(uint)
        // Özel validasyon mantığı
        if id < 100 {
            return errors.New("profile ID must be >= 100")
        }
        return nil
    })

Veritabanı Constraint'leri

**Foreign Key Constraint:**

ALTER TABLE profiles
ADD CONSTRAINT fk_profiles_user_id
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE;

**Unique Constraint:**

ALTER TABLE profiles
ADD CONSTRAINT uk_profiles_user_id
UNIQUE (user_id);

Performans Optimizasyonu

**Cache Kullanımı:**

// Validation sonuçlarını cache'le
cacheKey := fmt.Sprintf("validation:%s:%v", h.Key, value)
if cached := cache.Get(cacheKey); cached != nil {
    return cached.(error)
}

**Batch Validation:**

// Birden fazla değeri tek sorguda doğrula
ids := []uint{1, 2, 3}
var count int64
db.Model(&Profile{}).Where("id IN ?", ids).Count(&count)

Önemli Notlar

- Şu anki implementasyon placeholder'dır (nil döndürür) - Gerçek implementasyon veritabanı erişimi gerektirir - Validasyon kuralları field konfigürasyonuna bağlıdır - Error mesajları kullanıcı dostu olmalıdır - Performans için cache kullanılabilir

Best Practices

- Validasyon kurallarını açık ve anlaşılır yapın - Error mesajlarını kullanıcı dostu yazın - Veritabanı constraint'lerini kullanın - Validasyonu hem client hem server tarafında yapın - Batch validation ile performansı artırın

Uyarılar

- Validasyon atlanmamalıdır (güvenlik riski) - Error mesajları hassas bilgi içermemelidir - Veritabanı hatalarını yakalayın ve loglamayı unutmayın - Race condition'lara dikkat edin (concurrent updates) - Transaction içinde validasyon yapın

Döndürür:

  • Validasyon hatası varsa error, geçerli ise nil

func (*HasOneField) WithEagerLoad

func (h *HasOneField) WithEagerLoad() *HasOneField

WithEagerLoad, yükleme stratejisini eager loading olarak ayarlar.

Eager loading, ilişkili kayıtların ana kayıtlarla birlikte tek sorguda yüklenmesini sağlar. Bu, N+1 sorgu problemini önler ve performansı önemli ölçüde artırır.

Eager Loading Nedir?

Eager loading, ilişkili verilerin önceden (eager) yüklenmesi anlamına gelir. Ana kayıtlar sorgulanırken, ilişkili kayıtlar da aynı anda JOIN veya ayrı bir sorgu ile yüklenir ve cache'lenir.

Kullanım Senaryoları

- **Liste Görünümleri**: Birden fazla kaydın ilişkileriyle birlikte gösterilmesi - **API Responses**: İlişkili verilerin tek response'da dönülmesi - **Raporlama**: Toplu veri çekimlerinde performans optimizasyonu - **Dashboard**: Özet bilgilerin hızlı yüklenmesi - **Export İşlemleri**: Büyük veri setlerinin verimli işlenmesi

Kullanım Örneği

// Eager loading ile (önerilen)
field := fields.HasOne("Profile", "profile", "profiles").
    WithEagerLoad()

// Kullanıcıları profilleriyle birlikte yükle
// SQL: SELECT * FROM users; SELECT * FROM profiles WHERE user_id IN (1,2,3,...)
users := []User{}
db.Preload("Profile").Find(&users)

Performans Karşılaştırması

**Lazy Loading (N+1 Problem):**

// 1 sorgu: Kullanıcıları getir
users := []User{} // 100 kullanıcı
db.Find(&users)

// 100 sorgu: Her kullanıcı için profil getir
for _, user := range users {
    db.Model(&user).Association("Profile").Find(&user.Profile)
}
// Toplam: 101 sorgu

**Eager Loading:**

// 2 sorgu: Kullanıcıları ve tüm profilleri getir
users := []User{}
db.Preload("Profile").Find(&users)
// Toplam: 2 sorgu (veya JOIN ile 1 sorgu)

GORM Entegrasyonu

Eager loading, GORM'un Preload fonksiyonu ile çalışır:

db.Preload("Profile").Find(&users)
db.Preload("Profile.Country").Find(&users) // İç içe ilişkiler

Avantajlar

- **Performans**: N+1 sorgu problemini önler - **Hız**: Tek seferde tüm veriler yüklenir - **Verimlilik**: Veritabanı bağlantı sayısını azaltır - **Öngörülebilirlik**: Sorgu sayısı sabittir - **Cache Dostu**: Tüm veriler bellekte hazır

Dezavantajlar

- **Bellek Kullanımı**: Tüm ilişkili veriler belleğe yüklenir - **Gereksiz Veri**: Kullanılmayacak veriler de yüklenebilir - **İlk Yükleme**: İlk sorgu daha yavaş olabilir - **Karmaşık Sorgular**: Çok sayıda ilişki JOIN karmaşıklığı artırır

Ne Zaman Kullanılmalı?

**Eager Loading Kullan:** - Liste görünümlerinde (index, table) - İlişkili veri kesinlikle gerekli olduğunda - Birden fazla kayıt işlenirken - API response'larında - Export/raporlama işlemlerinde

**Lazy Loading Kullan:** - Tek kayıt görünümlerinde (show, detail) - İlişkili veri nadiren gerekli olduğunda - Bellek kısıtlı ortamlarda - Çok büyük ilişkili veri setlerinde

Önemli Notlar

- Varsayılan strateji EAGER_LOADING'dir (N+1 problemini önlemek için) - Çok sayıda ilişki için selective preloading kullanın - İç içe ilişkiler için nokta notasyonu kullanın: "Profile.Country" - Conditional preloading için Query callback kullanın

İleri Seviye Kullanım

// Koşullu eager loading
field := fields.HasOne("Profile", "profile", "profiles").
    WithEagerLoad().
    Query(func(q interface{}) interface{} {
        return q.(*gorm.DB).Where("verified = ?", true)
    })

// İç içe ilişkiler
db.Preload("Profile.Country").
   Preload("Profile.Avatar").
   Find(&users)

Döndürür:

  • Yapılandırılmış HasOneField pointer'ı (method chaining için)

func (*HasOneField) WithHoverCard

func (h *HasOneField) WithHoverCard(config HoverCardConfig) *HasOneField

WithHoverCard, hover card konfigürasyonunu ayarlar.

Bu metod, index ve detail sayfalarında ilişkili kaydın hover card ile nasıl görüntüleneceğini belirler.

Parametreler

- **config**: Hover card konfigürasyonu

Kullanım Örneği (Deprecated - Yeni API kullanın)

field := fields.HasOne("Profile", "profile", "profiles").
    WithHoverCard(*fields.NewHoverCardConfig())

Yeni API (Önerilen)

field := fields.HasOne("Profile", "profile", "profiles").
    HoverCard(&ProfileHoverCard{}).
    ResolveHoverCard(func(ctx context.Context, record interface{}, relatedID interface{}, field fields.Field) (interface{}, error) {
        // Custom logic
        return &ProfileHoverCard{...}, nil
    })

Döndürür:

  • HasOneField pointer'ı (method chaining için)

func (*HasOneField) WithLazyLoad

func (h *HasOneField) WithLazyLoad() *HasOneField

WithLazyLoad, yükleme stratejisini lazy loading olarak ayarlar.

Lazy loading, ilişkili kayıtların sadece gerektiğinde (on-demand) yüklenmesini sağlar. Bu, ilk sorgu performansını artırır ancak N+1 sorgu problemine yol açabilir.

Lazy Loading Nedir?

Lazy loading, ilişkili verilerin geç (lazy) yüklenmesi anlamına gelir. Ana kayıtlar sorgulanırken ilişkili kayıtlar yüklenmez, sadece ilişkiye erişildiğinde ayrı bir sorgu ile yüklenir.

Kullanım Senaryoları

- **Detay Görünümleri**: Tek kaydın detaylı gösteriminde - **Koşullu Yükleme**: İlişkili veri sadece belirli durumlarda gerekli - **Bellek Optimizasyonu**: Büyük ilişkili veri setlerinde - **API Pagination**: Sayfalanmış sonuçlarda gereksiz veri yüklemesini önleme - **Selective Loading**: Kullanıcı tercihine göre veri yükleme

Kullanım Örneği

// Lazy loading ile
field := fields.HasOne("Profile", "profile", "profiles").
    WithLazyLoad()

// Kullanıcıyı yükle (profil yüklenmez)
user := User{}
db.First(&user, 1)

// Profil sadece erişildiğinde yüklenir
db.Model(&user).Association("Profile").Find(&user.Profile)

N+1 Sorgu Problemi

Lazy loading'in en büyük dezavantajı N+1 sorgu problemidir:

// 1 sorgu: 100 kullanıcı getir
users := []User{}
db.Find(&users)

// 100 sorgu: Her kullanıcı için ayrı profil sorgusu
for _, user := range users {
    db.Model(&user).Association("Profile").Find(&user.Profile)
    // Her iterasyonda yeni bir sorgu!
}
// Toplam: 101 sorgu (çok yavaş!)

Performans Karşılaştırması

**Lazy Loading:** - İlk yükleme: Hızlı (sadece ana kayıtlar) - İlişki erişimi: Yavaş (her erişimde yeni sorgu) - Toplam sorgu: N+1 (N = kayıt sayısı) - Bellek: Az (sadece gerekli veriler)

**Eager Loading:** - İlk yükleme: Yavaş (tüm veriler) - İlişki erişimi: Hızlı (zaten yüklü) - Toplam sorgu: 1-2 (sabit) - Bellek: Fazla (tüm veriler)

Avantajlar

- **İlk Yükleme Hızı**: Ana kayıtlar hızlı yüklenir - **Bellek Verimliliği**: Sadece gerekli veriler yüklenir - **Esneklik**: İlişki isteğe bağlı yüklenir - **Basitlik**: Otomatik çalışır, ekstra kod gerekmez - **Koşullu Yükleme**: Sadece gerektiğinde yükleme

Dezavantajlar

- **N+1 Problem**: Çok sayıda ek sorgu oluşur - **Performans**: Liste görünümlerinde çok yavaş - **Öngörülemezlik**: Sorgu sayısı değişkendir - **Veritabanı Yükü**: Çok sayıda bağlantı açılır - **Debugging**: Sorgu sayısını takip etmek zor

Ne Zaman Kullanılmalı?

**Lazy Loading Kullan:** - Tek kayıt görünümlerinde (show, detail, edit) - İlişkili veri nadiren gerekli olduğunda - Çok büyük ilişkili veri setlerinde - Bellek kısıtlı ortamlarda - Koşullu veri yükleme senaryolarında

**Eager Loading Kullan:** - Liste görünümlerinde (index, table, grid) - İlişkili veri kesinlikle gerekli olduğunda - Birden fazla kayıt işlenirken - API response'larında - Export/raporlama işlemlerinde

N+1 Problemini Önleme

Lazy loading kullanırken N+1 problemini önlemek için:

// 1. Manuel Preload kullan
db.Preload("Profile").Find(&users)

// 2. Batch loading kullan
db.Model(&users).Association("Profile").Find(&profiles)

// 3. Eager loading'e geç
field.WithEagerLoad()

Önemli Notlar

- Liste görünümlerinde lazy loading kullanmayın (N+1 riski) - Tek kayıt görünümlerinde lazy loading tercih edilebilir - Production'da sorgu sayısını mutlaka monitor edin - GORM'un Debug() modu ile sorguları kontrol edin

İleri Seviye Kullanım

// Koşullu lazy loading
field := fields.HasOne("Profile", "profile", "profiles").
    WithLazyLoad()

// Runtime'da eager loading'e geç
if needsProfile {
    db.Preload("Profile").Find(&users)
} else {
    db.Find(&users)
}

Debugging İpuçları

// Sorgu sayısını kontrol et
db.Debug().Find(&users) // SQL loglarını gösterir

// N+1 tespiti için
// Her iterasyonda "SELECT * FROM profiles" görüyorsanız N+1 var!

Uyarılar

- Production'da lazy loading kullanırken dikkatli olun - N+1 problemi ciddi performans sorunlarına yol açar - Büyük veri setlerinde veritabanını aşırı yükleyebilir - Liste görünümlerinde kesinlikle eager loading kullanın

Döndürür:

  • Yapılandırılmış HasOneField pointer'ı (method chaining için)

type Hideable

type Hideable struct {
	// contains filtered or unexported fields
}

Hideable, alanların görünürlüğünü kontrol etmesini sağlayan bir mixin'dir.

Farklı bağlamlarda (index, detail, create, update) görünürlük ve özel gizleme callback'leri için yapılandırma sağlar.

Kullanım

type PasswordField struct {
    fields.Base
    fields.Hideable
}

field := &PasswordField{}
field.SetShowOnIndex(false)
field.SetShowOnDetail(false)
field.SetShowOnCreate(true)
field.SetShowOnUpdate(true)

Daha fazla örnek için docs/Fields.md dosyasına bakın.

func (*Hideable) GetHideCallback

func (h *Hideable) GetHideCallback() func(*context.Context) bool

GetHideCallback, gizleme callback fonksiyonunu döndürür. Hiçbir callback ayarlanmamışsa nil döndürür.

Döndürür:

  • Gizleme callback fonksiyonu veya ayarlanmamışsa nil

func (*Hideable) IsHidden

func (h *Hideable) IsHidden() bool

IsHidden, alanın gizli olup olmadığını döndürür.

Döndürür:

  • Alan gizliyse true, değilse false

func (*Hideable) SetHidden

func (h *Hideable) SetHidden(hidden bool)

SetHidden, alanın gizli olup olmadığını ayarlar.

Parametreler:

  • hidden: Alanı gizlemek için true, göstermek için false

Örnek:

field.SetHidden(true)

func (*Hideable) SetHideCallback

func (h *Hideable) SetHideCallback(cb func(*context.Context) bool)

SetHideCallback, özel bir gizleme callback fonksiyonu ayarlar.

Callback, context'i alır ve alan gizlenmeli ise true, gösterilmeli ise false döndürmelidir.

Parametreler:

  • cb: Alanın gizlenip gizlenmeyeceğini belirleyen fonksiyon

Örnek:

field.SetHideCallback(func(ctx *context.Context) bool {
    user := ctx.User()
    return user == nil || !user.IsAdmin
})

func (*Hideable) SetShowOnCreate

func (h *Hideable) SetShowOnCreate(show bool)

SetShowOnCreate, alanın oluşturma formunda gösterilip gösterilmeyeceğini ayarlar.

func (*Hideable) SetShowOnDetail

func (h *Hideable) SetShowOnDetail(show bool)

SetShowOnDetail, alanın detay görünümünde gösterilip gösterilmeyeceğini ayarlar.

func (*Hideable) SetShowOnIndex

func (h *Hideable) SetShowOnIndex(show bool)

SetShowOnIndex, alanın liste görünümünde gösterilip gösterilmeyeceğini ayarlar.

func (*Hideable) SetShowOnUpdate

func (h *Hideable) SetShowOnUpdate(show bool)

SetShowOnUpdate, alanın güncelleme formunda gösterilip gösterilmeyeceğini ayarlar.

func (*Hideable) ShowOnCreate

func (h *Hideable) ShowOnCreate() bool

ShowOnCreate, alanın oluşturma formunda gösterilip gösterilmeyeceğini döner.

func (*Hideable) ShowOnDetail

func (h *Hideable) ShowOnDetail() bool

ShowOnDetail, alanın detay görünümünde gösterilip gösterilmeyeceğini döner.

func (*Hideable) ShowOnIndex

func (h *Hideable) ShowOnIndex() bool

ShowOnIndex, alanın liste görünümünde gösterilip gösterilmeyeceğini döner.

func (*Hideable) ShowOnUpdate

func (h *Hideable) ShowOnUpdate() bool

ShowOnUpdate, alanın güncelleme formunda gösterilip gösterilmeyeceğini döner.

type HoverCardConfig

type HoverCardConfig struct {
	// Enabled, hover card'ın aktif olup olmadığını belirler
	Enabled bool `json:"enabled"`

	// Struct, hover card verisi için kullanılacak struct (tip bilgisi)
	// Bu, JSON serialization için kullanılır
	Struct interface{} `json:"-"`

	// Resolver, hover card verilerini çözmek için callback fonksiyonu
	Resolver HoverCardResolver `json:"-"`

	// Width, hover card genişliği (örn. "sm", "md", "lg", "xl")
	Width string `json:"width,omitempty"`

	// OpenDelay, hover card açılma gecikmesi (ms)
	OpenDelay int `json:"open_delay,omitempty"`

	// CloseDelay, hover card kapanma gecikmesi (ms)
	CloseDelay int `json:"close_delay,omitempty"`
}

HoverCardConfig, ilişki field'ları için hover card görüntüleme ayarlarını yönetir.

Bu yapı, hasOne, belongsTo ve morphTo field'larının index ve detail sayfalarında hover card ile nasıl görüntüleneceğini kontrol eder.

Özellikler

- **Enabled**: Hover card'ın aktif olup olmadığını belirler - **Struct**: Hover card verisi için kullanılacak struct (tip bilgisi) - **Resolver**: Hover card verilerini çözmek için callback fonksiyonu - **Width**: Hover card genişliği (örn. "sm", "md", "lg", "xl") - **OpenDelay**: Hover card açılma gecikmesi (ms) - **CloseDelay**: Hover card kapanma gecikmesi (ms)

Kullanım Örneği

// Hover card struct'ı tanımla
type AuthorHoverCard struct {
    Avatar string `json:"avatar"`
    Name   string `json:"name"`
    Email  string `json:"email"`
    Phone  string `json:"phone"`
}

// Field'a hover card ekle
field := fields.BelongsTo("Author", "author_id", "authors").
    DisplayUsing("name").
    HoverCard(&AuthorHoverCard{}).
    ResolveHoverCard(func(ctx context.Context, record interface{}, relatedID interface{}, field fields.Field) (interface{}, error) {
        // İlişkili kaydı veritabanından al
        author := &Author{}
        db.First(author, relatedID)

        // Hover card verisini döndür
        return &AuthorHoverCard{
            Avatar: author.Avatar,
            Name:   author.Name,
            Email:  author.Email,
            Phone:  author.Phone,
        }, nil
    })

API Endpoint

Frontend, hover card açıldığında şu endpoint'e istek atar:

GET /api/resource/{resource}/resolver/{field_name}?id={related_id}
POST /api/resource/{resource}/resolver/{field_name} (body: {id: related_id})

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func NewHoverCardConfig

func NewHoverCardConfig() *HoverCardConfig

NewHoverCardConfig, varsayılan hover card konfigürasyonu oluşturur.

Bu fonksiyon, temel hover card ayarlarıyla bir konfigürasyon döndürür.

Varsayılan Değerler

- **Enabled**: true - **Width**: "md" - **OpenDelay**: 200ms - **CloseDelay**: 300ms

Kullanım Örneği

config := fields.NewHoverCardConfig()

Döndürür:

  • Varsayılan HoverCardConfig pointer'ı

func (*HoverCardConfig) Disable

func (h *HoverCardConfig) Disable() *HoverCardConfig

Disable, hover card'ı devre dışı bırakır.

Bu metod, hover card gösterimini tamamen kapatır.

Kullanım Örneği

config := fields.NewHoverCardConfig()
config.Disable()

Döndürür:

  • HoverCardConfig pointer'ı (method chaining için)

func (*HoverCardConfig) SetDelays

func (h *HoverCardConfig) SetDelays(openDelay, closeDelay int) *HoverCardConfig

SetDelays, hover card açılma ve kapanma gecikmelerini ayarlar.

Bu metod, hover card'ın açılma ve kapanma gecikmelerini belirler.

Parametreler

- **openDelay**: Açılma gecikmesi (ms) - **closeDelay**: Kapanma gecikmesi (ms)

Kullanım Örneği

config := fields.NewHoverCardConfig()
config.SetDelays(300, 500)

Döndürür:

  • HoverCardConfig pointer'ı (method chaining için)

func (*HoverCardConfig) SetResolver

func (h *HoverCardConfig) SetResolver(resolver HoverCardResolver) *HoverCardConfig

SetResolver, hover card verilerini çözmek için callback fonksiyonunu ayarlar.

Bu metod, hover card verilerini almak için kullanılacak resolver'ı belirler.

Parametreler

- **resolver**: Hover card resolver callback fonksiyonu

Kullanım Örneği

config := fields.NewHoverCardConfig()
config.SetResolver(func(ctx context.Context, record interface{}, relatedID interface{}, field fields.Field) (interface{}, error) {
    // Custom logic
    return &AuthorHoverCard{...}, nil
})

Döndürür:

  • HoverCardConfig pointer'ı (method chaining için)

func (*HoverCardConfig) SetStruct

func (h *HoverCardConfig) SetStruct(s interface{}) *HoverCardConfig

SetStruct, hover card verisi için kullanılacak struct'ı ayarlar.

Bu metod, hover card verisi için tip bilgisini belirler.

Parametreler

- **s**: Hover card struct'ı (örn. &AuthorHoverCard{})

Kullanım Örneği

config := fields.NewHoverCardConfig()
config.SetStruct(&AuthorHoverCard{})

Döndürür:

  • HoverCardConfig pointer'ı (method chaining için)

func (*HoverCardConfig) SetWidth

func (h *HoverCardConfig) SetWidth(width string) *HoverCardConfig

SetWidth, hover card genişliğini ayarlar.

Bu metod, hover card'ın genişliğini belirler.

Parametreler

- **width**: Genişlik değeri ("sm", "md", "lg", "xl")

Kullanım Örneği

config := fields.NewHoverCardConfig()
config.SetWidth("lg")

Döndürür:

  • HoverCardConfig pointer'ı (method chaining için)

type HoverCardResolver

type HoverCardResolver func(ctx context.Context, record interface{}, relatedID interface{}, field RelationshipField) (interface{}, error)

HoverCardResolver, hover card verilerini çözmek için kullanılan callback fonksiyonu tipi.

Bu fonksiyon, hover card açıldığında çağrılır ve ilişkili kaydın hover card verilerini döndürür.

Parametreler

- **ctx**: Context - **record**: Ana kayıt (örn. Post, Comment, vb.) - **relatedID**: İlişkili kaydın ID'si - **field**: Field instance

Döndürür

- **interface{}**: Hover card verisi (struct veya map) - **error**: Hata (varsa)

Kullanım Örneği

resolver := func(ctx context.Context, record interface{}, relatedID interface{}, field Field) (interface{}, error) {
    // İlişkili kaydı veritabanından al
    author := &Author{}
    db.First(author, relatedID)

    // Hover card verisini döndür
    return &AuthorHoverCard{
        Avatar: author.Avatar,
        Name:   author.Name,
        Email:  author.Email,
        Phone:  author.Phone,
    }, nil
}

type LoadingStrategy

type LoadingStrategy string

LoadingStrategy, ilişkilerin nasıl yükleneceğini tanımlar.

İki ana strateji vardır: - EAGER_LOADING: İlişkili verileri önceden yükler (N+1 sorgu problemini önler) - LAZY_LOADING: İlişkili verileri ihtiyaç anında yükler (bellek tasarrufu)

const (
	// EAGER_LOADING, ilişkili verileri önceden yükler.
	// N+1 sorgu problemini önlemek için önerilir.
	EAGER_LOADING LoadingStrategy = "eager"

	// LAZY_LOADING, ilişkili verileri ihtiyaç anında yükler.
	// Bellek tasarrufu sağlar ancak N+1 sorgu problemine neden olabilir.
	LAZY_LOADING LoadingStrategy = "lazy"
)

type MorphTo

type MorphTo struct {
	Schema
	TypeMappings       map[string]string // Type => Resource slug mapping
	DisplayMappings    map[string]string // Type => Display field name
	QueryCallback      func(query interface{}) interface{}
	LoadingStrategy    LoadingStrategy
	GormRelationConfig *RelationshipGormConfig
	// contains filtered or unexported fields
}

MorphTo, polimorfik ilişkiyi temsil eder (örn. Comment -> Commentable).

MorphTo ilişkisi, bir kaydın farklı tiplerdeki kayıtlara ait olabileceğini belirtir. Bu, veritabanında morph_type ve morph_id sütunları ile temsil edilir.

Kullanım Senaryoları

- **Comment -> Commentable**: Bir yorum hem Post'a hem de Video'ya ait olabilir - **Image -> Imageable**: Bir resim hem User'a hem de Product'a ait olabilir - **Tag -> Taggable**: Bir etiket hem Post'a hem de Video'ya ait olabilir

Özellikler

- **Tip Eşlemeleri**: Veritabanı tip değerleri ile resource slug'ları arasında eşleme - **Görüntüleme Eşlemeleri**: Her tip için görüntüleme alanı özelleştirme - **Eager/Lazy Loading**: Yükleme stratejisi seçimi - **GORM Yapılandırması**: Polimorfik sütunlar özelleştirme - **Hover Card**: Index ve detail sayfalarında hover card desteği

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    }).
    Displays(map[string]string{
        "post":  "title",
        "video": "name",
    }).
    WithEagerLoad()

// Hover card ile
field := fields.NewMorphTo("Commentable", "commentable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    }).
    WithHoverCard(fields.NewHoverCardConfig().
        WithAvatar("thumbnail", "").
        WithGrid([]fields.HoverCardGridField{
            {Key: "title", Label: "Başlık", Type: "text"},
            {Key: "created_at", Label: "Tarih", Type: "date"},
        }, "2-column"))

Veritabanı Yapısı

Polimorfik ilişki genellikle şu yapıya sahiptir:

CREATE TABLE comments (
    id INT PRIMARY KEY,
    commentable_type VARCHAR(255),  -- "post" veya "video"
    commentable_id INT,             -- İlgili kaydın ID'si
    content TEXT
);

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func NewMorphTo

func NewMorphTo(name, key string) *MorphTo

NewMorphTo, yeni bir MorphTo polimorfik ilişki alanı oluşturur.

Bu fonksiyon, farklı tiplerdeki kayıtlara ait olabilen polimorfik ilişkiler için kullanılır. Veritabanında morph_type ve morph_id sütunları ile temsil edilir.

Parametreler

- **name**: Alanın görünen adı (örn. "Commentable", "Imageable", "Taggable") - **key**: İlişki key'i (örn. "commentable", "imageable", "taggable")

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    }).
    Displays(map[string]string{
        "post":  "title",
        "video": "name",
    })

Varsayılan Değerler

- **TypeMappings**: Boş map (Types() ile doldurulmalıdır) - **DisplayMappings**: Boş map (Displays() ile doldurulmalıdır) - **LoadingStrategy**: EAGER_LOADING (N+1 sorgu problemini önler) - **Polimorfik Sütunlar**: key + "_type" ve key + "_id" (örn. "commentable_type", "commentable_id")

Önemli Notlar

- Types() metodu ile tip eşlemelerini tanımlamalısınız - Displays() metodu ile her tip için görüntüleme alanını belirtmelisiniz - Polimorfik sütunlar veritabanında mevcut olmalıdır

Döndürür:

  • Yapılandırılmış MorphTo pointer'ı

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func (*MorphTo) Displays

func (m *MorphTo) Displays(displays map[string]string) *MorphTo

Displays, her tip için görüntüleme alanını ayarlar.

Bu metod, her polimorfik tip için hangi alanın görüntüleneceğini belirler. Farklı tipler farklı görüntüleme alanlarına sahip olabilir.

Parametreler

- **displays**: Tip değeri -> görüntüleme alanı eşlemesi (örn. {"post": "title", "video": "name"})

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    }).
    Displays(map[string]string{
        "post":  "title",    // Post'lar için title alanı görüntülenir
        "video": "name",     // Video'lar için name alanı görüntülenir
    })

Önemli Notlar

- Her tip için görüntüleme alanı belirtilmelidir - Görüntüleme alanları, ilgili resource'larda mevcut olmalıdır - Frontend'de ilişkili kaydı gösterirken bu alanlar kullanılır

Döndürür:

  • MorphTo pointer'ı (method chaining için)

func (*MorphTo) Extract

func (m *MorphTo) Extract(resource interface{})

Extract, MorphTo'ya özgü veri çıkarma işlemini gerçekleştirir.

Bu metod, Schema.Extract'ı override eder çünkü MorphTo struct'ta doğrudan bir field'a sahip değildir. Bunun yerine, morph_type ve morph_id field'larından polimorfik ilişkiyi çözümler.

Parametreler

- **resource**: Veri çıkarılacak kaynak

Önemli Notlar

- Schema.Extract çağrılmaz çünkü MorphTo doğrudan bir field'a sahip değildir - ResolveRelationship kullanılarak polimorfik ilişki çözümlenir - Çözümlenen veriler m.Data'ya atanır

Kullanım Örneği

field.Extract(comment)
// m.Data = {"type": "post", "id": 123, "morphToType": "post", "morphToId": 123}

func (*MorphTo) GetDisplayKey

func (m *MorphTo) GetDisplayKey() string

GetDisplayKey, görüntüleme key'ini döndürür.

MorphTo için kullanılmaz çünkü her tip farklı görüntüleme alanına sahip olabilir. Her zaman boş string döndürür.

Döndürür:

  • Boş string (MorphTo için uygulanamaz)

func (*MorphTo) GetHoverCard

func (m *MorphTo) GetHoverCard() *HoverCardConfig

GetHoverCard, hover card konfigürasyonunu döndürür.

Bu metod, hover card konfigürasyonunu alır.

Döndürür:

  • HoverCardConfig pointer'ı (nil olabilir)

func (*MorphTo) GetLoadingStrategy

func (m *MorphTo) GetLoadingStrategy() LoadingStrategy

GetLoadingStrategy, yükleme stratejisini döndürür.

Yükleme stratejisi tanımlanmışsa onu döndürür, aksi takdirde varsayılan EAGER_LOADING döndürür.

Döndürür:

  • EAGER_LOADING veya LAZY_LOADING

func (*MorphTo) GetQueryCallback

func (m *MorphTo) GetQueryCallback() func(interface{}) interface{}

GetQueryCallback, sorgu callback'ini döndürür.

Sorgu özelleştirme callback'i tanımlanmışsa onu döndürür, aksi takdirde varsayılan (no-op) callback döndürür.

Döndürür:

  • Sorgu özelleştirme callback fonksiyonu

func (*MorphTo) GetRelatedResourceSlug

func (m *MorphTo) GetRelatedResourceSlug() string

GetRelatedResource, ilgili resource slug'ını döndürür.

MorphTo için uygulanamaz çünkü birden fazla resource'a ait olabilir. Her zaman boş string döndürür.

Döndürür:

  • Boş string (MorphTo için uygulanamaz)

func (*MorphTo) GetRelationshipName

func (m *MorphTo) GetRelationshipName() string

GetRelationshipName, ilişkinin adını döndürür.

Döndürür:

  • İlişkinin adı (örn. "Commentable", "Imageable")

func (*MorphTo) GetRelationshipType

func (m *MorphTo) GetRelationshipType() string

GetRelationshipType, ilişki türünü döndürür.

MorphTo için her zaman "morphTo" döndürür.

Döndürür:

  • "morphTo" string değeri

func (*MorphTo) GetResourceForType

func (m *MorphTo) GetResourceForType(morphType string) (string, error)

GetResourceForType, verilen tip için resource slug'ını döndürür.

Bu metod, morph type değerine karşılık gelen resource slug'ını bulur. Tip kayıtlı değilse hata döndürür.

Parametreler

- **morphType**: Morph type değeri (örn. "post", "video")

Kullanım Örneği

resource, err := field.GetResourceForType("post")
// resource = "posts"

resource, err := field.GetResourceForType("unknown")
// err = "morph type 'unknown' is not registered"

Döndürür:

  • Resource slug'ı (tip kayıtlıysa)
  • Hata (tip kayıtlı değilse)

func (*MorphTo) GetSearchableColumns

func (m *MorphTo) GetSearchableColumns() []string

GetSearchableColumns, aranabilir sütunları döndürür.

MorphTo için kullanılmaz çünkü polimorfik ilişkilerde doğrudan arama yapılmaz. Her zaman boş slice döndürür.

Döndürür:

  • Boş string slice (MorphTo için uygulanamaz)

func (*MorphTo) GetTypes

func (m *MorphTo) GetTypes() map[string]string

GetTypes, tip eşlemelerini döndürür.

Bu metod, polimorfik ilişki için tanımlanmış tüm tip eşlemelerini döndürür. Tip eşlemeleri, veritabanı tip değerleri ile resource slug'ları arasındaki ilişkiyi belirtir.

Döndürür:

  • Tip değeri -> resource slug eşlemesi (örn. {"post": "posts", "video": "videos"})
  • Boş map (tip eşlemeleri tanımlanmamışsa)

func (*MorphTo) HoverCard

func (m *MorphTo) HoverCard(hoverStruct interface{}) *MorphTo

HoverCard, hover card struct'ını ayarlar ve hover card'ı etkinleştirir.

Bu metod, hover card için kullanılacak struct'ı belirler ve hover card özelliğini aktif eder.

Parametreler

- **hoverStruct**: Hover card verisi için kullanılacak struct (örn. &CommentableHoverCard{})

Kullanım Örneği

type CommentableHoverCard struct {
    Thumbnail string `json:"thumbnail"`
    Title     string `json:"title"`
    Type      string `json:"type"`
}

field := fields.NewMorphTo("Commentable", "commentable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    }).
    HoverCard(&CommentableHoverCard{})

Döndürür:

  • MorphTo pointer'ı (method chaining için)

func (*MorphTo) IsRequired

func (m *MorphTo) IsRequired() bool

IsRequired, alanın zorunlu olup olmadığını döndürür.

Döndürür:

  • true ise alan zorunludur

func (*MorphTo) Query

func (m *MorphTo) Query(fn func(interface{}) interface{}) *MorphTo

Query, ilişki sorgusunu özelleştirmek için callback ayarlar.

Bu metod, polimorfik ilişki sorgularını özelleştirmek için kullanılır. Filtreleme, sıralama veya diğer sorgu modifikasyonları yapılabilir.

Parametreler

- **fn**: Sorgu özelleştirme callback fonksiyonu

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    Query(func(q interface{}) interface{} {
        // Sadece aktif kayıtları getir
        return q.(*gorm.DB).Where("status = ?", "active")
    })

Döndürür:

  • MorphTo pointer'ı (method chaining için)

func (*MorphTo) ResolveHoverCard

func (m *MorphTo) ResolveHoverCard(resolver HoverCardResolver) *MorphTo

ResolveHoverCard, hover card verilerini çözmek için callback fonksiyonunu ayarlar.

Bu metod, hover card açıldığında çağrılacak resolver fonksiyonunu belirler. Resolver, ilişkili kaydın hover card verilerini döndürür.

Parametreler

- **resolver**: Hover card resolver callback fonksiyonu

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    }).
    HoverCard(&CommentableHoverCard{}).
    ResolveHoverCard(func(ctx context.Context, record interface{}, relatedID interface{}, field fields.Field) (interface{}, error) {
        // MorphTo için tip bilgisini al
        morphType := record.(*Comment).CommentableType

        // Tip'e göre ilişkili kaydı al
        var data interface{}
        switch morphType {
        case "post":
            post := &Post{}
            if err := db.First(post, relatedID).Error; err != nil {
                return nil, err
            }
            data = post
        case "video":
            video := &Video{}
            if err := db.First(video, relatedID).Error; err != nil {
                return nil, err
            }
            data = video
        }

        // Hover card verisini döndür
        return &CommentableHoverCard{
            Thumbnail: data.Thumbnail,
            Title: data.Title,
            Type: morphType,
        }, nil
    })

API Endpoint

Frontend, hover card açıldığında şu endpoint'e istek atar:

GET /api/resource/{resource}/resolver/{field_name}?id={related_id}&type={morph_type}
POST /api/resource/{resource}/resolver/{field_name} (body: {id: related_id, type: morph_type})

Döndürür:

  • MorphTo pointer'ı (method chaining için)

func (*MorphTo) ResolveRelationship

func (m *MorphTo) ResolveRelationship(item interface{}) (interface{}, error)

ResolveRelationship, polimorfik ilişkiyi morph type'a göre çözümler.

Bu metod, reflection kullanarak struct'tan morph_type ve morph_id değerlerini çıkarır. Farklı field adı varyasyonlarını (CamelCase, snake_case) destekler.

Parametreler

- **item**: İlişkili verileri çözümlenecek kaynak

Döndürür

Polimorfik ilişki bilgilerini içeren map:

  • **type**: Morph type değeri (örn. "post", "video")
  • **id**: Morph ID değeri (ilgili kaydın ID'si)
  • **morphToType**: Morph type değeri (alias)
  • **morphToId**: Morph ID değeri (alias)

Desteklenen Field Adları

- Type için: "CommentableType", "Commentable_Type" - ID için: "CommentableID", "CommentableId", "Commentable_ID", "Commentable_Id"

Kullanım Örneği

type Comment struct {
    ID              int
    CommentableType string  // "post" veya "video"
    CommentableID   int     // İlgili kaydın ID'si
    Content         string
}

resolved, err := field.ResolveRelationship(comment)
// resolved = {"type": "post", "id": 123, "morphToType": "post", "morphToId": 123}

Döndürür:

  • İlişki bilgileri map'i veya nil
  • Hata (çözümleme başarısız olursa)

func (*MorphTo) Searchable

func (m *MorphTo) Searchable() Element

Searchable, alanı aranabilir olarak işaretler.

Bu metod, alanın global arama işlemlerine dahil edilmesini sağlar. Element interface'ini implement eder.

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    Searchable()
// Bu alan global arama işlemlerine dahil edilir

Döndürür:

  • Element interface'i (method chaining için)

func (*MorphTo) Types

func (m *MorphTo) Types(types map[string]string) *MorphTo

Types, polimorfik ilişki için tip eşlemelerini ayarlar.

Bu metod, veritabanındaki tip değerleri ile resource slug'ları arasında eşleme oluşturur. Her tip değeri, hangi resource'a karşılık geldiğini belirtir.

Parametreler

- **types**: Tip değeri -> resource slug eşlemesi (örn. {"post": "posts", "video": "videos"})

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
        "article": "articles",
    })
// commentable_type = "post" ise posts resource'u kullanılır
// commentable_type = "video" ise videos resource'u kullanılır

Önemli Notlar

- Tip değerleri veritabanında commentable_type sütununda saklanır - Resource slug'ları, ilgili resource'ların benzersiz tanımlayıcılarıdır - Tüm olası tip değerleri bu map'te tanımlanmalıdır - Frontend'de select dropdown olarak görüntülenir

Döndürür:

  • MorphTo pointer'ı (method chaining için)

func (*MorphTo) ValidateRelationship

func (m *MorphTo) ValidateRelationship(value interface{}) error

ValidateRelationship, ilişkiyi doğrular.

Bu metod, polimorfik ilişkinin geçerli olup olmadığını kontrol eder. Gerçek implementasyonda, morph type'ın tip eşlemelerinde kayıtlı olup olmadığını kontrol eder.

Parametreler

- **value**: Doğrulanacak değer

Döndürür

- Hata (doğrulama başarısız olursa)

Önemli Notlar

- Morph type, TypeMappings'te tanımlanmış olmalıdır - Gerçek implementasyonda veritabanı kısıtlamaları kontrol edilir

func (*MorphTo) WithEagerLoad

func (m *MorphTo) WithEagerLoad() *MorphTo

WithEagerLoad, yükleme stratejisini eager loading olarak ayarlar.

Eager loading, ilişkili verileri önceden yükler ve N+1 sorgu problemini önler. Polimorfik ilişkiler için önerilir.

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    WithEagerLoad()
// İlişkili veriler önceden yüklenir

Döndürür:

  • MorphTo pointer'ı (method chaining için)

func (*MorphTo) WithHoverCard

func (m *MorphTo) WithHoverCard(config HoverCardConfig) *MorphTo

WithHoverCard, hover card konfigürasyonunu ayarlar.

Bu metod, index ve detail sayfalarında ilişkili kaydın hover card ile nasıl görüntüleneceğini belirler.

Parametreler

- **config**: Hover card konfigürasyonu

Kullanım Örneği (Deprecated - Yeni API kullanın)

field := fields.NewMorphTo("Commentable", "commentable").
    WithHoverCard(*fields.NewHoverCardConfig())

Yeni API (Önerilen)

field := fields.NewMorphTo("Commentable", "commentable").
    HoverCard(&CommentableHoverCard{}).
    ResolveHoverCard(func(ctx context.Context, record interface{}, relatedID interface{}, field fields.Field) (interface{}, error) {
        // Custom logic
        return &CommentableHoverCard{...}, nil
    })

Döndürür:

  • MorphTo pointer'ı (method chaining için)

func (*MorphTo) WithLazyLoad

func (m *MorphTo) WithLazyLoad() *MorphTo

WithLazyLoad, yükleme stratejisini lazy loading olarak ayarlar.

Lazy loading, ilişkili verileri ihtiyaç anında yükler. Bellek tasarrufu sağlar ancak N+1 sorgu problemine neden olabilir.

Kullanım Örneği

field := fields.NewMorphTo("Commentable", "commentable").
    WithLazyLoad()
// İlişkili veriler ihtiyaç anında yüklenir

Döndürür:

  • MorphTo pointer'ı (method chaining için)

type MorphToMany

type MorphToMany struct {
	Schema
	TypeMappings       map[string]string // Type => Resource slug mapping
	DisplayMappings    map[string]string // Type => Display field name
	PivotTableName     string            // Pivot tablo adı
	ForeignKeyColumn   string            // Ana tablonun FK (örn. "tag_id")
	RelatedKeyColumn   string            // Polimorfik ID sütunu (örn. "taggable_id")
	MorphTypeColumn    string            // Polimorfik tip sütunu (örn. "taggable_type")
	QueryCallback      func(query interface{}) interface{}
	LoadingStrategy    LoadingStrategy
	GormRelationConfig *RelationshipGormConfig
}

MorphToMany, polimorfik many-to-many ilişkiyi temsil eder (örn. Tag -> Taggable: posts, videos).

MorphToMany ilişkisi, bir kaydın farklı tiplerdeki birden fazla kayda ait olabileceğini belirtir. Bu, veritabanında polimorfik pivot tablo ile temsil edilir.

Kullanım Senaryoları

- **Tag -> Taggable**: Bir etiket hem Post'lara hem de Video'lara ait olabilir - **Image -> Imageable**: Bir resim hem User'lara hem de Product'lara ait olabilir

Veritabanı Yapısı

Polimorfik pivot tablo genellikle şu yapıya sahiptir:

CREATE TABLE taggables (
    tag_id INT,              -- Ana tablo FK
    taggable_id INT,         -- Polimorfik ID
    taggable_type VARCHAR,   -- Polimorfik tip ("post", "video")
    PRIMARY KEY (tag_id, taggable_id, taggable_type)
);

Kullanım Örneği

field := fields.NewMorphToMany("Taggable", "taggable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    }).
    Displays(map[string]string{
        "post":  "title",
        "video": "name",
    }).
    PivotTable("taggables").
    AutoOptions("name").
    WithEagerLoad()

func NewMorphToMany

func NewMorphToMany(name, key string) *MorphToMany

NewMorphToMany, yeni bir MorphToMany polimorfik many-to-many ilişki alanı oluşturur.

Parametreler

- **name**: Alanın görünen adı (örn. "Taggable", "Imageable") - **key**: İlişki key'i (örn. "taggable", "imageable")

Varsayılan Değerler

- **PivotTableName**: key + "s" (örn. "taggables") - **ForeignKeyColumn**: "tag_id" (ana tablonun foreign key'i) - **RelatedKeyColumn**: key + "_id" (örn. "taggable_id") - **MorphTypeColumn**: key + "_type" (örn. "taggable_type") - **LoadingStrategy**: EAGER_LOADING

Döndürür:

  • Yapılandırılmış MorphToMany pointer'ı

func (*MorphToMany) AutoOptions

func (m *MorphToMany) AutoOptions(displayField string) *MorphToMany

AutoOptions, ilişkili tablodan otomatik options oluşturmayı etkinleştirir.

Bu metod, MorphToMany ilişkisinde ilişkili kayıtların otomatik olarak yüklenmesini ve frontend'de multi-select combobox'ta gösterilmesini sağlar.

Parametreler

- **displayField**: Option label'ı için kullanılacak sütun adı (örn. "name", "title")

Kullanım Örneği

field := fields.NewMorphToMany("Taggable", "taggable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    }).
    AutoOptions("name")  // Ana tablodaki "name" sütunu label olarak kullanılır

Döndürür:

  • MorphToMany pointer'ı (method chaining için)

func (*MorphToMany) Displays

func (m *MorphToMany) Displays(displays map[string]string) *MorphToMany

Displays, her tip için görüntüleme alanını ayarlar.

Parametreler

- **displays**: Tip değeri -> görüntüleme alanı eşlemesi (örn. {"post": "title", "video": "name"})

Kullanım Örneği

field := fields.NewMorphToMany("Taggable", "taggable").
    Displays(map[string]string{
        "post":  "title",
        "video": "name",
    })

Döndürür:

  • MorphToMany pointer'ı (method chaining için)

func (*MorphToMany) ForeignKey

func (m *MorphToMany) ForeignKey(key string) *MorphToMany

ForeignKey, ana tablonun foreign key sütun adını ayarlar.

Parametreler

- **key**: Foreign key sütun adı (örn. "tag_id")

Döndürür:

  • MorphToMany pointer'ı (method chaining için)

func (*MorphToMany) GetDisplayKey

func (m *MorphToMany) GetDisplayKey() string

GetDisplayKey, görüntüleme key'ini döndürür.

func (*MorphToMany) GetLoadingStrategy

func (m *MorphToMany) GetLoadingStrategy() LoadingStrategy

GetLoadingStrategy, yükleme stratejisini döndürür.

func (*MorphToMany) GetQueryCallback

func (m *MorphToMany) GetQueryCallback() func(interface{}) interface{}

GetQueryCallback, sorgu callback'ini döndürür.

func (*MorphToMany) GetRelatedResource

func (m *MorphToMany) GetRelatedResource() string

GetRelatedResource, ilgili resource slug'ını döndürür. MorphToMany için uygulanamaz çünkü birden fazla resource'a ait olabilir.

func (*MorphToMany) GetRelationshipName

func (m *MorphToMany) GetRelationshipName() string

GetRelationshipName, ilişkinin adını döndürür.

func (*MorphToMany) GetRelationshipType

func (m *MorphToMany) GetRelationshipType() string

GetRelationshipType, ilişki türünü döndürür.

func (*MorphToMany) GetSearchableColumns

func (m *MorphToMany) GetSearchableColumns() []string

GetSearchableColumns, aranabilir sütunları döndürür.

func (*MorphToMany) GetTypes

func (m *MorphToMany) GetTypes() map[string]string

GetTypes, tip eşlemelerini döndürür.

func (*MorphToMany) IsRequired

func (m *MorphToMany) IsRequired() bool

IsRequired, alanın zorunlu olup olmadığını döndürür.

func (*MorphToMany) MorphType

func (m *MorphToMany) MorphType(column string) *MorphToMany

MorphType, polimorfik tip sütun adını ayarlar.

Parametreler

- **column**: Polimorfik tip sütun adı (örn. "taggable_type")

Döndürür:

  • MorphToMany pointer'ı (method chaining için)

func (*MorphToMany) PivotTable

func (m *MorphToMany) PivotTable(tableName string) *MorphToMany

PivotTable, pivot tablo adını özelleştirir.

Parametreler

- **tableName**: Pivot tablo adı (örn. "taggables", "imageables")

Döndürür:

  • MorphToMany pointer'ı (method chaining için)

func (*MorphToMany) Query

func (m *MorphToMany) Query(fn func(interface{}) interface{}) *MorphToMany

Query, ilişki sorgusunu özelleştirmek için callback ayarlar.

func (*MorphToMany) RelatedKey

func (m *MorphToMany) RelatedKey(key string) *MorphToMany

RelatedKey, polimorfik ID sütun adını ayarlar.

Parametreler

- **key**: Polimorfik ID sütun adı (örn. "taggable_id")

Döndürür:

  • MorphToMany pointer'ı (method chaining için)

func (*MorphToMany) ResolveRelationship

func (m *MorphToMany) ResolveRelationship(item interface{}) (interface{}, error)

ResolveRelationship, polimorfik many-to-many ilişkiyi çözümler.

func (*MorphToMany) Searchable

func (m *MorphToMany) Searchable() Element

Searchable, alanı aranabilir olarak işaretler.

func (*MorphToMany) Types

func (m *MorphToMany) Types(types map[string]string) *MorphToMany

Types, polimorfik ilişki için tip eşlemelerini ayarlar.

Parametreler

- **types**: Tip değeri -> resource slug eşlemesi (örn. {"post": "posts", "video": "videos"})

Kullanım Örneği

field := fields.NewMorphToMany("Taggable", "taggable").
    Types(map[string]string{
        "post":  "posts",
        "video": "videos",
    })

Döndürür:

  • MorphToMany pointer'ı (method chaining için)

func (*MorphToMany) ValidateRelationship

func (m *MorphToMany) ValidateRelationship(value interface{}) error

ValidateRelationship, ilişkiyi doğrular.

func (*MorphToMany) WithEagerLoad

func (m *MorphToMany) WithEagerLoad() *MorphToMany

WithEagerLoad, yükleme stratejisini eager loading olarak ayarlar.

func (*MorphToMany) WithLazyLoad

func (m *MorphToMany) WithLazyLoad() *MorphToMany

WithLazyLoad, yükleme stratejisini lazy loading olarak ayarlar.

type PanelField

type PanelField struct {
	*Schema
	Fields []core.Element
}

PanelField, alanları bölümlere/kartlara gruplamak için bir konteyner temsil eder.

Panel, ilgili alanları görsel olarak gruplamak ve organize etmek için kullanılır. Form sayfalarında alanları mantıksal bölümlere ayırmak için idealdir.

Kullanım Senaryoları

- **Profil Bilgileri**: Ad, soyad, e-posta gibi kişisel bilgileri grupla - **Adres Bilgileri**: Şehir, ilçe, posta kodu gibi adres alanlarını grupla - **Güvenlik Ayarları**: Şifre, 2FA gibi güvenlik alanlarını grupla

Özellikler

- **Başlık**: Panel başlığı - **Açıklama**: Panel açıklaması (opsiyonel) - **Sütun Sayısı**: Grid sütun sayısı (1-4) - **Daraltılabilir**: Panel daraltılabilir/genişletilebilir - **Varsayılan Daraltılmış**: Panel varsayılan olarak daraltılmış

Kullanım Örneği

panel := fields.Panel("Kişisel Bilgiler",
    fields.Text("Ad", "first_name"),
    fields.Text("Soyad", "last_name"),
    fields.Email("E-posta", "email"),
).WithDescription("Kullanıcının kişisel bilgileri").
  WithColumns(2).
  Collapsible()

func Panel

func Panel(title string, fields ...core.Element) *PanelField

Panel, alanları gruplamak için yeni bir panel/bölüm oluşturur.

Bu fonksiyon, ilgili alanları görsel olarak gruplamak için bir konteyner oluşturur. Form sayfalarında alanları mantıksal bölümlere ayırmak için kullanılır.

Parametreler

- **title**: Panel başlığı (örn. "Kişisel Bilgiler", "Adres Bilgileri") - **fields**: Panel içinde görüntülenecek alanlar

Kullanım Örneği

panel := fields.Panel("Kişisel Bilgiler",
    fields.Text("Ad", "first_name"),
    fields.Text("Soyad", "last_name"),
    fields.Email("E-posta", "email"),
)

Döndürür:

  • Yapılandırılmış PanelField pointer'ı

func (*PanelField) Collapsible

func (p *PanelField) Collapsible() *PanelField

Collapsible, panel'i daraltılabilir yapar.

Bu metod, panel başlığına tıklandığında panel içeriğinin daraltılıp genişletilebilmesini sağlar. Uzun formlarda alan tasarrufu sağlamak için kullanılır.

Kullanım Örneği

panel.Collapsible()
// Panel başlığına tıklandığında içerik daraltılır/genişletilir

Döndürür:

  • PanelField pointer'ı (method chaining için)

func (*PanelField) DefaultCollapsed

func (p *PanelField) DefaultCollapsed() *PanelField

DefaultCollapsed, panel'in varsayılan olarak daraltılmış olmasını sağlar.

Bu metod, panel'in sayfa yüklendiğinde daraltılmış olarak görüntülenmesini sağlar. Kullanıcı panel başlığına tıklayarak içeriği genişletebilir.

Kullanım Örneği

panel.DefaultCollapsed()
// Panel sayfa yüklendiğinde daraltılmış olarak görüntülenir

Önemli Notlar

- Bu metod otomatik olarak Collapsible() özelliğini de aktif eder

Döndürür:

  • PanelField pointer'ı (method chaining için)

func (*PanelField) GetFields

func (p *PanelField) GetFields() []core.Element

GetFields, bu panel içindeki alanları döndürür.

Döndürür:

  • Panel içindeki alanların listesi

func (*PanelField) WithColumns

func (p *PanelField) WithColumns(columns int) *PanelField

WithColumns, panel için grid sütun sayısını ayarlar (1-4).

Bu metod, panel içindeki alanların kaç sütunda görüntüleneceğini belirler. Sütun sayısı 1 ile 4 arasında olmalıdır.

Parametreler

- **columns**: Sütun sayısı (1-4 arası)

Kullanım Örneği

panel.WithColumns(2)  // Alanlar 2 sütunda görüntülenir
panel.WithColumns(3)  // Alanlar 3 sütunda görüntülenir

Önemli Notlar

- Sütun sayısı 1'den küçükse 1'e ayarlanır - Sütun sayısı 4'ten büyükse 4'e ayarlanır

Döndürür:

  • PanelField pointer'ı (method chaining için)

func (*PanelField) WithDescription

func (p *PanelField) WithDescription(description string) *PanelField

WithDescription, panel'e açıklama ekler.

Bu metod, panel başlığının altında görüntülenecek açıklayıcı bir metin ekler. Kullanıcılara panel içeriği hakkında bilgi vermek için kullanılır.

Parametreler

- **description**: Panel açıklaması

Kullanım Örneği

panel.WithDescription("Kullanıcının kişisel bilgilerini girin")

Döndürür:

  • PanelField pointer'ı (method chaining için)

type Post

type Post struct {
	// ID, gönderinin benzersiz kimliğidir (primary key).
	ID int `json:"id"`

	// UserID, gönderinin sahibi olan kullanıcının ID'sidir (foreign key).
	UserID int `json:"user_id"`

	// Title, gönderinin başlığıdır.
	Title string `json:"title"`

	// Content, gönderinin içeriğidir.
	Content string `json:"content"`

	// Author, gönderinin sahibi olan kullanıcıdır (BelongsTo ilişkisi).
	// Bu alan opsiyoneldir ve eager loading ile doldurulur.
	Author *User `json:"author,omitempty"`
}

Post, bir blog gönderisini temsil eden model yapısıdır.

Bu model, kullanıcılar tarafından oluşturulan içerikleri tutar ve BelongsTo, HasMany ve BelongsToMany ilişkilerinin test edilmesinde kullanılır.

İlişkiler

- **BelongsTo**: User (her gönderi bir kullanıcıya aittir) - **HasMany**: Comments (bir gönderinin birden fazla yorumu olabilir) - **BelongsToMany**: Tags (bir gönderi birden fazla etikete sahip olabilir)

JSON Serileştirme

Author alanı opsiyoneldir ve `omitempty` ile işaretlenmiştir. İlişki yüklenmemişse JSON'da görünmez.

Örnek Kullanım

```go var post Post err := db.QueryRow(`

SELECT p.id, p.user_id, p.title, p.content,
       u.id, u.name, u.email
FROM posts p
LEFT JOIN users u ON p.user_id = u.id
WHERE p.id = ?

`, 1).Scan(&post.ID, &post.UserID, &post.Title, &post.Content,

&post.Author.ID, &post.Author.Name, &post.Author.Email)

```

type PostTag

type PostTag struct {
	// PostID, gönderinin ID'sidir (composite primary key'in bir parçası).
	PostID int `json:"post_id"`

	// TagID, etiketin ID'sidir (composite primary key'in bir parçası).
	TagID int `json:"tag_id"`
}

PostTag, gönderi-etiket ilişkisini temsil eden pivot model yapısıdır.

Bu model, Post ve Tag arasındaki çoka-çok (many-to-many) ilişkiyi tutar. BelongsToMany ilişkisinin test edilmesinde kullanılır.

İlişki Türü

Bu bir **pivot tablo** modelidir ve iki model arasındaki çoka-çok ilişkiyi sağlar: - Bir gönderi birden fazla etikete sahip olabilir - Bir etiket birden fazla gönderide kullanılabilir

Veritabanı Yapısı

- Composite primary key (post_id, tag_id) - Foreign key: post_id -> posts.id - Foreign key: tag_id -> tags.id

Önemli Notlar

- Bu tablo ek veri tutmaz, sadece ilişkiyi tanımlar - Composite primary key sayesinde aynı ilişki iki kez eklenemez - Pivot tablolar genellikle ek metadata tutabilir (created_at, vb.)

Örnek Kullanım

```go // Bir gönderiye etiket ekle _, err := db.Exec("INSERT INTO post_tag (post_id, tag_id) VALUES (?, ?)", 1, 2)

// Bir gönderinin tüm etiketlerini getir rows, err := db.Query(`

SELECT t.id, t.name
FROM tags t
JOIN post_tag pt ON t.id = pt.tag_id
WHERE pt.post_id = ?

`, 1) ```

type Profile

type Profile struct {
	// ID, profilin benzersiz kimliğidir (primary key).
	ID int `json:"id"`

	// UserID, profilin ait olduğu kullanıcının ID'sidir (foreign key, unique).
	UserID int `json:"user_id"`

	// Bio, kullanıcının biyografisidir.
	Bio string `json:"bio"`

	// AvatarURL, kullanıcının profil resminin URL'sidir.
	AvatarURL string `json:"avatar_url"`

	// User, profilin ait olduğu kullanıcıdır (BelongsTo ilişkisi).
	// Bu alan opsiyoneldir ve eager loading ile doldurulur.
	User *User `json:"user,omitempty"`
}

Profile, bir kullanıcı profilini temsil eden model yapısıdır.

Bu model, kullanıcıların ek bilgilerini tutar ve HasOne ilişkisinin test edilmesinde kullanılır. Her kullanıcının yalnızca bir profili olabilir.

İlişkiler

- **BelongsTo**: User (her profil bir kullanıcıya aittir) - **HasOne** (ters yönde): User -> Profile

JSON Serileştirme

User alanı opsiyoneldir ve `omitempty` ile işaretlenmiştir. İlişki yüklenmemişse JSON'da görünmez.

Önemli Notlar

- UserID alanı UNIQUE constraint'e sahiptir - Bir kullanıcının yalnızca bir profili olabilir - Profil olmadan kullanıcı var olabilir (opsiyonel ilişki)

Örnek Kullanım

```go var profile Profile err := db.QueryRow(`

SELECT p.id, p.user_id, p.bio, p.avatar_url,
       u.id, u.name, u.email
FROM profiles p
LEFT JOIN users u ON p.user_id = u.id
WHERE p.user_id = ?

`, 1).Scan(&profile.ID, &profile.UserID, &profile.Bio, &profile.AvatarURL,

&profile.User.ID, &profile.User.Name, &profile.User.Email)

```

type RelationshipConstraints

type RelationshipConstraints interface {
	// ApplyLimit, sorgu sonuç sayısını sınırlar.
	//
	// # Parametreler
	//
	// - `ctx`: Context nesnesi
	// - `limit`: Maksimum sonuç sayısı (negatif değerler 0'a dönüştürülür)
	//
	// # Döndürür
	//
	// - `[]interface{}`: Kısıtlanmış sonuç listesi
	// - `error`: Hata durumunda hata nesnesi
	//
	// # Örnek
	//
	// “`go
	// results, err := constraints.ApplyLimit(ctx, 10)
	// if err != nil {
	//     log.Fatal(err)
	// }
	// “`
	ApplyLimit(ctx context.Context, limit int) ([]interface{}, error)

	// ApplyOffset, sorgu başlangıç noktasını kaydırır.
	//
	// # Parametreler
	//
	// - `ctx`: Context nesnesi
	// - `offset`: Kaç kayıt atlanacağı (negatif değerler 0'a dönüştürülür)
	//
	// # Döndürür
	//
	// - `[]interface{}`: Kaydırılmış sonuç listesi
	// - `error`: Hata durumunda hata nesnesi
	//
	// # Örnek
	//
	// “`go
	// // İlk 5 kaydı atla
	// results, err := constraints.ApplyOffset(ctx, 5)
	// if err != nil {
	//     log.Fatal(err)
	// }
	// “`
	ApplyOffset(ctx context.Context, offset int) ([]interface{}, error)

	// ApplyWhere, sorguya WHERE koşulu ekler.
	//
	// # Parametreler
	//
	// - `ctx`: Context nesnesi
	// - `column`: Koşul uygulanacak sütun adı
	// - `operator`: Karşılaştırma operatörü (=, !=, >, <, >=, <=, LIKE, vb.)
	// - `value`: Karşılaştırılacak değer
	//
	// # Döndürür
	//
	// - `[]interface{}`: Filtrelenmiş sonuç listesi
	// - `error`: Hata durumunda hata nesnesi
	//
	// # Örnek
	//
	// “`go
	// // Aktif kayıtları getir
	// results, err := constraints.ApplyWhere(ctx, "status", "=", "active")
	//
	// // Fiyatı 100'den büyük olanları getir
	// results, err = constraints.ApplyWhere(ctx, "price", ">", 100)
	// “`
	//
	// # Not
	//
	// Boş column değeri durumunda işlem yapılmaz ve boş liste döner.
	ApplyWhere(ctx context.Context, column string, operator string, value interface{}) ([]interface{}, error)

	// ApplyWhereIn, sorguya WHERE IN koşulu ekler.
	//
	// # Parametreler
	//
	// - `ctx`: Context nesnesi
	// - `column`: Koşul uygulanacak sütun adı
	// - `values`: Kontrol edilecek değerler listesi
	//
	// # Döndürür
	//
	// - `[]interface{}`: Filtrelenmiş sonuç listesi
	// - `error`: Hata durumunda hata nesnesi
	//
	// # Örnek
	//
	// “`go
	// // Belirli ID'lere sahip kayıtları getir
	// results, err := constraints.ApplyWhereIn(ctx, "id", []interface{}{1, 2, 3, 5, 8})
	//
	// // Belirli kategorilerdeki kayıtları getir
	// results, err = constraints.ApplyWhereIn(ctx, "category", []interface{}{"tech", "science", "art"})
	// “`
	//
	// # Not
	//
	// Boş column veya values durumunda işlem yapılmaz ve boş liste döner.
	ApplyWhereIn(ctx context.Context, column string, values []interface{}) ([]interface{}, error)
}

RelationshipConstraints, ilişkisel alanlar için sorgu kısıtlamaları uygulayan interface'dir.

Bu interface, relationship field'ları üzerinde LIMIT, OFFSET, WHERE ve WHERE IN gibi SQL kısıtlamalarını uygulamak için metodlar sağlar. Her metod context alır ve sonuçları döndürür.

Metodlar

- `ApplyLimit`: Sorgu sonuç sayısını sınırlar - `ApplyOffset`: Sorgu başlangıç noktasını kaydırır - `ApplyWhere`: WHERE koşulu ekler - `ApplyWhereIn`: WHERE IN koşulu ekler

Örnek Kullanım

```go constraints := NewRelationshipConstraints(relationshipField)

// Limit uygula results, err := constraints.ApplyLimit(ctx, 10)

// Offset uygula results, err = constraints.ApplyOffset(ctx, 5)

// WHERE koşulu ekle results, err = constraints.ApplyWhere(ctx, "status", "=", "active")

// WHERE IN koşulu ekle results, err = constraints.ApplyWhereIn(ctx, "id", []interface{}{1, 2, 3}) ```

Referans

Detaylı bilgi için: docs/Relationships.md(../../docs/Relationships.md)

type RelationshipConstraintsImpl

type RelationshipConstraintsImpl struct {
	// contains filtered or unexported fields
}

RelationshipConstraintsImpl, RelationshipConstraints interface'inin implementasyonudur.

Bu struct, relationship field'ları üzerinde sorgu kısıtlamalarını yönetir. Limit, offset ve WHERE koşullarını saklar ve uygular.

Alanlar

- `field`: İlişkili field nesnesi - `limit`: Maksimum sonuç sayısı (0 = sınırsız) - `offset`: Atlanacak kayıt sayısı - `constraints`: WHERE koşulları map'i

Örnek Kullanım

```go // Yeni constraints handler oluştur constraints := NewRelationshipConstraints(relationshipField)

// Kısıtlamaları uygula constraints.ApplyLimit(ctx, 10) constraints.ApplyOffset(ctx, 5) constraints.ApplyWhere(ctx, "status", "=", "active")

// Değerleri oku limit := constraints.GetLimit() // 10 offset := constraints.GetOffset() // 5 where := constraints.GetConstraints() // map[status:...] ```

Referans

Detaylı bilgi için: docs/Relationships.md(../../docs/Relationships.md)

func NewRelationshipConstraints

func NewRelationshipConstraints(field RelationshipField) *RelationshipConstraintsImpl

NewRelationshipConstraints, yeni bir relationship constraints handler oluşturur.

Bu constructor, verilen relationship field için kısıtlama yöneticisi oluşturur. Tüm kısıtlamalar varsayılan değerlerle (limit=0, offset=0, boş constraints) başlatılır.

Parametreler

- `field`: Kısıtlamaların uygulanacağı RelationshipField nesnesi

Döndürür

- Yapılandırılmış RelationshipConstraintsImpl pointer'ı

Örnek

```go // Relationship field oluştur relationshipField := fields.NewBelongsTo("user", "User")

// Constraints handler oluştur constraints := NewRelationshipConstraints(relationshipField)

// Kısıtlamaları uygula results, err := constraints.ApplyLimit(ctx, 10)

if err != nil {
    log.Fatal(err)
}

```

Not

- Limit ve offset başlangıçta 0 olarak ayarlanır - Constraints map'i boş olarak başlatılır - Field parametresi nil olmamalıdır

Referans

Detaylı bilgi için: docs/Relationships.md(../../docs/Relationships.md)

func (*RelationshipConstraintsImpl) ApplyLimit

func (rc *RelationshipConstraintsImpl) ApplyLimit(ctx context.Context, limit int) ([]interface{}, error)

ApplyLimit, sorgu sonuç sayısını sınırlar.

Bu metod, relationship sorgusu için maksimum sonuç sayısını belirler. Negatif değerler otomatik olarak 0'a dönüştürülür.

Parametreler

- `ctx`: Context nesnesi (timeout, cancellation için) - `limit`: Maksimum sonuç sayısı (0 = sınırsız, negatif değerler 0'a çevrilir)

Döndürür

- `[]interface{}`: Kısıtlanmış sonuç listesi (şu anki implementasyonda boş) - `error`: Hata durumunda hata nesnesi

Örnek

```go constraints := NewRelationshipConstraints(relationshipField)

// İlk 10 kaydı getir results, err := constraints.ApplyLimit(ctx, 10)

if err != nil {
    log.Fatal(err)
}

// Limit değerini kontrol et fmt.Println(constraints.GetLimit()) // 10 ```

Not

- Negatif limit değerleri 0'a dönüştürülür - Limit değeri struct içinde saklanır - Gerçek implementasyonda bu değer sorguya uygulanır

func (*RelationshipConstraintsImpl) ApplyOffset

func (rc *RelationshipConstraintsImpl) ApplyOffset(ctx context.Context, offset int) ([]interface{}, error)

ApplyOffset, sorgu başlangıç noktasını kaydırır.

Bu metod, relationship sorgusu için kaç kaydın atlanacağını belirler. Pagination (sayfalama) işlemleri için kullanılır. Negatif değerler otomatik olarak 0'a dönüştürülür.

Parametreler

- `ctx`: Context nesnesi (timeout, cancellation için) - `offset`: Atlanacak kayıt sayısı (negatif değerler 0'a çevrilir)

Döndürür

- `[]interface{}`: Kaydırılmış sonuç listesi (şu anki implementasyonda boş) - `error`: Hata durumunda hata nesnesi

Örnek

```go constraints := NewRelationshipConstraints(relationshipField)

// Sayfa 2 için (her sayfada 10 kayıt) constraints.ApplyLimit(ctx, 10) results, err := constraints.ApplyOffset(ctx, 10)

if err != nil {
    log.Fatal(err)
}

// Offset değerini kontrol et fmt.Println(constraints.GetOffset()) // 10 ```

Not

- Negatif offset değerleri 0'a dönüştürülür - Offset değeri struct içinde saklanır - Genellikle limit ile birlikte kullanılır (pagination) - Gerçek implementasyonda bu değer sorguya uygulanır

func (*RelationshipConstraintsImpl) ApplyWhere

func (rc *RelationshipConstraintsImpl) ApplyWhere(ctx context.Context, column string, operator string, value interface{}) ([]interface{}, error)

ApplyWhere, sorguya WHERE koşulu ekler.

Bu metod, relationship sorgusu için WHERE koşulu ekler. Belirtilen sütun, operatör ve değer kullanılarak filtreleme yapılır. Koşul constraints map'inde saklanır ve gerçek implementasyonda sorguya uygulanır.

Parametreler

- `ctx`: Context nesnesi (timeout, cancellation için) - `column`: Koşul uygulanacak sütun adı (boş olamaz) - `operator`: Karşılaştırma operatörü (=, !=, >, <, >=, <=, LIKE, vb.) - `value`: Karşılaştırılacak değer (herhangi bir tip olabilir)

Döndürür

- `[]interface{}`: Filtrelenmiş sonuç listesi (şu anki implementasyonda boş) - `error`: Hata durumunda hata nesnesi

Örnek

```go constraints := NewRelationshipConstraints(relationshipField)

// Aktif kayıtları getir results, err := constraints.ApplyWhere(ctx, "status", "=", "active")

if err != nil {
    log.Fatal(err)
}

// Fiyatı 100'den büyük olanları getir results, err = constraints.ApplyWhere(ctx, "price", ">", 100)

// LIKE operatörü ile arama results, err = constraints.ApplyWhere(ctx, "name", "LIKE", "%test%")

// Koşulları kontrol et constraints := constraints.GetConstraints() fmt.Println(constraints["status"]) // map[operator:= value:active] ```

Not

- Boş column değeri durumunda işlem yapılmaz ve boş liste döner - Aynı sütun için birden fazla koşul eklenirse son eklenen geçerli olur - Koşul map formatında saklanır: map[operator:... value:...] - Gerçek implementasyonda bu koşul sorguya uygulanır

Desteklenen Operatörler

- `=`: Eşittir - `!=`: Eşit değildir - `>`: Büyüktür - `<`: Küçüktür - `>=`: Büyük eşittir - `<=`: Küçük eşittir - `LIKE`: Benzer (pattern matching) - `NOT LIKE`: Benzer değil

func (*RelationshipConstraintsImpl) ApplyWhereIn

func (rc *RelationshipConstraintsImpl) ApplyWhereIn(ctx context.Context, column string, values []interface{}) ([]interface{}, error)

ApplyWhereIn, sorguya WHERE IN koşulu ekler.

Bu metod, relationship sorgusu için WHERE IN koşulu ekler. Belirtilen sütunun değerinin verilen değerler listesinde olup olmadığını kontrol eder. Koşul constraints map'inde saklanır ve gerçek implementasyonda sorguya uygulanır.

Parametreler

- `ctx`: Context nesnesi (timeout, cancellation için) - `column`: Koşul uygulanacak sütun adı (boş olamaz) - `values`: Kontrol edilecek değerler listesi (boş olamaz)

Döndürür

- `[]interface{}`: Filtrelenmiş sonuç listesi (şu anki implementasyonda boş) - `error`: Hata durumunda hata nesnesi

Örnek

```go constraints := NewRelationshipConstraints(relationshipField)

// Belirli ID'lere sahip kayıtları getir results, err := constraints.ApplyWhereIn(ctx, "id", []interface{}{1, 2, 3, 5, 8})

if err != nil {
    log.Fatal(err)
}

// Belirli kategorilerdeki kayıtları getir results, err = constraints.ApplyWhereIn(ctx, "category", []interface{}{"tech", "science", "art"})

// Belirli durumlardaki kayıtları getir results, err = constraints.ApplyWhereIn(ctx, "status", []interface{}{"active", "pending", "approved"})

// Koşulları kontrol et constraints := constraints.GetConstraints() fmt.Println(constraints["id"]) // map[in:[1 2 3 5 8]] ```

Not

- Boş column veya values durumunda işlem yapılmaz ve boş liste döner - Aynı sütun için birden fazla koşul eklenirse son eklenen geçerli olur - Koşul map formatında saklanır: map[in:[...]] - Gerçek implementasyonda bu koşul sorguya uygulanır - Values listesi herhangi bir tip içerebilir (int, string, vb.)

Performans Notu

WHERE IN sorguları büyük değer listeleri ile yavaş olabilir. Çok sayıda değer için alternatif yöntemler düşünülmelidir.

func (*RelationshipConstraintsImpl) GetConstraints

func (rc *RelationshipConstraintsImpl) GetConstraints() map[string]interface{}

GetConstraints, tüm WHERE koşullarını döndürür.

Bu metod, ApplyWhere ve ApplyWhereIn ile eklenen tüm koşulları map formatında döndürür. Her sütun için koşul bilgisi içerir.

Döndürür

- WHERE koşulları map'i (sütun adı -> koşul detayları)

Map Formatı

WHERE koşulu için: ```go

map[string]interface{}{
    "column_name": map[string]interface{}{
        "operator": "=",
        "value": "some_value",
    },
}

```

WHERE IN koşulu için: ```go

map[string]interface{}{
    "column_name": map[string]interface{}{
        "in": []interface{}{1, 2, 3},
    },
}

```

Örnek

```go constraints := NewRelationshipConstraints(relationshipField) constraints.ApplyWhere(ctx, "status", "=", "active") constraints.ApplyWhereIn(ctx, "id", []interface{}{1, 2, 3})

allConstraints := constraints.GetConstraints() fmt.Println(allConstraints) // Output: // map[ // status:map[operator:= value:active] // id:map[in:[1 2 3]] // ]

// Belirli bir koşulu kontrol et

if statusConstraint, ok := allConstraints["status"]; ok {
    constraint := statusConstraint.(map[string]interface{})
    fmt.Println(constraint["operator"]) // =
    fmt.Println(constraint["value"])    // active
}

```

Not

- Döndürülen map referans olarak döner, değişiklikler orijinal map'i etkiler - Boş map döndürülmesi hiç koşul eklenmediği anlamına gelir

func (*RelationshipConstraintsImpl) GetLimit

func (rc *RelationshipConstraintsImpl) GetLimit() int

GetLimit, mevcut limit değerini döndürür.

Bu metod, ApplyLimit ile ayarlanan limit değerini okur.

Döndürür

- Mevcut limit değeri (0 = sınırsız)

Örnek

```go constraints := NewRelationshipConstraints(relationshipField) constraints.ApplyLimit(ctx, 10)

limit := constraints.GetLimit() fmt.Println(limit) // 10 ```

func (*RelationshipConstraintsImpl) GetOffset

func (rc *RelationshipConstraintsImpl) GetOffset() int

GetOffset, mevcut offset değerini döndürür.

Bu metod, ApplyOffset ile ayarlanan offset değerini okur.

Döndürür

- Mevcut offset değeri (0 = baştan başla)

Örnek

```go constraints := NewRelationshipConstraints(relationshipField) constraints.ApplyOffset(ctx, 20)

offset := constraints.GetOffset() fmt.Println(offset) // 20 ```

type RelationshipCounting

type RelationshipCounting interface {
	// Count, ilişkili kaynakların sayısını döndürür.
	//
	// # Parametreler
	//
	// - `ctx`: İşlem context'i (timeout, iptal kontrolü için)
	//
	// # Dönüş Değerleri
	//
	// - `int64`: İlişkili kaynak sayısı
	// - `error`: Hata durumunda hata mesajı
	//
	// # İlişki Türlerine Göre Davranış
	//
	// | İlişki Türü    | Dönüş Değeri              |
	// |----------------|---------------------------|
	// | belongsTo      | 0 veya 1                  |
	// | hasOne         | 0 veya 1                  |
	// | hasMany        | İlişkili kaynak sayısı    |
	// | belongsToMany  | Pivot tablo kayıt sayısı  |
	// | morphTo        | 0 veya 1                  |
	Count(ctx context.Context) (int64, error)
}

RelationshipCounting, ilişkiler için sayma işlevselliğini yöneten interface'dir.

Bu interface, farklı ilişki türlerindeki ilişkili kaynakların sayısını hesaplamak için kullanılır. Her ilişki türü kendi sayma mantığına sahiptir.

Kullanım Örneği

```go counter := NewRelationshipCounting(relationshipField) count, err := counter.Count(ctx)

if err != nil {
    log.Fatal(err)
}

fmt.Printf("İlişkili kaynak sayısı: %d\n", count) ```

Önemli Notlar

- Context parametresi timeout ve iptal işlemleri için kullanılır - Hata durumunda 0 ve ilgili hata döner - Bilinmeyen ilişki türleri için 0 döner (hata vermez)

type RelationshipCountingImpl

type RelationshipCountingImpl struct {
	// contains filtered or unexported fields
}

RelationshipCountingImpl, RelationshipCounting interface'inin varsayılan implementasyonudur.

Bu struct, ilişki alanı (RelationshipField) üzerinden ilişki türünü tespit eder ve uygun sayma metodunu çağırır.

Kullanım Örneği

```go // Constructor ile oluşturma (önerilen) counter := NewRelationshipCounting(relationshipField)

// Manuel oluşturma

counter := &RelationshipCountingImpl{
    field: relationshipField,
}

// Sayma işlemi count, err := counter.Count(context.Background()) ```

Önemli Notlar

- Constructor fonksiyonu (`NewRelationshipCounting`) kullanımı önerilir - `field` parametresi nil olmamalıdır - Thread-safe değildir, concurrent kullanım için senkronizasyon gerekir

func NewRelationshipCounting

func NewRelationshipCounting(field RelationshipField) *RelationshipCountingImpl

NewRelationshipCounting, yeni bir RelationshipCountingImpl instance'ı oluşturur.

Bu constructor fonksiyonu, ilişki sayma işlevselliği için gerekli yapılandırmayı yapar ve kullanıma hazır bir instance döner.

Parametreler

- `field`: İlişki alanı (RelationshipField interface'ini implement etmeli)

Dönüş Değerleri

- `*RelationshipCountingImpl`: Yapılandırılmış RelationshipCountingImpl pointer'ı

Kullanım Örneği

```go // BelongsTo ilişkisi için belongsToField := NewBelongsTo("author", &User{}) counter := NewRelationshipCounting(belongsToField) count, _ := counter.Count(ctx)

// HasMany ilişkisi için hasManyField := NewHasMany("posts", &Post{}) counter := NewRelationshipCounting(hasManyField) count, _ := counter.Count(ctx)

// BelongsToMany ilişkisi için manyToManyField := NewBelongsToMany("tags", &Tag{}, "post_tags") counter := NewRelationshipCounting(manyToManyField) count, _ := counter.Count(ctx) ```

Önemli Notlar

- `field` parametresi nil olmamalıdır - Dönen pointer nil kontrolü gerektirmez (her zaman geçerli bir instance döner) - Method chaining için uygun değildir (immutable pattern kullanılmamıştır)

Referanslar

İlişki türleri hakkında detaylı bilgi: `docs/Relationships.md`

func (*RelationshipCountingImpl) Count

Count, ilişkili kaynakların sayısını döndürür.

Bu method, ilişki türünü tespit eder ve uygun sayma metodunu çağırır. Her ilişki türü için farklı sayma mantığı uygulanır.

Parametreler

- `ctx`: İşlem context'i (timeout, iptal kontrolü için)

Dönüş Değerleri

- `int64`: İlişkili kaynak sayısı - `error`: Hata durumunda hata mesajı

İlişki Türlerine Göre Davranış

| İlişki Türü | Method | Dönüş Değeri | |----------------|---------------------|---------------------------| | belongsTo | countBelongsTo() | 0 veya 1 | | hasOne | countHasOne() | 0 veya 1 | | hasMany | countHasMany() | İlişkili kaynak sayısı | | belongsToMany | countBelongsToMany()| Pivot tablo kayıt sayısı | | morphTo | countMorphTo() | 0 veya 1 | | Bilinmeyen | - | 0 (hata vermez) |

Kullanım Örneği

```go counter := NewRelationshipCounting(relationshipField)

// Context ile sayma ctx := context.Background() count, err := counter.Count(ctx)

if err != nil {
    log.Printf("Sayma hatası: %v", err)
    return
}

fmt.Printf("İlişkili kaynak sayısı: %d\n", count)

// Timeout ile sayma ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() count, err = counter.Count(ctx) ```

Önemli Notlar

- Bilinmeyen ilişki türleri için 0 döner ve hata vermez - Context timeout veya iptal durumunda ilgili hata döner - Thread-safe değildir, concurrent kullanım için senkronizasyon gerekir

Referanslar

İlişki türleri hakkında detaylı bilgi: `docs/Relationships.md`

type RelationshipDisplay

type RelationshipDisplay interface {
	// GetDisplayValue, bir ilişki için görüntüleme değerini döndürür
	GetDisplayValue(item interface{}) (string, error)

	// GetDisplayValues, birden fazla öğe için görüntüleme değerlerini döndürür
	GetDisplayValues(items []interface{}) ([]string, error)

	// FormatDisplayValue, bir görüntüleme değerini formatlar
	FormatDisplayValue(value interface{}) string
}

RelationshipDisplay, ilişkiler için görüntüleme özelleştirmesini yönetir.

Bu interface, ilişkili kayıtların nasıl görüntüleneceğini kontrol eder. Her ilişki türü için farklı görüntüleme stratejileri sağlar.

Kullanım Örneği

display := fields.NewRelationshipDisplay(field)
value, err := display.GetDisplayValue(item)

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

type RelationshipDisplayImpl

type RelationshipDisplayImpl struct {
	// contains filtered or unexported fields
}

RelationshipDisplayImpl, RelationshipDisplay interface'ini implement eder.

Bu yapı, ilişki görüntüleme işlemlerini gerçekleştirir. Her ilişki türü için özel görüntüleme mantığı sağlar.

func NewRelationshipDisplay

func NewRelationshipDisplay(field RelationshipField) *RelationshipDisplayImpl

NewRelationshipDisplay, yeni bir relationship display handler oluşturur.

Bu fonksiyon, verilen field için görüntüleme handler'ı döndürür.

Parametreler

- **field**: İlişki field'ı

Kullanım Örneği

display := fields.NewRelationshipDisplay(field)

Döndürür:

  • Yapılandırılmış RelationshipDisplayImpl pointer'ı

func (*RelationshipDisplayImpl) FormatDisplayValue

func (rd *RelationshipDisplayImpl) FormatDisplayValue(value interface{}) string

FormatDisplayValue formats a display value

func (*RelationshipDisplayImpl) GetDisplayValue

func (rd *RelationshipDisplayImpl) GetDisplayValue(item interface{}) (string, error)

GetDisplayValue returns the display value for a relationship

func (*RelationshipDisplayImpl) GetDisplayValues

func (rd *RelationshipDisplayImpl) GetDisplayValues(items []interface{}) ([]string, error)

GetDisplayValues returns display values for multiple items

type RelationshipError

type RelationshipError struct {
	FieldName        string
	RelationshipType string
	Message          string
	Context          map[string]interface{}
}

RelationshipError, ilişki işlemleri sırasında oluşan bir hatayı temsil eder.

Bu hata tipi, ilişki işlemlerinde oluşan hataları daha iyi anlamak ve debug etmek için ek bağlam bilgisi sağlar.

Özellikler

- **FieldName**: Hatanın oluştuğu alan adı - **RelationshipType**: İlişki türü (belongsTo, hasMany, vb.) - **Message**: Hata mesajı - **Context**: Ek bağlam bilgisi (map formatında)

Kullanım Örneği

err := &RelationshipError{
    FieldName: "author",
    RelationshipType: "belongsTo",
    Message: "related resource not found",
    Context: map[string]interface{}{
        "author_id": 123,
        "resource": "authors",
    },
}

func (*RelationshipError) Error

func (e *RelationshipError) Error() string

Error, error interface'ini implement eder. Formatlanmış hata mesajı döndürür.

Döndürür:

  • Formatlanmış hata mesajı (alan adı, ilişki türü ve mesaj içerir)

type RelationshipExistence

type RelationshipExistence interface {
	// Exists, ilişkili kaynakların var olup olmadığını kontrol eder.
	//
	// # Parametreler
	//
	// - `ctx`: Context nesnesi (timeout, cancellation için)
	//
	// # Dönüş Değerleri
	//
	// - `bool`: İlişkili kaynak varsa `true`, yoksa `false`
	// - `error`: Kontrol sırasında oluşan hata, başarılıysa `nil`
	//
	// # Davranış
	//
	// İlişki tipine göre uygun EXISTS sorgusu çalıştırılır:
	// - `belongsTo`: Foreign key üzerinden parent kaynak kontrolü
	// - `hasMany`: Child kayıtların varlık kontrolü
	// - `hasOne`: Child kaydın varlık kontrolü
	// - `belongsToMany`: Pivot tablo üzerinden ilişki kontrolü
	// - `morphTo`: Polimorfik ilişki kontrolü
	Exists(ctx context.Context) (bool, error)

	// DoesntExist, hiç ilişkili kaynak bulunmadığını kontrol eder.
	//
	// # Parametreler
	//
	// - `ctx`: Context nesnesi (timeout, cancellation için)
	//
	// # Dönüş Değerleri
	//
	// - `bool`: Hiç ilişkili kaynak yoksa `true`, varsa `false`
	// - `error`: Kontrol sırasında oluşan hata, başarılıysa `nil`
	//
	// # Not
	//
	// Bu method, `Exists` metodunun tersini döndürür.
	DoesntExist(ctx context.Context) (bool, error)
}

RelationshipExistence, ilişkili kaynakların varlık kontrolü için interface tanımlar.

Bu interface, relationship field'ların ilişkili kaynaklarının var olup olmadığını veya hiç ilişkili kaynak bulunmadığını kontrol etmek için kullanılır.

Metodlar

- `Exists`: İlişkili kaynakların var olup olmadığını kontrol eder - `DoesntExist`: Hiç ilişkili kaynak bulunmadığını kontrol eder

Kullanım Örneği

```go existence := NewRelationshipExistence(relationshipField)

// İlişkili kaynak var mı? exists, err := existence.Exists(ctx)

if err != nil {
    return err
}
if exists {
    fmt.Println("İlişkili kaynak bulundu")
}

// Hiç ilişkili kaynak yok mu? doesntExist, err := existence.DoesntExist(ctx)

if err != nil {
    return err
}
if doesntExist {
    fmt.Println("Hiç ilişkili kaynak yok")
}

```

Referans

Detaylı bilgi için bkz: `docs/Relationships.md`

type RelationshipExistenceImpl

type RelationshipExistenceImpl struct {
	// contains filtered or unexported fields
}

RelationshipExistenceImpl, RelationshipExistence interface'ini implement eder.

Bu struct, relationship field'ların ilişkili kaynaklarının varlık kontrolü işlemlerini gerçekleştirir. İlişki tipine göre uygun EXISTS sorgusu stratejisini otomatik olarak seçer ve uygular.

Alanlar

- `field`: Varlık kontrolü yapılacak relationship field

Kullanım Örneği

```go // Relationship field oluştur belongsToField := fields.NewBelongsTo("author", "Author")

// Varlık kontrolcüsü oluştur existence := fields.NewRelationshipExistence(belongsToField)

// Varlık kontrolü yap exists, err := existence.Exists(context.Background())

if err != nil {
    log.Fatal(err)
}
if exists {
    fmt.Println("İlişkili kaynak mevcut")
}

```

Desteklenen İlişki Tipleri

- `belongsTo`: Parent kaynak varlık kontrolü - `hasMany`: Child kayıtlar varlık kontrolü - `hasOne`: Child kayıt varlık kontrolü - `belongsToMany`: Pivot tablo varlık kontrolü - `morphTo`: Polimorfik ilişki varlık kontrolü

Referans

Detaylı bilgi için bkz: `docs/Relationships.md`

func NewRelationshipExistence

func NewRelationshipExistence(field RelationshipField) *RelationshipExistenceImpl

NewRelationshipExistence, yeni bir relationship varlık kontrolcüsü oluşturur.

Bu constructor, verilen relationship field için varlık kontrolü yapabilen bir handler oluşturur. Handler, ilişki tipine göre otomatik olarak uygun EXISTS sorgu stratejisini seçer.

Parametreler

- `field`: Varlık kontrolü yapılacak relationship field (RelationshipField interface'ini implement etmeli)

Dönüş Değerleri

- `*RelationshipExistenceImpl`: Yapılandırılmış varlık kontrolcüsü pointer'ı

Kullanım Örneği

```go // BelongsTo ilişkisi için authorField := fields.NewBelongsTo("author", "Author") existence := fields.NewRelationshipExistence(authorField)

// HasMany ilişkisi için commentsField := fields.NewHasMany("comments", "Comment") existence := fields.NewRelationshipExistence(commentsField)

// BelongsToMany ilişkisi için tagsField := fields.NewBelongsToMany("tags", "Tag") existence := fields.NewRelationshipExistence(tagsField) ```

Notlar

- Field parametresi nil olmamalıdır - Field, RelationshipField interface'ini implement etmelidir - Döndürülen handler thread-safe değildir, concurrent kullanım için senkronizasyon gerekir

Referans

Detaylı bilgi için bkz: `docs/Relationships.md`

func (*RelationshipExistenceImpl) DoesntExist

func (re *RelationshipExistenceImpl) DoesntExist(ctx context.Context) (bool, error)

DoesntExist, hiç ilişkili kaynak bulunmadığını kontrol eder.

Bu method, `Exists` metodunun tersini döndürür. İlişkili hiç kaynak yoksa `true`, en az bir ilişkili kaynak varsa `false` döner.

Parametreler

- `ctx`: Context nesnesi (timeout, cancellation için)

Dönüş Değerleri

- `bool`: Hiç ilişkili kaynak yoksa `true`, varsa `false` - `error`: Kontrol sırasında oluşan hata, başarılıysa `nil`

Davranış

Bu method dahili olarak `Exists` metodunu çağırır ve sonucunu tersine çevirir: - `Exists` true dönerse -> `DoesntExist` false döner - `Exists` false dönerse -> `DoesntExist` true döner - `Exists` hata dönerse -> `DoesntExist` de aynı hatayı döner

Kullanım Örneği

```go // BelongsTo ilişkisi için authorField := fields.NewBelongsTo("author", "Author") existence := fields.NewRelationshipExistence(authorField)

noAuthor, err := existence.DoesntExist(context.Background())

if err != nil {
    return fmt.Errorf("varlık kontrolü başarısız: %w", err)
}
if noAuthor {
    fmt.Println("Yazar atanmamış")
} else {
    fmt.Println("Yazar mevcut")
}

// HasMany ilişkisi için - yorum kontrolü commentsField := fields.NewHasMany("comments", "Comment") existence := fields.NewRelationshipExistence(commentsField)

noComments, err := existence.DoesntExist(ctx)

if err != nil {
    return err
}
if noComments {
    fmt.Println("Henüz yorum yapılmamış")
}

// Validation senaryosu

if noComments {
    return errors.New("en az bir yorum gerekli")
}

```

Notlar

- Context timeout veya cancellation durumunda hata döner - `Exists` metodunun tüm davranışları geçerlidir - Database bağlantı hataları error olarak döner - Bu method thread-safe değildir - Validation ve conditional logic için idealdir

Referans

Detaylı bilgi için bkz: `docs/Relationships.md`

func (*RelationshipExistenceImpl) Exists

func (re *RelationshipExistenceImpl) Exists(ctx context.Context) (bool, error)

Exists, ilişkili kaynakların var olup olmadığını kontrol eder.

Bu method, relationship field'ın tipine göre otomatik olarak uygun EXISTS sorgu stratejisini seçer ve çalıştırır. Her ilişki tipi için özel kontrol mantığı uygulanır.

Parametreler

- `ctx`: Context nesnesi (timeout, cancellation için)

Dönüş Değerleri

- `bool`: İlişkili kaynak varsa `true`, yoksa `false` - `error`: Kontrol sırasında oluşan hata, başarılıysa `nil`

İlişki Tiplerine Göre Davranış

- `belongsTo`: Foreign key üzerinden parent kaynak varlığını kontrol eder - `hasMany`: Child kayıtların varlığını kontrol eder (COUNT > 0) - `hasOne`: Child kaydın varlığını kontrol eder - `belongsToMany`: Pivot tablo üzerinden ilişki varlığını kontrol eder - `morphTo`: Polimorfik ilişki varlığını kontrol eder (type ve id üzerinden)

Kullanım Örneği

```go // BelongsTo ilişkisi için authorField := fields.NewBelongsTo("author", "Author") existence := fields.NewRelationshipExistence(authorField)

exists, err := existence.Exists(context.Background())

if err != nil {
    return fmt.Errorf("varlık kontrolü başarısız: %w", err)
}
if exists {
    fmt.Println("Yazar kaydı mevcut")
} else {
    fmt.Println("Yazar kaydı bulunamadı")
}

// HasMany ilişkisi için commentsField := fields.NewHasMany("comments", "Comment") existence := fields.NewRelationshipExistence(commentsField)

hasComments, err := existence.Exists(ctx)

if err != nil {
    return err
}
if hasComments {
    fmt.Println("En az bir yorum var")
}

```

Notlar

- Context timeout veya cancellation durumunda hata döner - Bilinmeyen ilişki tipleri için `false, nil` döner - Database bağlantı hataları error olarak döner - Bu method thread-safe değildir

Referans

Detaylı bilgi için bkz: `docs/Relationships.md`

type RelationshipField

type RelationshipField interface {
	Element

	// GetRelationshipType, ilişki türünü döndürür.
	// Döndürür: "belongsTo", "hasMany", "hasOne", "belongsToMany", "morphTo"
	GetRelationshipType() string

	// GetRelatedResourceSlug, ilgili resource'un slug'ını döndürür.
	// Döndürür: İlgili resource'un benzersiz tanımlayıcısı (slug)
	GetRelatedResourceSlug() string

	// GetRelationshipName, ilişkinin adını döndürür.
	// Döndürür: İlişkinin adı (örn. "author", "posts", "roles")
	GetRelationshipName() string

	// ResolveRelationship, verilen item için ilişkili verileri çözümler.
	// Parametreler:
	//   - item: İlişkili verileri çözümlenecek kaynak
	// Döndürür:
	//   - İlişkili veriler (tek kayıt veya kayıt listesi)
	//   - Hata (çözümleme başarısız olursa)
	ResolveRelationship(item interface{}) (interface{}, error)

	// GetQueryCallback, sorgu özelleştirme callback'ini döndürür.
	// Döndürür: Sorguyu özelleştiren callback fonksiyonu
	GetQueryCallback() func(interface{}) interface{}

	// GetLoadingStrategy, yükleme stratejisini döndürür.
	// Döndürür: EAGER_LOADING veya LAZY_LOADING
	GetLoadingStrategy() LoadingStrategy

	// ValidateRelationship, ilişki değerini doğrular.
	// Parametreler:
	//   - value: Doğrulanacak değer
	// Döndürür:
	//   - Hata (doğrulama başarısız olursa)
	ValidateRelationship(value interface{}) error

	// GetDisplayKey, BelongsTo için görüntülenecek key'i döndürür.
	// Döndürür: Görüntüleme için kullanılacak alan adı (örn. "name", "title")
	GetDisplayKey() string

	// GetSearchableColumns, BelongsTo için aranabilir sütunları döndürür.
	// Döndürür: Aranabilir sütun adlarının listesi
	GetSearchableColumns() []string

	// IsRequired, ilişkinin zorunlu olup olmadığını döndürür.
	// Döndürür: true ise ilişki zorunludur
	IsRequired() bool

	// GetTypes, MorphTo için kullanılabilir tipleri döndürür.
	// Döndürür: Tip adı -> resource slug eşlemesi
	GetTypes() map[string]string
}

RelationshipField, alan sisteminde bir veritabanı ilişkisini temsil eder.

Bu interface, tüm ilişki türleri (BelongsTo, HasMany, HasOne, BelongsToMany, MorphTo) için ortak metodları tanımlar.

Temel Özellikler

- **Tip Bilgisi**: İlişki türünü ve ilgili resource'u belirtir - **Çözümleme**: İlişkili verileri yükler ve çözümler - **Sorgu Özelleştirme**: İlişki sorgularını özelleştirme callback'leri - **Yükleme Stratejisi**: Eager veya lazy loading seçimi - **Doğrulama**: İlişki verilerini doğrulama - **Görüntüleme**: İlişkili verilerin nasıl gösterileceğini kontrol eder

Kullanım

RelationshipField interface'i doğrudan kullanılmaz, bunun yerine BelongsTo, HasMany, HasOne, BelongsToMany, MorphTo gibi somut tipler kullanılır.

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func IsRelationshipField

func IsRelationshipField(e Element) (RelationshipField, bool)

IsRelationshipField checks if an element is a relationship field

Bu fonksiyon, bir element'in relationship field olup olmadığını kontrol eder. core.Element interface'i RelationshipField interface'ini embed etmediği için, direkt type assertion yerine view field'ına bakarak kontrol yaparız.

Relationship field view'ları: - "has-many-field": HasMany ilişkisi - "belongs-to-field": BelongsTo ilişkisi - "has-one-field": HasOne ilişkisi - "morph-to-field": MorphTo ilişkisi - "morph-to-many-field": MorphToMany ilişkisi - "belongs-to-many-field": BelongsToMany ilişkisi

type RelationshipFilter

type RelationshipFilter interface {
	// ApplyFilter, ilişki sorgusuna bir filtre uygular
	ApplyFilter(ctx context.Context, column string, operator string, value interface{}) ([]interface{}, error)

	// ApplyMultipleFilters, birden fazla filtre uygular
	ApplyMultipleFilters(ctx context.Context, filters map[string]interface{}) ([]interface{}, error)

	// RemoveFilter, filtreyi kaldırır ve tüm ilişkili kaynakları yükler
	RemoveFilter(ctx context.Context) ([]interface{}, error)
}

RelationshipFilter, ilişkiler için filtreleme işlevselliğini yönetir.

Bu interface, ilişkili kayıtları filtrelemek için metodlar sağlar. Tek veya çoklu filtreler uygulanabilir.

Kullanım Örneği

filter := fields.NewRelationshipFilter(field)
results, err := filter.ApplyFilter(ctx, "status", "=", "active")

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

type RelationshipFilterImpl

type RelationshipFilterImpl struct {
	// contains filtered or unexported fields
}

RelationshipFilterImpl, RelationshipFilter interface'ini implement eder.

Bu yapı, ilişki filtreleme işlemlerini gerçekleştirir. Filtreler saklanır ve sorguya uygulanır.

func NewRelationshipFilter

func NewRelationshipFilter(field RelationshipField) *RelationshipFilterImpl

NewRelationshipFilter, yeni bir relationship filter handler oluşturur.

Bu fonksiyon, verilen field için filtreleme handler'ı döndürür.

Parametreler

- **field**: İlişki field'ı

Kullanım Örneği

filter := fields.NewRelationshipFilter(field)

Döndürür:

  • Yapılandırılmış RelationshipFilterImpl pointer'ı

func (*RelationshipFilterImpl) ApplyFilter

func (rf *RelationshipFilterImpl) ApplyFilter(ctx context.Context, column string, operator string, value interface{}) ([]interface{}, error)

ApplyFilter applies a filter to the relationship query

func (*RelationshipFilterImpl) ApplyMultipleFilters

func (rf *RelationshipFilterImpl) ApplyMultipleFilters(ctx context.Context, filters map[string]interface{}) ([]interface{}, error)

ApplyMultipleFilters applies multiple filters

func (*RelationshipFilterImpl) GetFilters

func (rf *RelationshipFilterImpl) GetFilters() map[string]interface{}

GetFilters returns the current filters

func (*RelationshipFilterImpl) RemoveFilter

func (rf *RelationshipFilterImpl) RemoveFilter(ctx context.Context) ([]interface{}, error)

RemoveFilter removes a filter and loads all related resources

type RelationshipGormConfig

type RelationshipGormConfig struct {
	// Foreign Key Yapılandırması (BelongsTo, HasOne, HasMany)
	ForeignKey     string `json:"-"` // Foreign key sütun adı (örn: "author_id")
	References     string `json:"-"` // Referans sütun (örn: "id")
	OnDelete       string `json:"-"` // ON DELETE davranışı: CASCADE, SET NULL, RESTRICT, NO ACTION
	OnUpdate       string `json:"-"` // ON UPDATE davranışı
	ConstraintName string `json:"-"` // Özel constraint adı

	// Many-to-Many Yapılandırması (BelongsToMany)
	PivotTable     string `json:"-"` // Ara tablo adı (örn: "user_roles")
	JoinForeignKey string `json:"-"` // Join tablosundaki ana model FK (örn: "user_id")
	JoinReferences string `json:"-"` // Join tablosundaki referans FK (örn: "role_id")
	JoinTable      string `json:"-"` // GORM joinTable alias

	// Polymorphic Yapılandırması (MorphTo, MorphOne, MorphMany, MorphToMany)
	Polymorphic      bool   `json:"-"` // Polymorphic ilişki mi?
	PolymorphicType  string `json:"-"` // Type sütun adı (örn: "commentable_type")
	PolymorphicID    string `json:"-"` // ID sütun adı (örn: "commentable_id")
	PolymorphicValue string `json:"-"` // Type değeri (örn: "posts", "users")

	// Eager Loading
	Preload bool `json:"-"` // Otomatik preload yapılsın mı?
}

RelationshipGormConfig, ilişki field'ları için GORM yapılandırmasını tanımlar. Bu yapı, foreign key, pivot tablo ve polymorphic ilişkiler için kullanılır.

func NewRelationshipGormConfig

func NewRelationshipGormConfig() *RelationshipGormConfig

NewRelationshipGormConfig, varsayılan değerlerle yeni bir RelationshipGormConfig oluşturur.

func (*RelationshipGormConfig) ToForeignKeyTag

func (r *RelationshipGormConfig) ToForeignKeyTag() string

ToForeignKeyTag, foreign key sütunu için GORM tag oluşturur. BelongsTo ilişkilerinde kullanılır (örn: author_id uint `gorm:"index"`).

func (*RelationshipGormConfig) ToGormTag

func (r *RelationshipGormConfig) ToGormTag() string

ToGormTag, ilişki için GORM struct tag'ini oluşturur. Bu metod, model alanları için gorm tag'leri üretir.

func (*RelationshipGormConfig) WithConstraintName

func (r *RelationshipGormConfig) WithConstraintName(name string) *RelationshipGormConfig

WithConstraintName, özel constraint adı belirler.

func (*RelationshipGormConfig) WithForeignKey

func (r *RelationshipGormConfig) WithForeignKey(fk string) *RelationshipGormConfig

WithForeignKey, foreign key sütununu belirler.

func (*RelationshipGormConfig) WithOnDelete

func (r *RelationshipGormConfig) WithOnDelete(action string) *RelationshipGormConfig

WithOnDelete, ON DELETE davranışını belirler.

func (*RelationshipGormConfig) WithOnUpdate

func (r *RelationshipGormConfig) WithOnUpdate(action string) *RelationshipGormConfig

WithOnUpdate, ON UPDATE davranışını belirler.

func (*RelationshipGormConfig) WithPivotTable

func (r *RelationshipGormConfig) WithPivotTable(table, joinFK, joinRef string) *RelationshipGormConfig

WithPivotTable, many-to-many için ara tablo belirler.

func (*RelationshipGormConfig) WithPolymorphic

func (r *RelationshipGormConfig) WithPolymorphic(typeColumn, idColumn string) *RelationshipGormConfig

WithPolymorphic, polymorphic ilişki yapılandırır.

func (*RelationshipGormConfig) WithPolymorphicValue

func (r *RelationshipGormConfig) WithPolymorphicValue(value string) *RelationshipGormConfig

WithPolymorphicValue, polymorphic type değerini belirler.

func (*RelationshipGormConfig) WithPreload

func (r *RelationshipGormConfig) WithPreload(enabled bool) *RelationshipGormConfig

WithPreload, eager loading'i etkinleştirir/devre dışı bırakır.

func (*RelationshipGormConfig) WithReferences

func (r *RelationshipGormConfig) WithReferences(ref string) *RelationshipGormConfig

WithReferences, referans sütununu belirler.

type RelationshipLoader

type RelationshipLoader interface {
	// Load related data using eager loading strategy
	EagerLoad(ctx context.Context, items []interface{}, field RelationshipField) error

	// Load related data using lazy loading strategy
	LazyLoad(ctx context.Context, item interface{}, field RelationshipField) (interface{}, error)

	// Load with constraints applied
	LoadWithConstraints(ctx context.Context, item interface{}, field RelationshipField, constraints map[string]interface{}) (interface{}, error)
}

RelationshipLoader handles loading relationships with different strategies

type RelationshipLoaderImpl

type RelationshipLoaderImpl struct {
}

RelationshipLoaderImpl, RelationshipLoader interface'ini implement eder.

Bu yapı, ilişki yükleme işlemlerini gerçekleştirir. Eager loading ve lazy loading stratejilerini destekler.

Kullanım Örneği

loader := fields.NewRelationshipLoader()
err := loader.EagerLoad(ctx, items, field)

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func NewRelationshipLoader

func NewRelationshipLoader() *RelationshipLoaderImpl

NewRelationshipLoader, yeni bir relationship loader oluşturur.

Bu fonksiyon, ilişki yükleme işlemleri için loader döndürür.

Kullanım Örneği

loader := fields.NewRelationshipLoader()

Döndürür:

  • Yapılandırılmış RelationshipLoaderImpl pointer'ı

func (*RelationshipLoaderImpl) EagerLoad

func (rl *RelationshipLoaderImpl) EagerLoad(ctx context.Context, items []interface{}, field RelationshipField) error

EagerLoad, eager loading stratejisi kullanarak ilişkili verileri yükler.

Bu metod, tüm ilişkili verileri tek bir sorguda yükler. N+1 sorgu problemini önlemek için kullanılır.

Parametreler

- **ctx**: Context - **items**: Yüklenecek öğeler - **field**: İlişki field'ı

Kullanım Örneği

err := loader.EagerLoad(ctx, items, field)

Döndürür:

  • Hata (yükleme başarısız olursa)

func (*RelationshipLoaderImpl) LazyLoad

func (rl *RelationshipLoaderImpl) LazyLoad(ctx context.Context, item interface{}, field RelationshipField) (interface{}, error)

LazyLoad loads related data using lazy loading strategy This loads related data on demand

func (*RelationshipLoaderImpl) LoadWithConstraints

func (rl *RelationshipLoaderImpl) LoadWithConstraints(ctx context.Context, item interface{}, field RelationshipField, constraints map[string]interface{}) (interface{}, error)

LoadWithConstraints loads related data with constraints applied

type RelationshipPagination

type RelationshipPagination interface {
	// ApplyPagination, ilişki sorgusuna sayfalama uygular.
	//
	// # Parametreler
	//
	//   - ctx: Context nesnesi
	//   - page: Sayfa numarası (minimum 1, geçersiz değerler 1'e ayarlanır)
	//   - perPage: Sayfa başına kayıt sayısı (minimum 1, maksimum 100)
	//
	// # Dönüş Değerleri
	//
	//   - []interface{}: Sayfalanmış kayıt listesi
	//   - error: Hata durumunda hata nesnesi
	//
	// # Önemli Notlar
	//
	//   - Sayfa numarası 1'den küçükse otomatik olarak 1'e ayarlanır
	//   - Sayfa boyutu 1'den küçükse otomatik olarak 15'e ayarlanır
	//   - Sayfa boyutu 100'den büyükse otomatik olarak 100'e sınırlanır
	ApplyPagination(ctx context.Context, page int, perPage int) ([]interface{}, error)

	// GetPageInfo, sayfalama metadata'sını döndürür.
	//
	// # Dönüş Değeri
	//
	// Map içeriği:
	//   - current_page: Mevcut sayfa numarası
	//   - per_page: Sayfa başına kayıt sayısı
	//   - total: Toplam kayıt sayısı
	//   - total_pages: Toplam sayfa sayısı
	//   - from: Başlangıç kayıt indeksi
	//   - to: Bitiş kayıt indeksi
	//
	// # Kullanım Örneği
	//
	//	info := pagination.GetPageInfo()
	//	currentPage := info["current_page"].(int)
	//	totalPages := info["total_pages"].(int64)
	GetPageInfo() map[string]interface{}
}

RelationshipPagination, ilişkiler için sayfalama işlevselliğini yönetir.

Bu interface, ilişkili kayıtları sayfalamak için metodlar sağlar. Sayfa numarası ve sayfa boyutu belirlenebilir, sayfalama metadata'sı alınabilir.

Kullanım Örneği

pagination := fields.NewRelationshipPagination(field)
results, err := pagination.ApplyPagination(ctx, 1, 15)
if err != nil {
    log.Fatal(err)
}
pageInfo := pagination.GetPageInfo()

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

type RelationshipPaginationImpl

type RelationshipPaginationImpl struct {
	// contains filtered or unexported fields
}

RelationshipPaginationImpl, RelationshipPagination interface'ini uygular.

Bu struct, ilişki sayfalama işlemlerinin somut implementasyonunu sağlar. Sayfa numarası, sayfa boyutu ve toplam kayıt sayısı bilgilerini tutar.

Alanlar

  • field: İlişki alanı referansı
  • page: Mevcut sayfa numarası (varsayılan: 1)
  • perPage: Sayfa başına kayıt sayısı (varsayılan: 15)
  • total: Toplam kayıt sayısı (varsayılan: 0)

Kullanım Örneği

impl := &RelationshipPaginationImpl{
    field:   myField,
    page:    1,
    perPage: 20,
    total:   100,
}

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func NewRelationshipPagination

func NewRelationshipPagination(field RelationshipField) *RelationshipPaginationImpl

NewRelationshipPagination, yeni bir ilişki sayfalama yöneticisi oluşturur.

Bu constructor, varsayılan değerlerle yapılandırılmış bir sayfalama nesnesi döndürür. Sayfa numarası 1, sayfa boyutu 15 ve toplam kayıt sayısı 0 olarak başlatılır.

Parametreler

  • field: İlişki alanı (RelationshipField interface'ini uygulayan nesne)

Dönüş Değeri

  • *RelationshipPaginationImpl: Yapılandırılmış sayfalama nesnesi pointer'ı

Kullanım Örneği

field := fields.NewBelongsTo("user", "User")
pagination := fields.NewRelationshipPagination(field)
// pagination.page = 1, pagination.perPage = 15, pagination.total = 0

Varsayılan Değerler

  • Sayfa numarası: 1
  • Sayfa boyutu: 15
  • Toplam kayıt: 0

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func (*RelationshipPaginationImpl) ApplyPagination

func (rp *RelationshipPaginationImpl) ApplyPagination(ctx context.Context, page int, perPage int) ([]interface{}, error)

ApplyPagination, ilişki sorgusuna sayfalama uygular.

Bu metod, sayfa numarası ve sayfa boyutunu doğrular, geçersiz değerleri düzeltir ve sayfalama parametrelerini ayarlar. Sayfa boyutu maksimum 100 ile sınırlandırılır.

Parametreler

  • ctx: Context nesnesi (iptal ve timeout yönetimi için)
  • page: Sayfa numarası (minimum 1, geçersiz değerler 1'e ayarlanır)
  • perPage: Sayfa başına kayıt sayısı (minimum 1, maksimum 100)

Dönüş Değerleri

  • []interface{}: Sayfalanmış kayıt listesi
  • error: Hata durumunda hata nesnesi, başarılı ise nil

Doğrulama Kuralları

  • page < 1 ise otomatik olarak 1'e ayarlanır
  • perPage < 1 ise otomatik olarak 15'e ayarlanır
  • perPage > 100 ise otomatik olarak 100'e sınırlanır

Kullanım Örneği

pagination := fields.NewRelationshipPagination(field)
results, err := pagination.ApplyPagination(ctx, 2, 20)
if err != nil {
    log.Fatal(err)
}
// results içinde 2. sayfanın 20 kaydı bulunur

Önemli Notlar

  • Şu anki implementasyon boş slice döndürür (placeholder)
  • Gerçek implementasyonda LIMIT ve OFFSET ile veritabanı sorgusu yapılır
  • Sayfa boyutu güvenlik nedeniyle 100 ile sınırlandırılmıştır

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func (*RelationshipPaginationImpl) GetPage

func (rp *RelationshipPaginationImpl) GetPage() int

GetPage, mevcut sayfa numarasını döndürür.

Bu metod, ApplyPagination() ile ayarlanan veya varsayılan sayfa numarasını döndürür.

Dönüş Değeri

  • int: Mevcut sayfa numarası (minimum 1)

Kullanım Örneği

pagination := fields.NewRelationshipPagination(field)
fmt.Println(pagination.GetPage()) // Çıktı: 1 (varsayılan)

pagination.ApplyPagination(ctx, 3, 15)
fmt.Println(pagination.GetPage()) // Çıktı: 3

Önemli Notlar

  • Varsayılan değer 1'dir (NewRelationshipPagination ile oluşturulduğunda)
  • ApplyPagination() çağrıldıktan sonra güncellenir

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func (*RelationshipPaginationImpl) GetPageInfo

func (rp *RelationshipPaginationImpl) GetPageInfo() map[string]interface{}

GetPageInfo, sayfalama metadata'sını döndürür.

Bu metod, mevcut sayfalama durumu hakkında detaylı bilgi içeren bir map döndürür. Toplam sayfa sayısı, mevcut sayfa, kayıt aralıkları gibi bilgiler içerir.

Dönüş Değeri

Map içeriği:

  • current_page (int): Mevcut sayfa numarası
  • per_page (int): Sayfa başına kayıt sayısı
  • total (int64): Toplam kayıt sayısı
  • total_pages (int64): Toplam sayfa sayısı
  • from (int): Başlangıç kayıt indeksi (0-based)
  • to (int): Bitiş kayıt indeksi (0-based)

Kullanım Örneği

pagination := fields.NewRelationshipPagination(field)
pagination.SetTotal(100)
pagination.ApplyPagination(ctx, 2, 15)

info := pagination.GetPageInfo()
fmt.Printf("Sayfa %d/%d\n", info["current_page"], info["total_pages"])
fmt.Printf("Kayıt %d-%d / %d\n", info["from"], info["to"], info["total"])
// Çıktı: Sayfa 2/7
// Çıktı: Kayıt 15-30 / 100

Hesaplama Detayları

  • total_pages = ceil(total / perPage)
  • from = (current_page - 1) * perPage
  • to = current_page * perPage

Önemli Notlar

  • perPage 0 ise total_pages 0 olarak döner (sıfıra bölme hatası önlenir)
  • from ve to değerleri 0-based indeks kullanır
  • SetTotal() ile toplam kayıt sayısı ayarlanmalıdır

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func (*RelationshipPaginationImpl) GetPerPage

func (rp *RelationshipPaginationImpl) GetPerPage() int

GetPerPage, sayfa başına kayıt sayısını döndürür.

Bu metod, ApplyPagination() ile ayarlanan veya varsayılan sayfa boyutunu döndürür.

Dönüş Değeri

  • int: Sayfa başına kayıt sayısı (minimum 1, maksimum 100)

Kullanım Örneği

pagination := fields.NewRelationshipPagination(field)
fmt.Println(pagination.GetPerPage()) // Çıktı: 15 (varsayılan)

pagination.ApplyPagination(ctx, 1, 25)
fmt.Println(pagination.GetPerPage()) // Çıktı: 25

pagination.ApplyPagination(ctx, 1, 150)
fmt.Println(pagination.GetPerPage()) // Çıktı: 100 (maksimum sınır)

Önemli Notlar

  • Varsayılan değer 15'tir (NewRelationshipPagination ile oluşturulduğunda)
  • ApplyPagination() çağrıldıktan sonra güncellenir
  • Değer otomatik olarak 1-100 aralığında sınırlandırılır

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func (*RelationshipPaginationImpl) GetTotal

func (rp *RelationshipPaginationImpl) GetTotal() int64

GetTotal, toplam kayıt sayısını döndürür.

Bu metod, SetTotal() ile ayarlanan toplam kayıt sayısını döndürür. Sayfalama metadata hesaplamaları için kullanılır.

Dönüş Değeri

  • int64: Toplam kayıt sayısı

Kullanım Örneği

pagination := fields.NewRelationshipPagination(field)
fmt.Println(pagination.GetTotal()) // Çıktı: 0 (varsayılan)

pagination.SetTotal(250)
fmt.Println(pagination.GetTotal()) // Çıktı: 250

// Toplam sayfa sayısını hesapla
totalPages := (pagination.GetTotal() + int64(pagination.GetPerPage()) - 1) / int64(pagination.GetPerPage())
fmt.Println(totalPages) // Çıktı: 17 (ceil(250/15))

Önemli Notlar

  • Varsayılan değer 0'dır (NewRelationshipPagination ile oluşturulduğunda)
  • SetTotal() ile güncellenir
  • GetPageInfo() bu değeri kullanarak total_pages hesaplar

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func (*RelationshipPaginationImpl) SetTotal

func (rp *RelationshipPaginationImpl) SetTotal(total int64)

SetTotal, toplam kayıt sayısını ayarlar.

Bu metod, sayfalama hesaplamaları için gerekli olan toplam kayıt sayısını belirler. GetPageInfo() metodunun doğru sonuçlar döndürebilmesi için bu metod çağrılmalıdır.

Parametreler

  • total: Toplam kayıt sayısı (int64)

Kullanım Örneği

pagination := fields.NewRelationshipPagination(field)
pagination.SetTotal(150) // 150 kayıt var
pagination.ApplyPagination(ctx, 1, 20)

info := pagination.GetPageInfo()
// info["total"] = 150
// info["total_pages"] = 8 (ceil(150/20))

Önemli Notlar

  • Bu metod ApplyPagination() çağrılmadan önce veya sonra çağrılabilir
  • Toplam kayıt sayısı genellikle veritabanı COUNT sorgusu ile elde edilir
  • Negatif değerler kabul edilir ancak mantıksal olarak 0 veya pozitif olmalıdır

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

type RelationshipQuery

type RelationshipQuery interface {
	// Apply WHERE clause
	Where(column string, operator string, value interface{}) RelationshipQuery

	// Apply WHERE IN clause
	WhereIn(column string, values []interface{}) RelationshipQuery

	// Apply ORDER BY clause
	OrderBy(column string, direction string) RelationshipQuery

	// Apply LIMIT clause
	Limit(limit int) RelationshipQuery

	// Apply OFFSET clause
	Offset(offset int) RelationshipQuery

	// Get count of results
	Count(ctx context.Context) (int64, error)

	// Check if results exist
	Exists(ctx context.Context) (bool, error)

	// Execute query and get results
	Get(ctx context.Context) ([]interface{}, error)

	// Execute query and get first result
	First(ctx context.Context) (interface{}, error)
}

RelationshipQuery represents a query builder for relationships

type RelationshipQueryImpl

type RelationshipQueryImpl struct {
	// contains filtered or unexported fields
}

RelationshipQueryImpl, RelationshipQuery interface'ini implement eder.

Bu yapı, ilişki sorguları için query builder sağlar. WHERE, ORDER BY, LIMIT, OFFSET gibi SQL clause'larını destekler.

Kullanım Örneği

query := fields.NewRelationshipQuery().
    Where("status", "=", "active").
    OrderBy("created_at", "DESC").
    Limit(10)

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

func NewRelationshipQuery

func NewRelationshipQuery() *RelationshipQueryImpl

NewRelationshipQuery, yeni bir relationship query oluşturur.

Bu fonksiyon, ilişki sorguları için boş bir query builder döndürür. Query builder, method chaining ile sorgu oluşturmayı destekler.

Kullanım Örneği

query := fields.NewRelationshipQuery()

Döndürür:

  • Yapılandırılmış RelationshipQueryImpl pointer'ı

func (*RelationshipQueryImpl) Count

func (rq *RelationshipQueryImpl) Count(ctx context.Context) (int64, error)

Count gets count of results

func (*RelationshipQueryImpl) Exists

func (rq *RelationshipQueryImpl) Exists(ctx context.Context) (bool, error)

Exists checks if results exist

func (*RelationshipQueryImpl) First

func (rq *RelationshipQueryImpl) First(ctx context.Context) (interface{}, error)

First executes query and gets first result

func (*RelationshipQueryImpl) Get

func (rq *RelationshipQueryImpl) Get(ctx context.Context) ([]interface{}, error)

Get executes query and gets results

func (*RelationshipQueryImpl) GetLimit

func (rq *RelationshipQueryImpl) GetLimit() int

GetLimit returns the LIMIT value

func (*RelationshipQueryImpl) GetOffset

func (rq *RelationshipQueryImpl) GetOffset() int

GetOffset returns the OFFSET value

func (*RelationshipQueryImpl) GetOrderByColumns

func (rq *RelationshipQueryImpl) GetOrderByColumns() []map[string]interface{}

GetOrderByColumns returns the ORDER BY columns

func (*RelationshipQueryImpl) GetWhereConditions

func (rq *RelationshipQueryImpl) GetWhereConditions() []map[string]interface{}

GetWhereConditions returns the WHERE conditions

func (*RelationshipQueryImpl) Limit

func (rq *RelationshipQueryImpl) Limit(limit int) RelationshipQuery

Limit applies LIMIT clause

func (*RelationshipQueryImpl) Offset

func (rq *RelationshipQueryImpl) Offset(offset int) RelationshipQuery

Offset applies OFFSET clause

func (*RelationshipQueryImpl) OrderBy

func (rq *RelationshipQueryImpl) OrderBy(column string, direction string) RelationshipQuery

OrderBy applies ORDER BY clause

func (*RelationshipQueryImpl) String

func (rq *RelationshipQueryImpl) String() string

String returns a string representation of the query

func (*RelationshipQueryImpl) Where

func (rq *RelationshipQueryImpl) Where(column string, operator string, value interface{}) RelationshipQuery

Where applies WHERE clause

func (*RelationshipQueryImpl) WhereIn

func (rq *RelationshipQueryImpl) WhereIn(column string, values []interface{}) RelationshipQuery

WhereIn applies WHERE IN clause

type RelationshipSearch

type RelationshipSearch interface {
	// Search, terime göre ilişkili kaynakları arar
	Search(ctx context.Context, term string) ([]interface{}, error)

	// SearchInColumns, belirli sütunlarda arama yapar
	SearchInColumns(ctx context.Context, term string, columns []string) ([]interface{}, error)

	// GetSearchableColumns, aranabilir sütunları döndürür
	GetSearchableColumns() []string
}

RelationshipSearch, ilişkiler için arama işlevselliğini yönetir.

Bu interface, ilişkili kayıtlarda arama yapmak için metodlar sağlar. Belirli sütunlarda veya tüm aranabilir sütunlarda arama yapılabilir.

Kullanım Örneği

search := fields.NewRelationshipSearch(field)
results, err := search.Search(ctx, "john")

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

type RelationshipSearchImpl

type RelationshipSearchImpl struct {
	// contains filtered or unexported fields
}

RelationshipSearchImpl, RelationshipSearch interface'ini implement eder.

Bu yapı, ilişki arama işlemlerini gerçekleştirir. Aranabilir sütunlar field'dan alınır.

func NewRelationshipSearch

func NewRelationshipSearch(field RelationshipField) *RelationshipSearchImpl

NewRelationshipSearch, yeni bir relationship search handler oluşturur.

Bu fonksiyon, verilen field için arama handler'ı döndürür.

Parametreler

- **field**: İlişki field'ı

Kullanım Örneği

search := fields.NewRelationshipSearch(field)

Döndürür:

  • Yapılandırılmış RelationshipSearchImpl pointer'ı

func (*RelationshipSearchImpl) CaseInsensitiveSearch

func (rs *RelationshipSearchImpl) CaseInsensitiveSearch(ctx context.Context, term string) ([]interface{}, error)

CaseInsensitiveSearch performs case-insensitive search

func (*RelationshipSearchImpl) GetSearchableColumns

func (rs *RelationshipSearchImpl) GetSearchableColumns() []string

GetSearchableColumns returns the searchable columns

func (*RelationshipSearchImpl) Search

func (rs *RelationshipSearchImpl) Search(ctx context.Context, term string) ([]interface{}, error)

Search searches for related resources by term

func (*RelationshipSearchImpl) SearchInColumns

func (rs *RelationshipSearchImpl) SearchInColumns(ctx context.Context, term string, columns []string) ([]interface{}, error)

SearchInColumns searches in specific columns

type RelationshipSerialization

type RelationshipSerialization interface {
	// SerializeRelationship, tekil bir ilişkiyi JSON formatına dönüştürür.
	//
	// # Parametreler
	//
	// - `item`: Serileştirilecek ilişki verisi (nil olabilir)
	//
	// # Döndürür
	//
	// - `map[string]interface{}`: Serileştirilmiş veri (type, name, resource, value içerir)
	// - `error`: Hata durumunda hata mesajı
	//
	// # Örnek
	//
	// “`go
	// data, err := serializer.SerializeRelationship(user)
	// // Sonuç: {"type": "belongsTo", "name": "author", "resource": "users", "value": {...}}
	// “`
	SerializeRelationship(item interface{}) (map[string]interface{}, error)

	// SerializeRelationships, çoklu ilişkileri JSON formatına dönüştürür.
	//
	// # Parametreler
	//
	// - `items`: Serileştirilecek ilişki verileri dizisi (nil veya boş olabilir)
	//
	// # Döndürür
	//
	// - `[]map[string]interface{}`: Serileştirilmiş veri dizisi
	// - `error`: Hata durumunda hata mesajı
	//
	// # Örnek
	//
	// “`go
	// items, err := serializer.SerializeRelationships(users)
	// // Sonuç: [{"type": "hasMany", "name": "posts", "resource": "posts", "value": {...}}, ...]
	// “`
	SerializeRelationships(items []interface{}) ([]map[string]interface{}, error)
}

RelationshipSerialization, ilişkilerin JSON serileştirme işlemlerini yönetir.

Bu interface, relationship field'larının JSON formatına dönüştürülmesi için gerekli metodları tanımlar. Hem tekil hem de çoklu ilişkilerin serileştirmesini destekler.

Kullanım

```go serializer := NewRelationshipSerialization(relationshipField)

// Tekil ilişki serileştirme data, err := serializer.SerializeRelationship(user)

if err != nil {
    log.Fatal(err)
}

// Çoklu ilişki serileştirme items, err := serializer.SerializeRelationships(users)

if err != nil {
    log.Fatal(err)
}

```

Referans

Detaylı bilgi için: docs/Relationships.md(../../docs/Relationships.md)

type RelationshipSerializationImpl

type RelationshipSerializationImpl struct {
	// contains filtered or unexported fields
}

RelationshipSerializationImpl, RelationshipSerialization interface'ini implement eder.

Bu struct, relationship field'larının JSON serileştirme işlemlerini gerçekleştirir. İlişki tipini, adını ve ilgili resource bilgilerini içeren JSON çıktısı üretir.

Alanlar

- `field`: Serileştirilecek relationship field

Örnek

```go

impl := &RelationshipSerializationImpl{
    field: belongsToField,
}

```

func NewRelationshipSerialization

func NewRelationshipSerialization(field RelationshipField) *RelationshipSerializationImpl

NewRelationshipSerialization, yeni bir relationship serialization handler oluşturur.

Bu constructor, verilen relationship field için bir serileştirme handler'ı başlatır.

Parametreler

- `field`: Serileştirilecek relationship field

Döndürür

- Yapılandırılmış RelationshipSerializationImpl pointer'ı

Örnek

```go belongsTo := fields.NewBelongsTo("author").

SetRelatedResource("users")

serializer := fields.NewRelationshipSerialization(belongsTo)

// Kullanım data, err := serializer.SerializeRelationship(user) ```

Notlar

- Field parametresi nil olmamalıdır - Döndürülen handler tüm serileştirme metodlarını destekler

func (*RelationshipSerializationImpl) SerializeRelationship

func (rs *RelationshipSerializationImpl) SerializeRelationship(item interface{}) (map[string]interface{}, error)

SerializeRelationship, tekil bir ilişkiyi JSON formatına dönüştürür.

Bu method, verilen ilişki verisini JSON-uyumlu bir map yapısına dönüştürür. İlişki tipi, adı, resource bilgisi ve değeri içeren bir yapı oluşturur.

Parametreler

- `item`: Serileştirilecek ilişki verisi (nil olabilir)

Döndürür

- `map[string]interface{}`: Serileştirilmiş veri yapısı

  • `type`: İlişki tipi (belongsTo, hasMany, hasOne, belongsToMany, morphTo)
  • `name`: İlişki adı
  • `resource`: İlgili resource adı
  • `value`: İlişki verisi (nil olabilir)

- `error`: Hata durumunda hata mesajı (şu an için her zaman nil)

Örnek

```go serializer := NewRelationshipSerialization(belongsToField) data, err := serializer.SerializeRelationship(user) // Sonuç: { // "type": "belongsTo", // "name": "author", // "resource": "users", // "value": {...} // } ```

Notlar

- Nil değerler için sadece `value: nil` içeren bir map döner - İlişki metadata'sı field'dan otomatik olarak alınır

func (*RelationshipSerializationImpl) SerializeRelationships

func (rs *RelationshipSerializationImpl) SerializeRelationships(items []interface{}) ([]map[string]interface{}, error)

SerializeRelationships, çoklu ilişkileri JSON formatına dönüştürür.

Bu method, verilen ilişki verileri dizisini JSON-uyumlu map dizisine dönüştürür. Her bir ilişki için SerializeRelationship metodunu çağırır.

Parametreler

- `items`: Serileştirilecek ilişki verileri dizisi (nil veya boş olabilir)

Döndürür

- `[]map[string]interface{}`: Serileştirilmiş veri dizisi (boş dizi olabilir) - `error`: Herhangi bir item'ın serileştirmesinde hata oluşursa hata mesajı

Örnek

```go serializer := NewRelationshipSerialization(hasManyField) items, err := serializer.SerializeRelationships(posts)

if err != nil {
    log.Fatal(err)
}

// Sonuç: [ // {"type": "hasMany", "name": "posts", "resource": "posts", "value": {...}}, // {"type": "hasMany", "name": "posts", "resource": "posts", "value": {...}} // ] ```

Notlar

- Nil veya boş dizi için boş slice döner (nil değil) - Her item için ayrı ayrı SerializeRelationship çağrılır - Herhangi bir item'da hata oluşursa işlem durur ve hata döner

func (*RelationshipSerializationImpl) ToJSON

func (rs *RelationshipSerializationImpl) ToJSON(item interface{}) (string, error)

ToJSON, ilişkiyi JSON string formatına dönüştürür.

Bu method, SerializeRelationship metodunu kullanarak ilişkiyi önce map yapısına, ardından JSON string formatına dönüştürür.

Parametreler

- `item`: JSON'a dönüştürülecek ilişki verisi (nil olabilir)

Döndürür

- `string`: JSON formatında string (örn: `{"type":"belongsTo","name":"author",...}`) - `error`: Serileştirme veya JSON encoding hatası

Örnek

```go serializer := NewRelationshipSerialization(belongsToField) jsonStr, err := serializer.ToJSON(user)

if err != nil {
    log.Fatal(err)
}

fmt.Println(jsonStr) // Çıktı: {"type":"belongsTo","name":"author","resource":"users","value":{...}} ```

Notlar

- İç içe SerializeRelationship ve json.Marshal çağrıları yapar - Her iki aşamada da hata oluşabilir - Nil değerler için `{"value":null}` formatında JSON döner

func (*RelationshipSerializationImpl) ToJSONArray

func (rs *RelationshipSerializationImpl) ToJSONArray(items []interface{}) (string, error)

ToJSONArray, çoklu ilişkileri JSON array string formatına dönüştürür.

Bu method, SerializeRelationships metodunu kullanarak ilişkileri önce map dizisine, ardından JSON array string formatına dönüştürür.

Parametreler

- `items`: JSON array'e dönüştürülecek ilişki verileri dizisi (nil veya boş olabilir)

Döndürür

- `string`: JSON array formatında string (örn: `[{"type":"hasMany",...},{...}]`) - `error`: Serileştirme veya JSON encoding hatası

Örnek

```go serializer := NewRelationshipSerialization(hasManyField) jsonStr, err := serializer.ToJSONArray(posts)

if err != nil {
    log.Fatal(err)
}

fmt.Println(jsonStr) // Çıktı: [{"type":"hasMany","name":"posts","resource":"posts","value":{...}},...] ```

Notlar

- İç içe SerializeRelationships ve json.Marshal çağrıları yapar - Her iki aşamada da hata oluşabilir - Nil veya boş dizi için `[]` formatında JSON döner - HasMany ve BelongsToMany ilişkileri için idealdir

type RelationshipSort

type RelationshipSort interface {
	// ApplySort, ilişki sorgusuna bir sıralama uygular
	ApplySort(ctx context.Context, column string, direction string) ([]interface{}, error)

	// ApplyMultipleSorts, birden fazla sıralama uygular
	ApplyMultipleSorts(ctx context.Context, sorts map[string]string) ([]interface{}, error)

	// RemoveSort, sıralamayı kaldırır ve varsayılan sıralama düzenini kullanır
	RemoveSort(ctx context.Context) ([]interface{}, error)
}

RelationshipSort, ilişkiler için sıralama işlevselliğini yönetir.

Bu interface, ilişkili kayıtları sıralamak için metodlar sağlar. Tek veya çoklu sıralamalar uygulanabilir.

Kullanım Örneği

sort := fields.NewRelationshipSort(field)
results, err := sort.ApplySort(ctx, "created_at", "DESC")

Daha fazla bilgi için docs/Relationships.md dosyasına bakın.

type RelationshipSortImpl

type RelationshipSortImpl struct {
	// contains filtered or unexported fields
}

RelationshipSortImpl, RelationshipSort interface'ini implement eder.

Bu yapı, ilişki sıralama işlemlerini gerçekleştirir. Sıralamalar saklanır ve sorguya uygulanır.

func NewRelationshipSort

func NewRelationshipSort(field RelationshipField) *RelationshipSortImpl

NewRelationshipSort, yeni bir relationship sort handler oluşturur.

Bu fonksiyon, verilen field için sıralama handler'ı döndürür.

Parametreler

- **field**: İlişki field'ı

Kullanım Örneği

sort := fields.NewRelationshipSort(field)

Döndürür:

  • Yapılandırılmış RelationshipSortImpl pointer'ı

func (*RelationshipSortImpl) ApplyMultipleSorts

func (rs *RelationshipSortImpl) ApplyMultipleSorts(ctx context.Context, sorts map[string]string) ([]interface{}, error)

ApplyMultipleSorts applies multiple sorts

func (*RelationshipSortImpl) ApplySort

func (rs *RelationshipSortImpl) ApplySort(ctx context.Context, column string, direction string) ([]interface{}, error)

ApplySort applies a sort to the relationship query

func (*RelationshipSortImpl) GetSorts

func (rs *RelationshipSortImpl) GetSorts() map[string]string

GetSorts returns the current sorts

func (*RelationshipSortImpl) RemoveSort

func (rs *RelationshipSortImpl) RemoveSort(ctx context.Context) ([]interface{}, error)

RemoveSort removes a sort and uses default sort order

type RelationshipValidator

type RelationshipValidator interface {
	// Validate that related resource exists
	ValidateExists(ctx context.Context, value interface{}, field RelationshipField) error

	// Validate foreign key references
	ValidateForeignKey(ctx context.Context, value interface{}, field RelationshipField) error

	// Validate pivot table entries
	ValidatePivot(ctx context.Context, value interface{}, field RelationshipField) error

	// Validate morph type is registered
	ValidateMorphType(ctx context.Context, value interface{}, field RelationshipField) error
}

RelationshipValidator handles validation of relationships

type RelationshipValidatorImpl

type RelationshipValidatorImpl struct {
}

RelationshipValidatorImpl, RelationshipValidator interface'ini implement eden struct'tır.

Bu struct, tüm ilişki tiplerinin doğrulanması için gerekli metodları sağlar. Veritabanı bağlantısı veya query builder bu struct'a eklenerek gerçek doğrulama işlemleri yapılabilir.

Özellikler

- Foreign key doğrulama - Pivot tablo doğrulama - Polimorfik tip doğrulama - İlişkili kaynak varlık kontrolü

Not

Şu anki implementasyon placeholder'dır. Gerçek kullanımda veritabanı bağlantısı eklenmeli ve doğrulama sorguları çalıştırılmalıdır.

func NewRelationshipValidator

func NewRelationshipValidator() *RelationshipValidatorImpl

NewRelationshipValidator, yeni bir ilişki validator'ı oluşturur.

Bu constructor, RelationshipValidatorImpl struct'ının yeni bir instance'ını döndürür. Döndürülen validator, tüm ilişki tiplerinin doğrulanması için kullanılabilir.

Döndürür

- Yapılandırılmış RelationshipValidatorImpl pointer'ı

Örnek

```go validator := fields.NewRelationshipValidator()

// Validator'ı kullanarak ilişkileri doğrula err := validator.ValidateBelongsTo(ctx, userID, belongsToField)

if err != nil {
    // Hata yönetimi
}

```

Not

Şu anki implementasyon placeholder'dır. Gerçek kullanımda veritabanı bağlantısı constructor'a parametre olarak geçilebilir.

func (*RelationshipValidatorImpl) ValidateBelongsTo

func (rv *RelationshipValidatorImpl) ValidateBelongsTo(ctx context.Context, value interface{}, field *BelongsToField) error

ValidateBelongsTo, BelongsTo ilişkilerini doğrular.

Bu metod, bir kaydın başka bir kayda ait olduğu (BelongsTo) ilişkilerin geçerliliğini kontrol eder. Alan zorunlu ise ve değer nil ise hata döndürür. Gerçek implementasyonda veritabanı sorgusu yaparak ilişkili kaynağın varlığı kontrol edilmelidir.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak ilişki değeri (parent kaynak ID'si) - `field`: *BelongsToField - BelongsTo alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Hatalar

- `RelationshipError`: Alan zorunlu ve değer nil ise

Örnek

```go validator := fields.NewRelationshipValidator()

// Post -> User ilişkisini doğrula belongsToField := fields.NewBelongsTo("user", "users").Required() err := validator.ValidateBelongsTo(ctx, userID, belongsToField)

if err != nil {
    // İlişkili kullanıcı bulunamadı veya zorunlu alan boş
    log.Printf("BelongsTo doğrulama hatası: %v", err)
}

```

İşlem Adımları (Gerçek İmplementasyon)

1. Değerin nil olup olmadığını kontrol et 2. Alan zorunlu ise ve değer nil ise hata döndür 3. Veritabanında ilişkili kaynağı sorgula 4. Kaynak bulunamazsa hata döndür

Not

BelongsTo ilişkileri genellikle foreign key ile tanımlanır. Örneğin, bir Post kaydı user_id foreign key'i ile User kaydına bağlanır.

func (*RelationshipValidatorImpl) ValidateBelongsToMany

func (rv *RelationshipValidatorImpl) ValidateBelongsToMany(ctx context.Context, value interface{}, field *BelongsToManyField) error

ValidateBelongsToMany, BelongsToMany ilişkilerini doğrular.

Bu metod, çoka-çok (many-to-many) ilişkilerin geçerliliğini kontrol eder. BelongsToMany ilişkileri pivot tablo kullanarak iki kaydı birbirine bağlar. Gerçek implementasyonda pivot tablosundaki tüm girişlerin var olduğu ve hem foreign key'lerin hem de related key'lerin geçerli olduğu kontrol edilmelidir.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak ilişki değerleri (pivot tablo girişleri) - `field`: *BelongsToManyField - BelongsToMany alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Örnek

```go validator := fields.NewRelationshipValidator()

// User -> Roles ilişkisini doğrula (pivot: role_user) belongsToManyField := fields.NewBelongsToMany("roles", "roles").

PivotTable("role_user").
ForeignKey("user_id").
RelatedKey("role_id")

err := validator.ValidateBelongsToMany(ctx, roleIDs, belongsToManyField)

if err != nil {
    // Pivot tablo girişleri veya ilişkili kayıtlar geçersiz
    log.Printf("BelongsToMany doğrulama hatası: %v", err)
}

```

İşlem Adımları (Gerçek İmplementasyon)

1. Pivot tablo girişlerini çıkar 2. Tüm girişlerin pivot tablosunda var olduğunu doğrula 3. Foreign key'lerin ve related key'lerin geçerli olduğunu doğrula

Not

BelongsToMany ilişkileri üç tablo kullanır: iki ana tablo ve bir pivot tablo. Örneğin, User ve Role tabloları arasında role_user pivot tablosu ile çoka-çok ilişki kurulabilir.

func (*RelationshipValidatorImpl) ValidateExists

func (rv *RelationshipValidatorImpl) ValidateExists(ctx context.Context, value interface{}, field RelationshipField) error

ValidateExists, ilişkili kaynağın var olup olmadığını doğrular.

Bu metod, verilen değerin nil olup olmadığını kontrol eder ve alan zorunlu ise hata döndürür. Gerçek implementasyonda veritabanı sorgusu yaparak ilişkili kaynağın varlığı kontrol edilmelidir.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak değer (ilişkili kaynak ID'si) - `field`: RelationshipField - İlişki alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Hatalar

- `RelationshipError`: Alan zorunlu ve değer nil ise

Örnek

```go validator := fields.NewRelationshipValidator() err := validator.ValidateExists(ctx, userID, belongsToField)

if err != nil {
    // İlişkili kaynak bulunamadı veya zorunlu alan boş
    log.Printf("Doğrulama hatası: %v", err)
}

```

Not

Şu anki implementasyon sadece nil kontrolü yapar. Gerçek kullanımda veritabanı sorgusu eklenmeli ve kaynağın varlığı kontrol edilmelidir.

func (*RelationshipValidatorImpl) ValidateForeignKey

func (rv *RelationshipValidatorImpl) ValidateForeignKey(ctx context.Context, value interface{}, field RelationshipField) error

ValidateForeignKey, foreign key referanslarını doğrular.

Bu metod, verilen değerin geçerli bir foreign key olup olmadığını kontrol eder. Gerçek implementasyonda veritabanı sorgusu yaparak foreign key'in ilişkili tabloda var olup olmadığı kontrol edilmelidir.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak foreign key değeri - `field`: RelationshipField - İlişki alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Örnek

```go validator := fields.NewRelationshipValidator() err := validator.ValidateForeignKey(ctx, categoryID, belongsToField)

if err != nil {
    // Foreign key geçersiz
    log.Printf("Foreign key hatası: %v", err)
}

```

İşlem Adımları (Gerçek İmplementasyon)

1. Foreign key değerini çıkar 2. İlişkili kaynak tablosunu sorgula 3. Foreign key'in var olduğunu doğrula

Not

Şu anki implementasyon sadece nil kontrolü yapar. Gerçek kullanımda veritabanı sorgusu eklenmeli ve foreign key'in varlığı kontrol edilmelidir.

func (*RelationshipValidatorImpl) ValidateHasMany

func (rv *RelationshipValidatorImpl) ValidateHasMany(ctx context.Context, value interface{}, field *HasManyField) error

ValidateHasMany, HasMany ilişkilerini doğrular.

Bu metod, bir kaydın birden fazla ilişkili kayda sahip olduğu (HasMany) ilişkilerin geçerliliğini kontrol eder. Gerçek implementasyonda veritabanı sorgusu yaparak tüm foreign key'lerin geçerli olduğu kontrol edilmelidir.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak ilişki değerleri (child kaynak ID'leri) - `field`: *HasManyField - HasMany alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Örnek

```go validator := fields.NewRelationshipValidator()

// User -> Posts ilişkisini doğrula hasManyField := fields.NewHasMany("posts", "posts") err := validator.ValidateHasMany(ctx, postIDs, hasManyField)

if err != nil {
    // İlişkili kayıtlar geçersiz
    log.Printf("HasMany doğrulama hatası: %v", err)
}

```

İşlem Adımları (Gerçek İmplementasyon)

1. Foreign key değerlerini çıkar 2. İlişkili kaynak tablosunu sorgula 3. Tüm foreign key'lerin geçerli olduğunu doğrula

Not

HasMany ilişkileri genellikle child tabloda foreign key ile tanımlanır. Örneğin, bir User kaydı birden fazla Post kaydına sahip olabilir ve her Post kaydı user_id foreign key'i ile User'a bağlanır.

func (*RelationshipValidatorImpl) ValidateHasOne

func (rv *RelationshipValidatorImpl) ValidateHasOne(ctx context.Context, value interface{}, field *HasOneField) error

ValidateHasOne, HasOne ilişkilerini doğrular.

Bu metod, bir kaydın tek bir ilişkili kayda sahip olduğu (HasOne) ilişkilerin geçerliliğini kontrol eder. Gerçek implementasyonda veritabanı sorgusu yaparak en fazla bir ilişkili kaynağın var olduğu kontrol edilmelidir.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak ilişki değeri (child kaynak ID'si) - `field`: *HasOneField - HasOne alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Örnek

```go validator := fields.NewRelationshipValidator()

// User -> Profile ilişkisini doğrula hasOneField := fields.NewHasOne("profile", "profiles") err := validator.ValidateHasOne(ctx, profileID, hasOneField)

if err != nil {
    // İlişkili kayıt geçersiz veya birden fazla kayıt var
    log.Printf("HasOne doğrulama hatası: %v", err)
}

```

İşlem Adımları (Gerçek İmplementasyon)

1. Foreign key değerini çıkar 2. İlişkili kaynak tablosunu sorgula 3. En fazla bir ilişkili kaynağın var olduğunu doğrula

Not

HasOne ilişkileri HasMany'ye benzer ancak tek bir kayıt ile sınırlıdır. Örneğin, bir User kaydı tek bir Profile kaydına sahip olabilir ve Profile kaydı user_id foreign key'i ile User'a bağlanır.

func (*RelationshipValidatorImpl) ValidateMorphTo

func (rv *RelationshipValidatorImpl) ValidateMorphTo(ctx context.Context, value interface{}, field *MorphTo) error

ValidateMorphTo, MorphTo ilişkilerini doğrular.

Bu metod, polimorfik (MorphTo) ilişkilerin geçerliliğini kontrol eder. MorphTo ilişkileri, bir kaydın birden fazla farklı model tipine bağlanabilmesini sağlar. Gerçek implementasyonda morph tipinin kayıtlı olduğu, ilgili kaynak tablosunun sorgulandığı ve kaynağın var olduğu kontrol edilmelidir.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak morph değeri (tip ve ID içerir) - `field`: *MorphTo - MorphTo alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Hatalar

- `RelationshipError`: Hiç morph tipi kayıtlı değilse

Örnek

```go validator := fields.NewRelationshipValidator()

// Comment -> Commentable (Post veya Video) ilişkisini doğrula morphToField := fields.NewMorphTo("commentable").

AddType("post", "posts").
AddType("video", "videos")

// Morph değeri: {type: "post", id: 123}

morphValue := map[string]interface{}{
    "commentable_type": "post",
    "commentable_id": 123,
}

err := validator.ValidateMorphTo(ctx, morphValue, morphToField)

if err != nil {
    // Morph tipi kayıtlı değil veya ilişkili kaynak bulunamadı
    log.Printf("MorphTo doğrulama hatası: %v", err)
}

```

İşlem Adımları (Gerçek İmplementasyon)

1. Değerden morph tipini çıkar 2. Tipin alan tanımındaki tip eşleştirmelerinde kayıtlı olup olmadığını kontrol et 3. İlgili kaynak tablosunu sorgula 4. Kaynağın var olduğunu doğrula

Not

MorphTo ilişkileri için en az bir tip kaydı zorunludur. Tip eşleştirmeleri morph_type sütunundaki değerleri gerçek model isimlerine çevirir. Örneğin: "post" -> "posts" tablosu, "video" -> "videos" tablosu

Referans

Detaylı polimorfik ilişki dokümantasyonu için: `docs/Relationships.md`

func (*RelationshipValidatorImpl) ValidateMorphType

func (rv *RelationshipValidatorImpl) ValidateMorphType(ctx context.Context, value interface{}, field RelationshipField) error

ValidateMorphType, morph tipinin kayıtlı olup olmadığını doğrular.

Bu metod, polimorfik ilişkilerde (MorphTo) kullanılan morph tipinin alan tanımında kayıtlı olup olmadığını kontrol eder. MorphTo ilişkileri birden fazla model tipine bağlanabildiği için, tip eşleştirmelerinin doğru yapılandırılması kritiktir.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak morph değeri - `field`: RelationshipField - İlişki alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Hatalar

- `RelationshipError`: MorphTo alanında hiç tip kayıtlı değilse

Örnek

```go validator := fields.NewRelationshipValidator() err := validator.ValidateMorphType(ctx, morphValue, morphToField)

if err != nil {
    // Morph tipi kayıtlı değil
    log.Printf("Morph tip hatası: %v", err)
}

```

İşlem Adımları (Gerçek İmplementasyon)

1. Değerden morph tipini çıkar 2. Tipin alan tanımındaki tip eşleştirmelerinde kayıtlı olup olmadığını kontrol et 3. Kayıtlı değilse hata döndür

Not

MorphTo alanları için en az bir tip kaydı zorunludur. Aksi takdirde polimorfik ilişki kurulamaz.

func (*RelationshipValidatorImpl) ValidatePivot

func (rv *RelationshipValidatorImpl) ValidatePivot(ctx context.Context, value interface{}, field RelationshipField) error

ValidatePivot, pivot tablo girişlerini doğrular.

Bu metod, çoka-çok (many-to-many) ilişkilerde kullanılan pivot tablo girişlerinin geçerliliğini kontrol eder. Gerçek implementasyonda pivot tablosundaki tüm girişlerin var olduğu ve foreign key'lerin geçerli olduğu doğrulanmalıdır.

Parametreler

- `ctx`: Context - İşlem context'i - `value`: interface{} - Doğrulanacak pivot tablo değerleri - `field`: RelationshipField - İlişki alan tanımı

Döndürür

- `error`: Doğrulama hatası (varsa), nil (başarılı ise)

Örnek

```go validator := fields.NewRelationshipValidator() err := validator.ValidatePivot(ctx, pivotData, belongsToManyField)

if err != nil {
    // Pivot tablo girişleri geçersiz
    log.Printf("Pivot doğrulama hatası: %v", err)
}

```

İşlem Adımları (Gerçek İmplementasyon)

1. Pivot tablo girişlerini çıkar 2. Tüm girişlerin pivot tablosunda var olduğunu doğrula 3. Foreign key'lerin geçerli olduğunu doğrula

Not

Şu anki implementasyon sadece nil kontrolü yapar. Gerçek kullanımda pivot tablo sorguları eklenmeli ve girişlerin varlığı kontrol edilmelidir.

type Resolver

type Resolver = core.Resolver

Resolver, alan değerlerini çözümleyen interface'dir.

Bu tip, core.Resolver'ın bir alias'ıdır ve özel alan değeri çözümleme mantığı sağlamak için kullanılır.

Daha fazla bilgi için pkg/core/resolver.go dosyasına bakın.

type Schema

type Schema struct {
	Name               string                                                              `json:"name"`      // Görünen Ad
	Key                string                                                              `json:"key"`       // Veri Anahtarı
	View               string                                                              `json:"view"`      // Frontend Bileşeni
	Data               interface{}                                                         `json:"data"`      // Alan Değeri
	Type               ElementType                                                         `json:"type"`      // Veri Tipi
	Context            ElementContext                                                      `json:"context"`   // Görünüm Bağlamı (List, Detail, Form)
	IsReadOnly         bool                                                                `json:"read_only"` // Salt okunur mu?
	IsDisabled         bool                                                                `json:"disabled"`  // Devre dışı mı?
	IsImmutable        bool                                                                `json:"immutable"` // Değiştirilemez mi?
	Props              map[string]interface{}                                              `json:"props"`     // Ekstra özellikler
	IsRequired         bool                                                                `json:"required"`  // Zorunlu mu?
	IsNullable         bool                                                                `json:"nullable"`  // Boş bırakılabilir mi?
	PlaceholderText    string                                                              `json:"placeholder"`
	LabelText          string                                                              `json:"label"`
	HelpTextContent    string                                                              `json:"help_text"`
	IsFilterable       bool                                                                `json:"filterable"`
	IsSortable         bool                                                                `json:"sortable"`
	GlobalSearch       bool                                                                `json:"searchable"`
	IsStacked          bool                                                                `json:"stacked"`
	TextAlign          string                                                              `json:"text_align"`
	Suggestions        []interface{}                                                       `json:"suggestions"`
	ExtractCallback    func(value interface{}, item interface{}, c *fiber.Ctx) interface{} `json:"-"`
	VisibilityCallback VisibilityFunc                                                      `json:"-"`
	StorageCallback    StorageCallbackFunc                                                 `json:"-"`
	ModifyCallback     func(value interface{}, c *fiber.Ctx) interface{}                   `json:"-"`
	AutoOptionsConfig  core.AutoOptionsConfig                                              `json:"-"`

	// Validation (Kategori 1)
	ValidationRules         []ValidationRule `json:"validation_rules"`
	CreationValidationRules []ValidationRule `json:"creation_validation_rules,omitempty"`
	UpdateValidationRules   []ValidationRule `json:"update_validation_rules,omitempty"`
	CustomValidators        []ValidatorFunc  `json:"-"`

	// Display (Kategori 2)
	DisplayCallback        func(value interface{}, item interface{}) interface{} `json:"-"`
	DisplayedAs            string                                                `json:"displayed_as"`
	DisplayUsingLabelsFlag bool                                                  `json:"display_using_labels"`
	ResolveHandleValue     string                                                `json:"resolve_handle"`

	// Dependencies (Kategori 3)
	DependsOnFields            []string               `json:"depends_on"`
	DependencyRules            map[string]interface{} `json:"dependency_rules"`
	DependencyCallback         DependencyCallbackFunc `json:"-"`
	DependencyCallbackOnCreate DependencyCallbackFunc `json:"-"`
	DependencyCallbackOnUpdate DependencyCallbackFunc `json:"-"`

	// Suggestions (Kategori 4)
	SuggestionsCallback       func(string) []interface{} `json:"-"`
	AutoCompleteURL           string                     `json:"autocomplete_url"`
	MinCharsForSuggestionsVal int                        `json:"min_chars_for_suggestions"`

	// Attachments (Kategori 5)
	AcceptedMimeTypes  []string                             `json:"accepted_mime_types"`
	MaxFileSize        int64                                `json:"max_file_size"`
	StorageDisk        string                               `json:"storage_disk"`
	StoragePath        string                               `json:"storage_path"`
	UploadCallback     func(interface{}, interface{}) error `json:"-"`
	RemoveEXIFDataFlag bool                                 `json:"remove_exif_data"`

	// Repeater (Kategori 6)
	RepeaterFields  []core.Element `json:"-"`
	MinRepeatsCount int            `json:"min_repeats"`
	MaxRepeatsCount int            `json:"max_repeats"`

	// Rich Text (Kategori 7)
	EditorType     string `json:"editor_type"`
	EditorLanguage string `json:"editor_language"`
	EditorTheme    string `json:"editor_theme"`

	// Status (Kategori 8)
	StatusColors map[string]string `json:"status_colors"`
	BadgeVariant string            `json:"badge_variant"`

	// Pivot (Kategori 9)
	IsPivotField      bool   `json:"is_pivot_field"`
	PivotResourceName string `json:"pivot_resource_name"`

	// GORM Veritabanı Yapılandırması (Kategori 10)
	GormConfiguration *GormConfig `json:"-"`

	// Context for i18n (Kategori 11)
	FiberCtx *fiber.Ctx `json:"-"`
}

Schema, bir alanın temel yapılandırmasını ve durumunu tutan yapıdır.

Schema, Go Panel API'nin alan sisteminin temel yapı taşıdır. Her alan, bir Schema örneği olarak temsil edilir ve frontend ile backend arasında veri taşımak için kullanılır.

Temel Özellikler

- **JSON Serileştirme**: Tüm alanlar JSON formatında serileştirilebilir - **Veri Çıkarma**: Reflection kullanarak model'lerden veri çıkarır - **Görünürlük Kontrolü**: Farklı bağlamlarda (list, detail, form) görünürlük kontrolü - **Callback Desteği**: Extract, Modify, Resolve, Storage callback'leri - **Fluent API**: Zincirleme metod çağrıları ile kolay yapılandırma

Kategoriler

Schema, 10 ana kategoride özellik içerir:

1. **Temel Özellikler**: Name, Key, View, Data, Type, Context 2. **Durum Özellikleri**: IsReadOnly, IsDisabled, IsImmutable, IsRequired, IsNullable 3. **UI Özellikleri**: PlaceholderText, LabelText, HelpTextContent, IsStacked, TextAlign 4. **Arama/Filtreleme**: IsFilterable, IsSortable, GlobalSearch 5. **Callback'ler**: ExtractCallback, VisibilityCallback, StorageCallback, ModifyCallback 6. **Doğrulama**: ValidationRules, CustomValidators 7. **Görüntüleme**: DisplayCallback, DisplayedAs, DisplayUsingLabelsFlag 8. **Bağımlılıklar**: DependsOnFields, DependencyRules 9. **Öneriler**: SuggestionsCallback, AutoCompleteURL, MinCharsForSuggestionsVal 10. **Dosya Yükleme**: AcceptedMimeTypes, MaxFileSize, StorageDisk, StoragePath

Kullanım Örneği

schema := &fields.Schema{
    Key:   "email",
    Name:  "E-posta",
    View:  "email-field",
    Type:  core.TYPE_EMAIL,
    Props: make(map[string]interface{}),
}
schema.OnList().OnDetail().OnForm().Required().Searchable()

Mixin Desteği

Schema, mixin pattern'ini desteklemez (çünkü kendisi bir veri yapısıdır), ancak mixin özelliklerini (Searchable, Sortable, vb.) field'lar aracılığıyla kullanabilir.

Daha fazla bilgi için docs/Fields.md ve .docs/ARCHITECTURE.md dosyalarına bakın.

func Audio

func Audio(name string, attribute ...string) *Schema

Bu fonksiyon, ses dosyası yükleme alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - Podcast bölümleri, müzik dosyaları, ses notları gibi ses dosyaları yüklemek için - Genellikle MP3, WAV, OGG, M4A gibi ses formatlarını destekler - Ses oynatıcı entegrasyonu yapılabilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Ses Dosyası", "Podcast")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış ses alan şeması pointer'ı

Örnek Kullanım:

audioField := Audio("Ses Dosyası")
podcastField := Audio("Podcast Bölümü", "podcast_episode")

Önemli Notlar:

  • Frontend bileşeni "file-field" olarak ayarlanır
  • TYPE_AUDIO sabiti ile alan türü belirtilir
  • Ses codec ve format doğrulaması yapılabilir
  • Ses süresi metadata'sı çıkarılabilir

func Badge

func Badge(name string, attribute ...string) *Schema

Bu fonksiyon, badge/status gösterim alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - Durum göstermek için (örn: "Aktif", "Beklemede", "Tamamlandı") - Renk kodlu etiketler ile görsel durum gösterimi - Genellikle salt okunur (read-only) alan olarak kullanılır

Parametreler:

  • name: Alanın görüntü adı (örn: "Durum", "Etiket")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış badge alan şeması pointer'ı

Örnek Kullanım:

statusBadge := Badge("Durum")
tagBadge := Badge("Etiket", "tag")

Önemli Notlar:

  • Frontend bileşeni "badge-field" olarak ayarlanır
  • TYPE_BADGE sabiti ile alan türü belirtilir
  • Renk ve stil Props haritasına eklenebilir
  • Genellikle liste görünümünde gösterilir

func BooleanGroup

func BooleanGroup(name string, attribute ...string) *Schema

Bu fonksiyon, birden fazla boolean seçeneği checkbox group olarak gösterir ve yapılandırır.

Kullanım Senaryosu: - Birden fazla özelliği aynı anda seçmek için (örn: İzinler, Tercihler) - Her seçenek bağımsız olarak seçilebilir veya seçimi kaldırılabilir - Genellikle JSON array veya virgülle ayrılmış string olarak saklanır

Parametreler:

  • name: Alanın görüntü adı (örn: "İzinler", "Tercihler")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış boolean grup alan şeması pointer'ı

Örnek Kullanım:

permissionsGroup := BooleanGroup("İzinler")
preferencesGroup := BooleanGroup("Tercihler", "user_preferences")

Önemli Notlar:

  • Frontend bileşeni "boolean-group-field" olarak ayarlanır
  • TYPE_BOOLEAN_GROUP sabiti ile alan türü belirtilir
  • Seçenekler Props haritasına "options" anahtarı ile eklenebilir
  • Genellikle JSON array olarak veritabanında saklanır

func Code

func Code(name string, attribute ...string) *Schema

Bu fonksiyon, kod editörü alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - JSON, JavaScript, SQL, HTML gibi kod yazma ve düzenleme için - Syntax highlighting ve kod biçimlendirmesi destekler - Genellikle Monaco Editor veya benzer editörler ile entegre edilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Kod", "SQL Sorgusu")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış kod alan şeması pointer'ı

Örnek Kullanım:

codeField := Code("Kod")
sqlField := Code("SQL Sorgusu", "sql_query")

Önemli Notlar:

  • Frontend bileşeni "code-field" olarak ayarlanır
  • TYPE_CODE sabiti ile alan türü belirtilir
  • Dil (language) Props haritasına eklenebilir (json, javascript, sql, html vb.)
  • Tema (theme) ayarlanabilir (light, dark vb.)

func Collection

func Collection(name string, resource string, attribute ...string) *Schema

Bu fonksiyon, ilişkili kayıtların listesini gösteren (HasMany ilişkisi) alan oluşturur ve yapılandırır.

Kullanım Senaryosu: - Bir kaynağın birden fazla ilişkili kaynağa sahip olduğu bire-çok ilişkiyi temsil eder - Örn: Bir yazının birden fazla yorumu, bir kategorinin birden fazla ürünü - Genellikle listede gizlenir, detay sayfasında ilişkili kayıtların tablosu gösterilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Yorumlar", "Ürünler")
  • resource: İlişkili kaynağın adı (örn: "comments", "products")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış koleksiyon alan şeması pointer'ı

Örnek Kullanım:

commentsCollection := Collection("Yorumlar", "comments")
productsCollection := Collection("Ürünler", "products", "product_ids")

Önemli Notlar:

  • Frontend bileşeni "collection-field" olarak ayarlanır
  • TYPE_COLLECTION sabiti ile alan türü belirtilir
  • Context HIDE_ON_LIST ile liste görünümünde gizlenir
  • Detay sayfasında ilişkili kayıtların listesi gösterilir

func Color

func Color(name string, attribute ...string) *Schema

Bu fonksiyon, renk seçici alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - Tema rengi, arka plan rengi, vurgu rengi gibi renk seçimi için - Hex, RGB, HSL format desteği sağlar - Renk paleti veya özel renk seçici ile seçim yapılabilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Renk", "Tema Rengi")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış renk alan şeması pointer'ı

Örnek Kullanım:

colorField := Color("Renk")
themeColorField := Color("Tema Rengi", "theme_color")

Önemli Notlar:

  • Frontend bileşeni "color-field" olarak ayarlanır
  • TYPE_COLOR sabiti ile alan türü belirtilir
  • Hex formatı (#RRGGBB) standart olarak kullanılır
  • Alfa (opacity) değeri eklenebilir

func Combobox

func Combobox(name string, attribute ...string) *Schema

Bu fonksiyon, çoktan seçmeli veya arama yapılabilir seçim alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - Uzun seçenekler listesinden arama yaparak seçim yapmak için - Otomatik tamamlama (autocomplete) özelliği ile hızlı seçim - Genellikle API'den dinamik olarak yüklenen seçenekler için

Parametreler:

  • name: Alanın görüntü adı (örn: "Ürün", "Müşteri")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış combobox alan şeması pointer'ı

Örnek Kullanım:

productCombo := Combobox("Ürün")
customerCombo := Combobox("Müşteri", "customer_id")

Önemli Notlar:

  • Frontend bileşeni "combobox-field" olarak ayarlanır
  • TYPE_SELECT sabiti ile alan türü belirtilir (veya TYPE_COMBOBOX eğer yeni tip gerekiyorsa)
  • Arama ve filtreleme işlevselliği sağlar
  • Genellikle Select'ten daha gelişmiş bir bileşendir

func Connect

func Connect(name string, resource string, attribute ...string) *Schema

Bu fonksiyon, çoktan çoka (BelongsToMany ilişkisi) ilişki kurmak için kullanılır ve yapılandırır.

Kullanım Senaryosu: - İki kaynak arasında çoktan çoka ilişkiyi temsil eder - Örn: Bir ürünün birden fazla etiketi, bir yazının birden fazla kategorisi - Genellikle ara tablo (pivot table) ile yönetilir - Listede gizlenir, detay sayfasında ilişkili kayıtları seçmek için kullanılır

Parametreler:

  • name: Alanın görüntü adı (örn: "Etiketler", "Kategoriler")
  • resource: İlişkili kaynağın adı (örn: "tags", "categories")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış bağlantı alan şeması pointer'ı

Örnek Kullanım:

tagsConnect := Connect("Etiketler", "tags")
categoriesConnect := Connect("Kategoriler", "categories", "category_ids")

Önemli Notlar:

  • Frontend bileşeni "connect-field" olarak ayarlanır
  • TYPE_CONNECT sabiti ile alan türü belirtilir
  • Context HIDE_ON_LIST ile liste görünümünde gizlenir
  • Detay sayfasında çoklu seçim yapılabilir

func Date

func Date(name string, attribute ...string) *Schema

Bu fonksiyon, tarih seçim alanı (datepicker) oluşturur ve yapılandırır.

Kullanım Senaryosu: - Doğum tarihi, etkinlik tarihi, başlangıç tarihi gibi tarih girişi için - Takvim arayüzü ile tarih seçimi yapılabilir - Tarih formatı ve aralığı kısıtlaması eklenebilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Doğum Tarihi", "Etkinlik Tarihi")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış tarih alan şeması pointer'ı

Örnek Kullanım:

dateField := Date("Doğum Tarihi")
eventField := Date("Etkinlik Tarihi", "event_date")

Önemli Notlar:

  • Frontend bileşeni "date-field" olarak ayarlanır
  • TYPE_DATE sabiti ile alan türü belirtilir
  • Tarih formatı (YYYY-MM-DD) standart olarak kullanılır
  • Min/Max tarih kısıtlaması eklenebilir

func DateTime

func DateTime(name string, attribute ...string) *Schema

Bu fonksiyon, tarih ve saat seçim alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - Etkinlik başlangıç zamanı, randevu saati, yayın zamanı gibi tarih ve saat girişi için - Takvim ve saat seçici arayüzü ile tarih ve saat seçimi yapılabilir - Zaman dilimi (timezone) desteği eklenebilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Randevu Saati", "Yayın Zamanı")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış tarih-saat alan şeması pointer'ı

Örnek Kullanım:

datetimeField := DateTime("Randevu Saati")
eventField := DateTime("Etkinlik Zamanı", "event_datetime")

Önemli Notlar:

  • Frontend bileşeni "datetime-field" olarak ayarlanır
  • TYPE_DATETIME sabiti ile alan türü belirtilir
  • ISO 8601 formatı (YYYY-MM-DDTHH:mm:ss) standart olarak kullanılır
  • Zaman dilimi bilgisi saklanabilir

func Detail

func Detail(name string, resource string, attribute ...string) *Schema

Bu fonksiyon, bir kaynağın detayını gösteren (HasOne ilişkisi) alan oluşturur ve yapılandırır.

Kullanım Senaryosu: - Bir kaynağın başka bir kaynağa sahip olduğu bire-bir ilişkiyi temsil eder - Örn: Bir kullanıcının bir profili, bir ürünün bir açıklaması - Genellikle listede gizlenir, detay sayfasında gösterilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Profil", "Açıklama")
  • resource: İlişkili kaynağın adı (örn: "profiles", "descriptions")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış detay alan şeması pointer'ı

Örnek Kullanım:

profileDetail := Detail("Profil", "profiles")
descDetail := Detail("Açıklama", "descriptions", "description_id")

Önemli Notlar:

  • Frontend bileşeni "detail-field" olarak ayarlanır
  • TYPE_DETAIL sabiti ile alan türü belirtilir
  • Context HIDE_ON_LIST ile liste görünümünde gizlenir
  • Detay sayfasında ilişkili kaynağın bilgileri gösterilir

func Email

func Email(name string, attribute ...string) *Schema

Bu fonksiyon, e-posta giriş alanı (input type="email") oluşturur ve yapılandırır.

Kullanım Senaryosu: - Kullanıcı e-posta adresi, iletişim e-postası gibi e-posta girişi için - Otomatik olarak e-posta formatı doğrulaması yapılır - Tarayıcı tarafından native e-posta doğrulaması desteklenir

Parametreler:

  • name: Alanın görüntü adı (örn: "E-posta", "İletişim E-postası")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış e-posta alan şeması pointer'ı

Örnek Kullanım:

emailField := Email("E-posta")
contactField := Email("İletişim E-postası", "contact_email")

Önemli Notlar:

  • Frontend bileşeni "email-field" olarak ayarlanır
  • TYPE_EMAIL sabiti ile alan türü belirtilir
  • Backend'de regex veya email validator kütüphanesi ile doğrulama yapılmalı
  • Benzersizlik kısıtlaması (unique constraint) eklenebilir

func File

func File(name string, attribute ...string) *Schema

Bu fonksiyon, genel dosya yükleme alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - PDF, Word, Excel, ZIP gibi çeşitli dosya türlerini yüklemek için - Belge yönetimi, raporlar, ek dosyalar gibi genel dosya depolaması için - Dosya türü ve boyutu kısıtlaması eklenebilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Dosya", "Ek Dosya")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış dosya alan şeması pointer'ı

Örnek Kullanım:

fileField := File("Dosya")
attachmentField := File("Ek Dosya", "attachment")

Önemli Notlar:

  • Frontend bileşeni "file-field" olarak ayarlanır
  • TYPE_FILE sabiti ile alan türü belirtilir
  • Dosya türü whitelist'i eklenebilir (örn: .pdf, .doc, .xls)
  • Maksimum dosya boyutu kısıtlaması yapılabilir

func ID

func ID(name ...string) *Schema

Bu fonksiyon, benzersiz kimlik alanını oluşturur ve yapılandırır.

Kullanım Senaryosu: - Veritabanı kayıtlarının birincil anahtarını temsil eder - Genellikle otomatik olarak oluşturulan ve değiştirilemeyen bir alandır - Yalnızca liste görünümünde gösterilir, form düzenlemesinde gizlenir

Parametreler:

  • name: İsteğe bağlı alan adı (varsayılan: "ID")

Dönüş Değeri:

  • *Schema: Yapılandırılmış ID alan şeması pointer'ı

Örnek Kullanım:

idField := ID()                    // Varsayılan "ID" adı ile
idField := ID("Kayıt Numarası")    // Özel ad ile

Önemli Notlar:

  • Veritabanı anahtarı her zaman "id" olarak ayarlanır
  • OnlyOnList() metodu çağrılarak sadece liste görünümünde gösterilir
  • Frontend bileşeni "id-field" olarak ayarlanır

func Image

func Image(name string, attribute ...string) *Schema

Bu fonksiyon, görsel yükleme alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - Ürün resimleri, profil fotoğrafları, banner görselleri gibi görsel dosyaları yüklemek için - Genellikle JPG, PNG, WebP gibi görsel formatlarını destekler - Ön izleme (preview) ve crop işlemleri yapılabilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Ürün Resmi", "Profil Fotoğrafı")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış görsel alan şeması pointer'ı

Örnek Kullanım:

imageField := Image("Ürün Resmi")
avatarField := Image("Profil Fotoğrafı", "avatar")

Önemli Notlar:

  • Frontend bileşeni "image-field" olarak ayarlanır
  • TYPE_FILE sabiti ile alan türü belirtilir
  • Dosya boyutu ve format kısıtlaması eklenebilir
  • CDN veya cloud storage entegrasyonu yapılabilir

func KeyValue

func KeyValue(name string, attribute ...string) *Schema

Bu fonksiyon, anahtar-değer ikilisi girişi sağlayan alan oluşturur ve yapılandırır.

Kullanım Senaryosu: - Dinamik ayarlar, meta veriler, özel özellikler gibi anahtar-değer çiftlerini depolamak için - JSON formatında saklanabilen esnek veri yapısı - Örn: {"color": "red", "size": "large", "material": "cotton"}

Parametreler:

  • name: Alanın görüntü adı (örn: "Özellikler", "Meta Veriler")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış anahtar-değer alan şeması pointer'ı

Örnek Kullanım:

kvField := KeyValue("Özellikler")
metaField := KeyValue("Meta Veriler", "metadata")

Önemli Notlar:

  • Frontend bileşeni "key-value-field" olarak ayarlanır
  • TYPE_KEY_VALUE sabiti ile alan türü belirtilir
  • Genellikle JSON formatında veritabanında saklanır
  • Dinamik form alanları için idealdir
func Link(name string, resource string, attribute ...string) *Schema

Bu fonksiyon, başka bir kaynağa bağlantı (BelongsTo ilişkisi) oluşturur ve yapılandırır.

Kullanım Senaryosu: - Bir kaynağın başka bir kaynağa ait olduğu ilişkiyi temsil eder - Örn: Bir ürün bir kategoriye ait, bir yorum bir yazıya ait - Seçim alanı ile ilişkili kaynağı seçmek için kullanılır

Parametreler:

  • name: Alanın görüntü adı (örn: "Kategori", "Yazar")
  • resource: İlişkili kaynağın adı (örn: "categories", "authors")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış bağlantı alan şeması pointer'ı

Örnek Kullanım:

categoryLink := Link("Kategori", "categories")
authorLink := Link("Yazar", "authors", "author_id")

Önemli Notlar:

  • Frontend bileşeni "link-field" olarak ayarlanır
  • TYPE_LINK sabiti ile alan türü belirtilir
  • Props haritasına "resource" anahtarı ile ilişkili kaynak adı eklenir
  • Method chaining ile ek özellikler eklenebilir

func Matrix

func Matrix(name string, attribute ...string) *Schema

Matrix, satır/sütun bazlı JSON veri giriş alanı oluşturur.

Bu alan tipi; dinamik kolonlar, farklı hücre tipleri (text/select/checkbox/radio vb.) ve satır ekleme-silme davranışları gibi gelişmiş form ihtiyaçları için kullanılır.

Parametreler:

  • name: Alanın görüntü adı
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış matrix alan şeması pointer'ı

Örnek Kullanım:

matrix := Matrix("Variant Matrix", "variant_matrix")

Önemli Notlar:

  • Frontend bileşeni "matrix-field" olarak ayarlanır
  • TYPE_KEY_VALUE kullanılarak JSON tabanlı veri formatı korunur

func Money

func Money(name string, attribute ...string) *Schema

Money, para tutarı için özel bir alan oluşturur.

Varsayılan olarak: - view: "money-field" - type: TYPE_MONEY - currency: "USD" - currencies: DefaultCurrencies

func NewField

func NewField(name string, attribute ...string) *Schema

Bu fonksiyon, yeni bir alan şeması oluşturur ve temel konfigürasyonunu başlatır.

Kullanım Senaryosu: - Tüm alan türlerinin temelini oluşturur - Alan adını ve veritabanı anahtarını ayarlar - Varsayılan özellikleri başlatır

Parametreler:

  • name: Alanın görüntü adı (örn: "Kullanıcı Adı", "E-posta")
  • attribute: İsteğe bağlı veritabanı sütun adı (varsayılan: name'i küçük harfe çevirip boşlukları alt çizgi ile değiştirir)

Dönüş Değeri:

  • *Schema: Yapılandırılmış alan şeması pointer'ı

Örnek Kullanım:

field := NewField("Kullanıcı Adı")                    // Key: "kullanıcı_adı"
field := NewField("Kullanıcı Adı", "username")        // Key: "username"

Önemli Notlar:

  • Döndürülen Schema pointer'ı method chaining için kullanılabilir
  • Props haritası boş olarak başlatılır, sonradan özellikler eklenebilir
  • TextAlign varsayılan olarak "left" (sol hizalı) olarak ayarlanır

func Number

func Number(name string, attribute ...string) *Schema

Bu fonksiyon, sayı giriş alanı (input type="number") oluşturur ve yapılandırır.

Kullanım Senaryosu: - Yaş, fiyat, miktar, telefon numarası gibi sayısal değerlerin girişi için - Min/max değer kısıtlaması ve adım (step) ayarı yapılabilir - Otomatik olarak sayı dışı karakterleri filtreler

Parametreler:

  • name: Alanın görüntü adı (örn: "Fiyat", "Miktar")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış sayı alan şeması pointer'ı

Örnek Kullanım:

priceField := Number("Fiyat")
quantityField := Number("Miktar", "quantity")
ageField := Number("Yaş", "age")

Önemli Notlar:

  • Frontend bileşeni "number-field" olarak ayarlanır
  • TYPE_NUMBER sabiti ile alan türü belirtilir
  • Min/Max değerleri Props haritasına eklenebilir
  • Step değeri (örn: 0.01 para birimi için) ayarlanabilir

func Password

func Password(name string, attribute ...string) *Schema

Bu fonksiyon, şifre giriş alanı (input type="password") oluşturur ve yapılandırır.

Kullanım Senaryosu: - Kullanıcı şifresi, API anahtarı, gizli token gibi hassas bilgilerin girişi için - Girilen karakterler maskelenir ve görüntülenmez - Genellikle şifre güç göstergesi ve göster/gizle butonu ile birlikte kullanılır

Parametreler:

  • name: Alanın görüntü adı (örn: "Şifre", "Yeni Şifre")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış şifre alan şeması pointer'ı

Örnek Kullanım:

passField := Password("Şifre")
newPassField := Password("Yeni Şifre", "new_password")

Önemli Notlar:

  • Frontend bileşeni "password-field" olarak ayarlanır
  • TYPE_PASSWORD sabiti ile alan türü belirtilir
  • Backend'de şifre hash'lenmeli (bcrypt, argon2 vb.)
  • HTTPS üzerinden iletilmeli

func PolyCollection

func PolyCollection(name string, resource string, attribute ...string) *Schema

Bu fonksiyon, polimorfik koleksiyon (MorphMany ilişkisi) oluşturur ve yapılandırır.

Kullanım Senaryosu: - Bir kaynağın birden fazla farklı kaynak türüne ait olabileceği polimorfik bire-çok ilişkiyi temsil eder - Örn: Bir ürünün birden fazla açıklaması olabilir, bir yazının birden fazla yorumu olabilir - Genellikle listede gizlenir, detay sayfasında ilişkili kayıtların listesi gösterilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Açıklamalar", "Yorumlar")
  • resource: İlişkili kaynağın adı (örn: "descriptions", "comments")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış polimorfik koleksiyon alan şeması pointer'ı

Örnek Kullanım:

polyCollection := PolyCollection("Açıklamalar", "descriptions")
commentsCollection := PolyCollection("Yorumlar", "comments", "comment_ids")

Önemli Notlar:

  • Frontend bileşeni "poly-collection-field" olarak ayarlanır
  • TYPE_POLY_COLLECTION sabiti ile alan türü belirtilir
  • Context HIDE_ON_LIST ile liste görünümünde gizlenir

func PolyConnect

func PolyConnect(name string, resource string, attribute ...string) *Schema

Bu fonksiyon, polimorfik çoktan çoka (BelongsToMany ilişkisi) ilişki kurmak için kullanılır ve yapılandırır.

Kullanım Senaryosu: - Bir kaynağın birden fazla farklı kaynak türüne çoktan çoka ilişkiyi temsil eder - Örn: Bir ürünün birden fazla kategoriye ait olabilir, bir yazının birden fazla etiketi olabilir - Genellikle ara tablo (pivot table) ile yönetilir - Listede gizlenir, detay sayfasında ilişkili kayıtları seçmek için kullanılır

Parametreler:

  • name: Alanın görüntü adı (örn: "Kategoriler", "Etiketler")
  • resource: İlişkili kaynağın adı (örn: "categories", "tags")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış polimorfik bağlantı alan şeması pointer'ı

Örnek Kullanım:

polyConnect := PolyConnect("Kategoriler", "categories")
tagsConnect := PolyConnect("Etiketler", "tags", "tag_ids")

Önemli Notlar:

  • Frontend bileşeni "poly-connect-field" olarak ayarlanır
  • TYPE_POLY_CONNECT sabiti ile alan türü belirtilir
  • Context HIDE_ON_LIST ile liste görünümünde gizlenir
  • Detay sayfasında çoklu seçim yapılabilir

func PolyDetail

func PolyDetail(name string, resource string, attribute ...string) *Schema

Bu fonksiyon, polimorfik detay (MorphOne ilişkisi) oluşturur ve yapılandırır.

Kullanım Senaryosu: - Bir kaynağın birden fazla farklı kaynak türüne ait olabileceği polimorfik bire-bir ilişkiyi temsil eder - Örn: Bir ürünün bir açıklaması olabilir, bir yazının bir özeti olabilir - Genellikle listede gizlenir, detay sayfasında gösterilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Açıklama", "Özet")
  • resource: İlişkili kaynağın adı (örn: "descriptions", "summaries")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış polimorfik detay alan şeması pointer'ı

Örnek Kullanım:

polyDetail := PolyDetail("Açıklama", "descriptions")
summaryDetail := PolyDetail("Özet", "summaries", "summary_id")

Önemli Notlar:

  • Frontend bileşeni "poly-detail-field" olarak ayarlanır
  • TYPE_POLY_DETAIL sabiti ile alan türü belirtilir
  • Context HIDE_ON_LIST ile liste görünümünde gizlenir
func PolyLink(name string, attribute ...string) *Schema

Bu fonksiyon, polimorfik ilişki bağlantısı (MorphTo ilişkisi) oluşturur ve yapılandırır.

Kullanım Senaryosu: - Bir kaynağın birden fazla farklı kaynak türüne ait olabileceği polimorfik ilişkiyi temsil eder - Örn: Bir yorum bir yazıya veya bir ürüne ait olabilir - Genellikle "commentable_type" ve "commentable_id" sütunları ile yönetilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Bağlantılı Kaynak")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış polimorfik bağlantı alan şeması pointer'ı

Örnek Kullanım:

polyLink := PolyLink("Bağlantılı Kaynak")
commentableLink := PolyLink("Yorum Yapılan", "commentable")

Önemli Notlar:

  • Frontend bileşeni "poly-link-field" olarak ayarlanır
  • TYPE_POLY_LINK sabiti ile alan türü belirtilir
  • Polimorfik ilişkiler karmaşık olabilir, dikkatli tasarım gerekir

func RichText

func RichText(name string, attribute ...string) *Schema

Bu fonksiyon, zengin metin editörü (WYSIWYG - What You See Is What You Get) alanı oluşturur.

Kullanım Senaryosu: - Blog yazıları, ürün açıklamaları, HTML içeriği gibi zengin metin girişi için - Metin biçimlendirmesi (bold, italic, underline), listeler, linkler vb. destekler - Genellikle TinyMCE, Quill veya benzer editörler ile entegre edilir

Parametreler:

  • name: Alanın görüntü adı (örn: "İçerik", "Açıklama")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış zengin metin alan şeması pointer'ı

Örnek Kullanım:

contentField := RichText("İçerik")
descField := RichText("Ürün Açıklaması", "product_description")

Önemli Notlar:

  • Frontend bileşeni "richtext-field" olarak ayarlanır
  • TYPE_RICHTEXT sabiti ile alan türü belirtilir
  • HTML sanitization gerekli olabilir (XSS koruması için)

func Select

func Select(name string, attribute ...string) *Schema

Bu fonksiyon, standart seçim listesi oluşturur ve yapılandırır.

Kullanım Senaryosu: - Önceden tanımlanmış seçeneklerden birini seçmek için - Durum, kategori, tür gibi sınırlı sayıda seçeneği olan alanlar için - Dropdown veya select bileşeni ile seçim yapılır

Parametreler:

  • name: Alanın görüntü adı (örn: "Durum", "Tür")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış seçim alan şeması pointer'ı

Örnek Kullanım:

statusSelect := Select("Durum")
typeSelect := Select("Tür", "type_id")

Önemli Notlar:

  • Frontend bileşeni "select-field" olarak ayarlanır
  • TYPE_SELECT sabiti ile alan türü belirtilir
  • Seçenekler Props haritasına "options" anahtarı ile eklenebilir
  • Varsayılan değer ayarlanabilir

func Stack

func Stack(children []core.Element) *Schema

Stack, birden fazla alanı tek bir konteynerde göstermek için kullanılan display odaklı bir field oluşturur.

Bu fonksiyon özellikle Display callback'lerinde kullanılır:

fields.Text("Sizes", "sizes").Display(func(value interface{}, item interface{}) core.Element {
    return fields.Stack([]core.Element{
        fields.Badge("10").WithProps("variant", "secondary"),
        fields.Badge("20").WithProps("variant", "secondary"),
    })
})

func Switch

func Switch(name string, attribute ...string) *Schema

Bu fonksiyon, boolean değerler için switch/toggle bileşeni oluşturur ve yapılandırır.

Kullanım Senaryosu: - Aktif/Pasif, Evet/Hayır, Açık/Kapalı gibi boolean değerleri için - Toggle switch bileşeni ile kolay seçim yapılabilir - Genellikle veritabanında 0/1 veya true/false olarak saklanır

Parametreler:

  • name: Alanın görüntü adı (örn: "Aktif", "Yayınla")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış switch alan şeması pointer'ı

Örnek Kullanım:

activeSwitch := Switch("Aktif")
publishSwitch := Switch("Yayınla", "is_published")

Önemli Notlar:

  • Frontend bileşeni "switch-field" olarak ayarlanır
  • TYPE_BOOLEAN sabiti ile alan türü belirtilir
  • Genellikle checkbox yerine toggle switch kullanılır
  • Varsayılan değer (true/false) ayarlanabilir

func Tel

func Tel(name string, attribute ...string) *Schema

Bu fonksiyon, telefon numarası giriş alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - Müşteri telefon numarası, iletişim numarası gibi telefon girişi için - Genellikle metin input olarak render edilir, ancak telefon formatı doğrulaması yapılabilir - Ülkeye göre farklı telefon formatları desteklenebilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Telefon", "Cep Telefonu")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış telefon alan şeması pointer'ı

Örnek Kullanım:

phoneField := Tel("Telefon")
mobileField := Tel("Cep Telefonu", "mobile_phone")

Önemli Notlar:

  • Frontend bileşeni "text-field" olarak ayarlanır (genellikle text input kullanılır)
  • TYPE_TEL sabiti ile alan türü belirtilir
  • Backend'de regex veya libphonenumber gibi kütüphaneler ile doğrulama yapılmalı
  • Uluslararası format desteği eklenebilir

func Text

func Text(name string, attribute ...string) *Schema

Bu fonksiyon, standart metin giriş alanı (input type="text") oluşturur ve yapılandırır.

Kullanım Senaryosu: - Kullanıcı adı, başlık, kısa açıklama gibi tek satırlı metin girişi için - Basit string veri türü için en yaygın kullanılan alan - Maksimum uzunluk kısıtlaması eklenebilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Başlık", "Kullanıcı Adı")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış metin alan şeması pointer'ı

Örnek Kullanım:

titleField := Text("Başlık")
usernameField := Text("Kullanıcı Adı", "username")
emailField := Text("E-posta", "email_address")

Önemli Notlar:

  • Frontend bileşeni "text-field" olarak ayarlanır
  • TYPE_TEXT sabiti ile alan türü belirtilir
  • Method chaining ile ek özellikler eklenebilir (örn: .Required(), .MaxLength(100))

func Textarea

func Textarea(name string, attribute ...string) *Schema

Bu fonksiyon, çok satırlı metin giriş alanı (textarea) oluşturur ve yapılandırır.

Kullanım Senaryosu: - Uzun açıklamalar, notlar, biyografi gibi çok satırlı metin girişi için - Sabit yükseklikte veya dinamik olarak genişleyebilen textarea - Markdown veya HTML desteği eklenebilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Açıklama", "Notlar")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış textarea alan şeması pointer'ı

Örnek Kullanım:

descField := Textarea("Açıklama")
bioField := Textarea("Biyografi", "biography")

Önemli Notlar:

  • Frontend bileşeni "textarea-field" olarak ayarlanır
  • TYPE_TEXTAREA sabiti ile alan türü belirtilir
  • Satır sayısı (rows) özelliği Props haritasına eklenebilir

func Video

func Video(name string, attribute ...string) *Schema

Bu fonksiyon, video yükleme alanı oluşturur ve yapılandırır.

Kullanım Senaryosu: - Ürün tanıtım videoları, eğitim videoları, demo videoları gibi video dosyaları yüklemek için - Genellikle MP4, WebM, OGG gibi video formatlarını destekler - Video ön izlemesi ve oynatıcı entegrasyonu yapılabilir

Parametreler:

  • name: Alanın görüntü adı (örn: "Tanıtım Videosu", "Demo")
  • attribute: İsteğe bağlı veritabanı sütun adı

Dönüş Değeri:

  • *Schema: Yapılandırılmış video alan şeması pointer'ı

Örnek Kullanım:

videoField := Video("Tanıtım Videosu")
demoField := Video("Demo Videosu", "demo_video")

Önemli Notlar:

  • Frontend bileşeni "file-field" olarak ayarlanır
  • TYPE_VIDEO sabiti ile alan türü belirtilir
  • Dosya boyutu kısıtlaması eklenebilir (videolar genellikle büyük dosyalardır)
  • Video codec ve format doğrulaması yapılabilir

func (*Schema) Accept

func (s *Schema) Accept(mimeTypes ...string) core.Element

Accept, kabul edilen MIME tiplerini ayarlar.

Bu metod, hangi dosya tiplerinin yüklenebileceğini belirler. Frontend'de dosya seçici bu tiplere göre filtrelenir.

Parametreler

  • mimeTypes: Kabul edilen MIME tipleri (variadic)

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Yaygın MIME Tipleri

  • Resimler: "image/jpeg", "image/png", "image/gif", "image/webp"
  • Dökümanlar: "application/pdf", "application/msword"
  • Video: "video/mp4", "video/webm"
  • Audio: "audio/mpeg", "audio/wav"

Kullanım Senaryoları

  • Profil fotoğrafı yükleme
  • Döküman yükleme
  • Medya dosyası yükleme

Örnek

field := File("avatar", "Profil Fotoğrafı").
    Accept("image/jpeg", "image/png", "image/webp").
    MaxSize(5 * 1024 * 1024) // 5MB

func (*Schema) AddValidationRule

func (s *Schema) AddValidationRule(rule interface{}) core.Element

AddValidationRule, alana bir doğrulama kuralı ekler.

Bu metod, özel veya hazır doğrulama kurallarını alana eklemek için kullanılır. ValidationRule interface'ini implement eden herhangi bir kural eklenebilir.

Parametreler

  • rule: Eklenecek doğrulama kuralı (ValidationRule interface'ini implement etmeli)

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Özel doğrulama kuralları ekleme
  • Hazır kural fonksiyonlarını kullanma
  • Çoklu doğrulama kuralları birleştirme

Örnek

field := Text("age", "Yaş").
    AddValidationRule(Min(18)).
    AddValidationRule(Max(100))

func (*Schema) AllowCustomCurrency

func (s *Schema) AllowCustomCurrency(allow bool) *Schema

AllowCustomCurrency, money field için custom currency girişine izin verip vermeyeceğini ayarlar.

func (*Schema) AsPivot

func (s *Schema) AsPivot() core.Element

AsPivot, alanı pivot field olarak işaretler.

Bu metod, alanın bir pivot tablo alanı olduğunu belirtir. Many-to-many ilişkilerde ara tablodaki ekstra alanlar için kullanılır.

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Rol-izin ilişkisinde izin tarihi
  • Ürün-kategori ilişkisinde sıralama
  • Kullanıcı-grup ilişkisinde katılma tarihi

Örnek

field := DateTime("assigned_at", "Atanma Tarihi").
    AsPivot().
    WithPivotResource("user_roles")

func (*Schema) AutoOptions

func (s *Schema) AutoOptions(displayField string) Element

AutoOptions, alan için otomatik seçenek yükleme ayarlar.

Bu metod, ilişkili model'den otomatik olarak seçeneklerin yüklenmesini sağlar. BelongsTo, HasOne gibi ilişki alanları için kullanılır.

Parametreler

  • displayField: Seçeneklerde gösterilecek alan adı

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • İlişkili model seçenekleri
  • Dinamik seçenek listeleri
  • Veritabanından seçenek yükleme

Örnek

field := BelongsTo("category_id", "Kategori").AutoOptions("name")

func (*Schema) CanSee

func (s *Schema) CanSee(fn VisibilityFunc) Element

CanSee, alan için görünürlük callback'i ayarlar.

Bu metod, alanın dinamik olarak gösterilip gizlenmesini sağlar. Callback, kullanıcı izinlerine, rol'lere veya diğer koşullara göre çalışabilir.

Parametreler

  • fn: Görünürlük kontrolü yapan fonksiyon

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • İzin tabanlı görünürlük
  • Rol tabanlı görünürlük
  • Koşullu alan gösterimi
  • Dinamik form yapıları

Örnek

field := Text("salary", "Maaş").CanSee(func(ctx *core.ResourceContext) bool {
    return ctx.User.IsAdmin()
})

func (*Schema) CreationRules

func (s *Schema) CreationRules(rules ...interface{}) core.Element

func (*Schema) Currencies

func (s *Schema) Currencies(currencies ...Currency) *Schema

Currencies, money field için izin verilen para birimi enum listesini ayarlar.

func (*Schema) Currency

func (s *Schema) Currency(currency string) *Schema

Currency, money field için para birimi kodunu ayarlar (örn: "USD", "TRY").

func (*Schema) CurrencyEnum

func (s *Schema) CurrencyEnum(currency Currency) *Schema

CurrencyEnum, money field için para birimini enum ile ayarlar.

func (*Schema) CustomCurrencies

func (s *Schema) CustomCurrencies(currencies ...string) *Schema

CustomCurrencies, money field için ek özel para birimi kodları tanımlar.

func (*Schema) Default

func (s *Schema) Default(value interface{}) Element

Default, alan için varsayılan değer ayarlar.

Bu metod, alanın başlangıç değerini belirler. Form ilk açıldığında bu değer gösterilir.

Parametreler

  • value: Varsayılan değer

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Form başlangıç değerleri
  • Önerilen değerler
  • Varsayılan seçimler

Örnek

field := Select("status", "Durum").Default("active")

func (*Schema) DependsOn

func (s *Schema) DependsOn(fields ...string) core.Element

DependsOn, alanın bağımlı olduğu diğer alanları belirtir.

Bu metod, alanın görünürlüğünün veya davranışının diğer alanlara bağlı olduğunu belirtir. Bağımlı alanlar değiştiğinde, bu alan da güncellenir.

Parametreler

  • fields: Bağımlı olunan alan adları (variadic)

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Cascade seçim alanları (ülke -> şehir -> ilçe)
  • Koşullu alan gösterimi
  • Dinamik form yapıları
  • İlişkili alan güncellemeleri

Örnek

field := Select("city", "Şehir").
    DependsOn("country").
    When("country", "=", "TR")

func (*Schema) Disabled

func (s *Schema) Disabled() Element

Disabled, alanı devre dışı bırakır.

Devre dışı alanlar, kullanıcı tarafından ne düzenlenebilir ne de etkileşime girebilir. ReadOnly'den farklı olarak, görsel olarak da devre dışı görünür.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

ReadOnly vs Disabled

  • **ReadOnly**: Görüntülenebilir, kopyalanabilir, ancak düzenlenemez
  • **Disabled**: Tamamen etkileşimsiz, genellikle gri/soluk görünür

Kullanım Senaryoları

  • Koşullu olarak devre dışı bırakılan alanlar
  • İzin kontrolü gerektiren alanlar
  • Bağımlı alanlar (başka bir alan seçilene kadar)

Örnek

field := Select("city", "Şehir").Disabled()

func (*Schema) Display

func (s *Schema) Display(fn interface{}) core.Element

Display, alan için özel görüntüleme callback'i ayarlar.

Bu metod, alanın değerinin nasıl görüntüleneceğini özelleştirmeye olanak tanır. Callback, alan değerini ve ilgili kaydı alır; görüntülenecek değeri döner.

Parametreler

  • fn: Görüntüleme işlemini yapan fonksiyon. Desteklenen imzalar:
  • func(value interface{}) string
  • func(value interface{}) interface{}
  • func(value interface{}, item interface{}) string
  • func(value interface{}, item interface{}) interface{}

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Tarih formatı özelleştirme
  • Para birimi formatı
  • Boolean değerleri metin olarak gösterme
  • Enum değerlerini açıklayıcı metne çevirme

Örnek

field := Boolean("is_active", "Aktif").Display(func(value interface{}, item interface{}) interface{} {
    if value.(bool) {
        return "Aktif ✓"
    }
    return "Pasif ✗"
})

func (*Schema) DisplayAs

func (s *Schema) DisplayAs(format string) core.Element

DisplayAs, alan için görüntüleme format string'i ayarlar.

Bu metod, alanın değerinin belirli bir formatta görüntülenmesini sağlar. Format string'i, frontend tarafından yorumlanır.

Parametreler

  • format: Görüntüleme format string'i

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Tarih formatı belirleme ("DD/MM/YYYY")
  • Para birimi formatı ("$0,0.00")
  • Yüzde formatı ("%0.2f")

Örnek

field := Number("price", "Fiyat").DisplayAs("$0,0.00")

func (*Schema) DisplayUsingLabels

func (s *Schema) DisplayUsingLabels() core.Element

DisplayUsingLabels, alanın etiketler kullanarak görüntüleneceğini belirtir.

Bu metod, select, radio gibi seçim alanlarında değer yerine etiketin gösterilmesini sağlar. Örneğin, "1" yerine "Aktif" gösterilir.

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Select alanlarında etiket gösterimi
  • Enum değerlerinin açıklayıcı gösterimi
  • İlişkili kayıtların isim gösterimi

Örnek

field := Select("status", "Durum").
    Options([]map[string]interface{}{
        {"value": 1, "label": "Aktif"},
        {"value": 0, "label": "Pasif"},
    }).
    DisplayUsingLabels()

func (*Schema) Email

func (s *Schema) Email() core.Element

Email, e-posta doğrulama kuralı ekler.

Bu metod, alanın geçerli bir e-posta adresi içermesini zorunlu kılar. RFC 5322 standardına göre e-posta formatı kontrol edilir.

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Doğrulama Kuralları

  • @ işareti içermeli
  • Geçerli domain formatı
  • Geçerli local part formatı

Kullanım Senaryoları

  • Kullanıcı kayıt formları
  • İletişim formları
  • Profil güncelleme formları

Örnek

field := Text("email", "E-posta").Required().Email()

func (*Schema) Exists

func (s *Schema) Exists(table, column string) core.Element

Exists, varlık doğrulama kuralı ekler.

Bu metod, alanın değerinin belirtilen tabloda mevcut olmasını zorunlu kılar. Foreign key ilişkileri için kullanılır.

Parametreler

  • table: Kontrol edilecek tablo adı
  • column: Kontrol edilecek sütun adı

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Foreign key doğrulama
  • İlişkili kayıt kontrolü
  • Referans doğrulama

Önemli Notlar

  • Silinen kayıtlar (soft delete) için dikkatli kullanılmalı
  • Performans için veritabanı indeksi önerilir
  • NULL değerler için ayrıca Nullable() kullanılmalı

Örnek

field := BelongsTo("category_id", "Kategori").
    Required().
    Exists("categories", "id")

func (*Schema) Extract

func (s *Schema) Extract(resource interface{})

Extract, verilen resource'dan veri çıkarır ve alanı doldurur.

Bu metod, reflection kullanarak resource'dan alan değerini çıkarır. Resource bir struct veya map olabilir. Struct için, alan adı veya JSON tag'i kullanılarak field bulunur. Map için, key kullanılarak değer alınır.

Özel Durumlar

  • **ID Suffix Uyumsuzluğu**: "author_id" gibi bir key için, önce "AuthorId" aranır, bulunamazsa "AuthorID" aranır (Go naming convention)
  • **JSON Tag Desteği**: Struct field'ları JSON tag'leri ile de eşleştirilebilir
  • **Nil Güvenliği**: Resource nil ise hiçbir işlem yapılmaz

Parametreler:

  • resource: Veri çıkarılacak kaynak (struct veya map)

Örnek:

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

user := &User{Name: "John", Email: "[email protected]"}
schema := &Schema{Key: "name"}
schema.Extract(user)
// schema.Data artık "John" değerini içerir

func (*Schema) Fields

func (s *Schema) Fields(fields ...core.Element) core.Element

Fields, repeater için alt alanları ayarlar.

Bu metod, tekrarlayan grup içindeki alanları belirler. Her tekrar, bu alanların bir kopyasını içerir.

Parametreler

  • fields: Tekrarlayan alan listesi (variadic)

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Telefon numaraları listesi
  • E-posta adresleri listesi
  • Ürün varyantları
  • Adres bilgileri

Örnek

field := Repeater("phones", "Telefon Numaraları").
    Fields(
        Text("number", "Numara").Required(),
        Select("type", "Tip").Options([]string{"Ev", "İş", "Mobil"}),
    ).
    MinRepeats(1).
    MaxRepeats(5)

func (*Schema) Filterable

func (s *Schema) Filterable() Element

Filterable, alanın filtrelenebilir olduğunu belirtir.

Filterable alanlar, liste görünümünde filtre seçenekleri sunar. Kullanıcılar bu alana göre kayıtları filtreleyebilir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Durum alanları (aktif/pasif)
  • Kategori alanları
  • Tarih aralıkları
  • Sayısal aralıklar

Örnek

field := Select("status", "Durum").Filterable()

func (*Schema) GetAcceptedMimeTypes

func (s *Schema) GetAcceptedMimeTypes() []string

GetAcceptedMimeTypes, kabul edilen MIME tiplerini döner.

Döndürür

  • []string: Kabul edilen MIME tipleri listesi (boş slice olabilir)

Örnek

mimeTypes := field.GetAcceptedMimeTypes()
for _, mime := range mimeTypes {
    fmt.Println("Accepted:", mime)
}

func (*Schema) GetAutoCompleteURL

func (s *Schema) GetAutoCompleteURL() string

GetAutoCompleteURL, otomatik tamamlama URL'ini döner.

Döndürür

  • string: Autocomplete API endpoint'i

func (*Schema) GetAutoOptionsConfig

func (s *Schema) GetAutoOptionsConfig() core.AutoOptionsConfig

GetAutoOptionsConfig, alanın auto options yapılandırmasını döner.

Döndürür

  • core.AutoOptionsConfig: Auto options yapılandırması

func (*Schema) GetBadgeVariant

func (s *Schema) GetBadgeVariant() string

GetBadgeVariant, badge varyantını döner.

Döndürür

  • string: Badge varyantı (örn. "solid", "outline")

func (*Schema) GetContext

func (s *Schema) GetContext() ElementContext

GetContext, alanın görüntülendiği bağlamı döndürür. Bağlam, alanın nerede gösterilmesi gerektiğini belirtir (form, list, detail).

Döndürür:

  • Görüntüleme bağlamı (ElementContext)

func (*Schema) GetCreationValidationRules

func (s *Schema) GetCreationValidationRules() []interface{}

func (*Schema) GetCustomValidators

func (s *Schema) GetCustomValidators() []interface{}

GetCustomValidators, özel doğrulayıcı fonksiyonlarını döner.

Döndürür

  • []interface{}: Özel doğrulayıcı fonksiyonları listesi

Örnek

validators := field.GetCustomValidators()
for _, validator := range validators {
    // Doğrulayıcıyı çalıştır
}

func (*Schema) GetDependencies

func (s *Schema) GetDependencies() []string

GetDependencies, alanın bağımlı olduğu diğer alanların listesini döner.

Bu metod, Props içindeki "dependencies" anahtarını kontrol eder. Bağımlılık yönetimi için kullanılır.

Döndürür

  • []string: Bağımlı alan adları listesi (boş slice olabilir)

Kullanım Senaryoları

  • Dinamik form alanları
  • Koşullu alan gösterimi
  • Cascade seçim alanları
  • Bağımlılık grafiği oluşturma

Örnek

deps := field.GetDependencies()
for _, dep := range deps {
    // Bağımlı alanı kontrol et
}

func (*Schema) GetDependencyCallback

func (s *Schema) GetDependencyCallback(context string) DependencyCallbackFunc

GetDependencyCallback, bağlama göre uygun callback'i döner.

Bu metod, verilen bağlama (create/update) göre uygun callback fonksiyonunu döner. Bağlama özel callback yoksa, genel callback döner.

Parametreler

  • context: Bağlam string'i ("create" veya "update")

Döndürür

  • DependencyCallbackFunc: Uygun callback fonksiyonu (nil olabilir)

Örnek

callback := field.GetDependencyCallback("create")
if callback != nil {
    result := callback(dependencies, ctx)
}

func (*Schema) GetDependencyRules

func (s *Schema) GetDependencyRules() map[string]interface{}

GetDependencyRules, bağımlılık kurallarını döner.

Döndürür

  • map[string]interface{}: Bağımlılık kuralları map'i (boş map olabilir)

Örnek

rules := field.GetDependencyRules()
for field, rule := range rules {
    fmt.Printf("Field %s has rule: %v\n", field, rule)
}

func (*Schema) GetDisplayCallback

func (s *Schema) GetDisplayCallback() func(value interface{}, item interface{}) interface{}

GetDisplayCallback, görüntüleme callback fonksiyonunu döner.

Döndürür

  • func(value interface{}, item interface{}) interface{}: Display callback fonksiyonu (nil olabilir)

Örnek

callback := field.GetDisplayCallback()
if callback != nil {
    displayValue := callback(value, item)
}

func (*Schema) GetDisplayedAs

func (s *Schema) GetDisplayedAs() string

GetDisplayedAs, görüntüleme format string'ini döner.

Döndürür

  • string: Format string'i

func (*Schema) GetEditorLanguage

func (s *Schema) GetEditorLanguage() string

GetEditorLanguage, editör dilini döner.

Döndürür

  • string: Dil kodu (örn. "tr", "en")

func (*Schema) GetEditorTheme

func (s *Schema) GetEditorTheme() string

GetEditorTheme, editör temasını döner.

Döndürür

  • string: Tema adı (örn. "modern", "dark")

func (*Schema) GetEditorType

func (s *Schema) GetEditorType() string

GetEditorType, editör tipini döner.

Döndürür

  • string: Editör tipi (örn. "tinymce", "quill", "ckeditor")

func (*Schema) GetGormConfig

func (s *Schema) GetGormConfig() *GormConfig

GetGormConfig, alanın GORM yapılandırmasını döner.

func (*Schema) GetKey

func (s *Schema) GetKey() string

GetKey, alanın benzersiz tanımlayıcısını döndürür. Key, alanı resource model'indeki bir field'a eşlemek için kullanılır.

Döndürür:

  • Alanın benzersiz tanımlayıcısı (key)

func (*Schema) GetMaxFileSize

func (s *Schema) GetMaxFileSize() int64

GetMaxFileSize, maksimum dosya boyutunu döner.

Döndürür

  • int64: Maksimum dosya boyutu (byte cinsinden)

Örnek

maxSize := field.GetMaxFileSize()
fmt.Printf("Max size: %d MB\n", maxSize/(1024*1024))

func (*Schema) GetMaxRepeats

func (s *Schema) GetMaxRepeats() int

GetMaxRepeats, maksimum tekrar sayısını döner.

Döndürür

  • int: Maksimum tekrar sayısı

func (*Schema) GetMetadata

func (s *Schema) GetMetadata() map[string]interface{}

GetMetadata, alan hakkında metadata bilgilerini döner.

Bu metod, alanın tüm özelliklerini içeren bir map döner. API yanıtları, debugging ve introspection için kullanılır.

Döndürür

  • map[string]interface{}: Alan metadata'sı

İçerilen Bilgiler

  • name: Görünen ad
  • key: Benzersiz tanımlayıcı
  • view: Frontend bileşeni
  • type: Veri tipi
  • context: Görüntüleme bağlamı
  • read_only: Salt okunur durumu
  • disabled: Devre dışı durumu
  • immutable: Değiştirilemez durumu
  • required: Zorunlu durumu
  • nullable: Boş bırakılabilir durumu
  • filterable: Filtrelenebilir durumu
  • sortable: Sıralanabilir durumu
  • searchable: Aranabilir durumu
  • stacked: Yığılmış durumu
  • text_align: Metin hizalama
  • dependencies: Bağımlılıklar
  • props: Ekstra özellikler

Örnek

metadata := field.GetMetadata()
fmt.Printf("Field: %s, Type: %s\n", metadata["name"], metadata["type"])

func (*Schema) GetMinCharsForSuggestions

func (s *Schema) GetMinCharsForSuggestions() int

GetMinCharsForSuggestions, öneri için minimum karakter sayısını döner.

Döndürür

  • int: Minimum karakter sayısı

func (*Schema) GetMinRepeats

func (s *Schema) GetMinRepeats() int

GetMinRepeats, minimum tekrar sayısını döner.

Döndürür

  • int: Minimum tekrar sayısı

func (*Schema) GetModifyCallback

func (s *Schema) GetModifyCallback() func(value interface{}, c *fiber.Ctx) interface{}

GetModifyCallback, alanın modify callback'ini döner.

Döndürür

  • func: Modify callback fonksiyonu (nil olabilir)

func (*Schema) GetName

func (s *Schema) GetName() string

GetName, bu element'in görünen adını döndürür.

Name, element'in kullanıcı arayüzünde gösterilecek insan okunabilir adıdır. Genellikle form label'ı veya tablo başlığı olarak kullanılır.

Döndürür:

  • Element'in görünen adı (örn: "Name", "Email", "Author")

Örnek:

field := fields.Text("Name", "name")
name := field.GetName() // "Name"

func (*Schema) GetPivotResourceName

func (s *Schema) GetPivotResourceName() string

GetPivotResourceName, pivot resource adını döner.

Döndürür

  • string: Pivot resource adı

func (*Schema) GetRepeaterFields

func (s *Schema) GetRepeaterFields() []Element

GetRepeaterFields, repeater alt alanlarını döner.

Döndürür

  • []Element: Alt alan listesi

Örnek

fields := field.GetRepeaterFields()
for _, f := range fields {
    fmt.Println(f.GetKey())
}

func (*Schema) GetResolveCallback

func (s *Schema) GetResolveCallback() func(value interface{}, item interface{}, c *fiber.Ctx) interface{}

GetResolveCallback, alanın resolve callback'ini döner.

Döndürür

  • func: Resolve callback fonksiyonu (nil olabilir)

func (*Schema) GetResolveHandle

func (s *Schema) GetResolveHandle() string

GetResolveHandle, resolve handle değerini döner.

Bu metod, client-side bileşen etkileşimi için kullanılan handle'ı döner.

Döndürür

  • string: Resolve handle değeri

Örnek

handle := field.GetResolveHandle()
if handle != "" {
    // Handle'ı kullan
}

func (*Schema) GetStatusColors

func (s *Schema) GetStatusColors() map[string]string

GetStatusColors, durum renk eşleştirmesini döner.

Döndürür

  • map[string]string: Durum-renk eşleştirme map'i (boş map olabilir)

Örnek

colors := field.GetStatusColors()
if color, ok := colors["active"]; ok {
    fmt.Println("Active color:", color)
}

func (*Schema) GetStorageCallback

func (s *Schema) GetStorageCallback() StorageCallbackFunc

GetStorageCallback, alanın depolama callback'ini döner.

Döndürür

  • StorageCallbackFunc: Depolama callback fonksiyonu (nil olabilir)

func (*Schema) GetStorageDisk

func (s *Schema) GetStorageDisk() string

GetStorageDisk, depolama disk adını döner.

Döndürür

  • string: Depolama disk adı (örn. "local", "s3", "gcs")

Örnek

disk := field.GetStorageDisk()

func (*Schema) GetStoragePath

func (s *Schema) GetStoragePath() string

GetStoragePath, depolama yolunu döner.

Döndürür

  • string: Depolama yolu (örn. "uploads/avatars")

Örnek

path := field.GetStoragePath()

func (*Schema) GetSuggestions

func (s *Schema) GetSuggestions(query string) []interface{}

GetSuggestions, verilen sorgu için önerileri döner.

Bu metod, SuggestionsCallback varsa onu çağırır, yoksa mevcut Suggestions listesini döner.

Parametreler

  • query: Arama sorgusu

Döndürür

  • []interface{}: Öneri listesi

Örnek

suggestions := field.GetSuggestions("john")
for _, s := range suggestions {
    fmt.Println(s)
}

func (*Schema) GetSuggestionsCallback

func (s *Schema) GetSuggestionsCallback() func(string) []interface{}

GetSuggestionsCallback, öneri callback fonksiyonunu döner.

Döndürür

  • func(string) []interface{}: Suggestions callback fonksiyonu (nil olabilir)

Örnek

callback := field.GetSuggestionsCallback()
if callback != nil {
    suggestions := callback("query")
}

func (*Schema) GetType

func (s *Schema) GetType() core.ElementType

GetType, bu element'in veri tipini döndürür.

Type, element'in veri tipini belirler ve validation, formatting ve OpenAPI schema oluşturma için kullanılır. Örneğin: TYPE_TEXT, TYPE_NUMBER, TYPE_BOOLEAN, TYPE_DATE

Döndürür:

  • Element'in veri tipi (core.ElementType)

Örnek:

field := fields.Text("Name", "name")
fieldType := field.GetType() // core.TYPE_TEXT

func (*Schema) GetUpdateValidationRules

func (s *Schema) GetUpdateValidationRules() []interface{}

func (*Schema) GetUploadCallback

func (s *Schema) GetUploadCallback() func(interface{}, interface{}) error

GetUploadCallback, dosya yükleme callback fonksiyonunu döner.

Döndürür

  • func: Upload callback fonksiyonu (nil olabilir)

Örnek

callback := field.GetUploadCallback()
if callback != nil {
    err := callback(file, item)
}

func (*Schema) GetValidationRules

func (s *Schema) GetValidationRules() []interface{}

GetValidationRules, doğrulama kurallarını döner.

Döndürür

  • []interface{}: Doğrulama kuralları listesi

Örnek

rules := field.GetValidationRules()
for _, rule := range rules {
    // Kuralı uygula
}

func (*Schema) GetView

func (s *Schema) GetView() string

GetView, alanın görünüm tipini döndürür. View tipi, alanın UI'da nasıl render edileceğini belirler.

Döndürür:

  • Görünüm tipi (örn. "text-field", "email-field", "select-field")

func (*Schema) Gorm

func (s *Schema) Gorm(config *GormConfig) Element

Gorm, alan için GORM veritabanı yapılandırmasını ayarlar. Bu metod, migration ve model oluşturma için kullanılır.

func (*Schema) GormAutoIncrement

func (s *Schema) GormAutoIncrement() Element

GormAutoIncrement, alanı otomatik artış olarak işaretler.

func (*Schema) GormComment

func (s *Schema) GormComment(comment string) Element

GormComment, alan için veritabanı yorumu ekler.

func (*Schema) GormDefault

func (s *Schema) GormDefault(value interface{}) Element

GormDefault, alan için varsayılan değer belirler.

func (*Schema) GormForeignKey

func (s *Schema) GormForeignKey(fk, references string) Element

GormForeignKey, alan için foreign key ilişkisi tanımlar.

func (*Schema) GormFullTextIndex

func (s *Schema) GormFullTextIndex(name ...string) Element

GormFullTextIndex, alan için fulltext indeks oluşturur.

func (*Schema) GormIndex

func (s *Schema) GormIndex(name ...string) Element

GormIndex, alan için indeks oluşturur.

func (*Schema) GormOnDelete

func (s *Schema) GormOnDelete(action string) Element

GormOnDelete, foreign key için ON DELETE davranışını belirler.

func (*Schema) GormOnUpdate

func (s *Schema) GormOnUpdate(action string) Element

GormOnUpdate, foreign key için ON UPDATE davranışını belirler.

func (*Schema) GormPrimaryKey

func (s *Schema) GormPrimaryKey() Element

GormPrimaryKey, alanı birincil anahtar olarak işaretler.

func (*Schema) GormSize

func (s *Schema) GormSize(size int) Element

GormSize, alan için sütun boyutunu belirler.

func (*Schema) GormSnowflake

func (s *Schema) GormSnowflake() Element

GormSnowflake, Snowflake tipinde ID kullanır.

func (*Schema) GormSoftDelete

func (s *Schema) GormSoftDelete() Element

GormSoftDelete, alan için soft delete desteği ekler.

func (*Schema) GormType

func (s *Schema) GormType(sqlType string) Element

GormType, alan için SQL tipini belirler.

func (*Schema) GormULID

func (s *Schema) GormULID() Element

GormULID, ULID tipinde ID kullanır.

func (*Schema) GormUUID

func (s *Schema) GormUUID() Element

GormUUID, UUID tipinde ID kullanır.

func (*Schema) GormUniqueIndex

func (s *Schema) GormUniqueIndex(name ...string) Element

GormUniqueIndex, alan için benzersiz indeks oluşturur.

func (*Schema) HasGormConfig

func (s *Schema) HasGormConfig() bool

HasGormConfig, alanın GORM yapılandırması olup olmadığını kontrol eder.

func (*Schema) HelpText

func (s *Schema) HelpText(helpText string) Element

HelpText, alan için yardım metni ayarlar.

HelpText, alanın altında gösterilen açıklayıcı veya yönlendirici metindir. Kullanıcıya alan hakkında ek bilgi verir.

Parametreler

  • helpText: Yardım metni

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Format açıklaması (örn. "DD/MM/YYYY formatında")
  • Karakter limiti bilgisi
  • Güvenlik uyarıları
  • Kullanım önerileri

Örnek

field := Password("password", "Şifre").
    HelpText("En az 8 karakter, bir büyük harf ve bir rakam içermelidir")

func (*Schema) HideNumberControls

func (s *Schema) HideNumberControls() Element

HideNumberControls, number input alanındaki artı/eksi butonlarını gizler.

Bu metod ShowNumberControls(false) için kısa yoldur.

func (*Schema) HideOnApi

func (s *Schema) HideOnApi() Element

HideOnApi, alanı external API yanıtlarında gizler.

Bu metod, alanın external API çıktısında yer almamasını sağlar.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Text("secret", "secret").HideOnApi()

func (*Schema) HideOnCreate

func (s *Schema) HideOnCreate() Element

HideOnCreate, alanı oluşturma formunda gizler.

Bu metod, alanın yeni kayıt oluşturma formunda gizlenmesini sağlar. Genellikle otomatik oluşturulan alanlar (ID, timestamps) için kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Text("id", "ID").HideOnCreate()

func (*Schema) HideOnDetail

func (s *Schema) HideOnDetail() Element

HideOnDetail, alanı detay görünümünde gizler.

Bu metod, alanın kayıt detay sayfasında gizlenmesini sağlar. Genellikle sadece form için gerekli olan alanlar için kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Password("password", "Şifre").HideOnDetail()

func (*Schema) HideOnGrid

func (s *Schema) HideOnGrid() Element

HideOnGrid, alanı grid görünümünde gizler.

func (*Schema) HideOnList

func (s *Schema) HideOnList() Element

HideOnList, alanı liste görünümünde gizler.

Bu metod, alanın tablo/liste görünümünde gizlenmesini sağlar. Genellikle uzun metinler veya hassas bilgiler için kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Textarea("bio", "Biyografi").HideOnList()

func (*Schema) HideOnUpdate

func (s *Schema) HideOnUpdate() Element

HideOnUpdate, alanı güncelleme formunda gizler.

Bu metod, alanın kayıt güncelleme formunda gizlenmesini sağlar. Genellikle değiştirilmemesi gereken alanlar için kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Text("username", "Kullanıcı Adı").HideOnUpdate()

func (*Schema) Immutable

func (s *Schema) Immutable() Element

Immutable, alanı değiştirilemez olarak işaretler.

Immutable alanlar, oluşturulduktan sonra asla değiştirilemez. Genellikle oluşturma formunda gösterilir, güncelleme formunda gizlenir veya salt okunur olur.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Kullanıcı adı (username)
  • E-posta adresi (bazı sistemlerde)
  • Benzersiz tanımlayıcılar
  • Kayıt oluşturma zamanı

Örnek

field := Text("username", "Kullanıcı Adı").Immutable()

func (*Schema) IsConditionallyVisible

func (s *Schema) IsConditionallyVisible(item interface{}) bool

IsConditionallyVisible, alanın kayıt değerlerine göre görünür olup olmadığını belirler.

Bu metod, VisibilityCallback varsa onu çağırır, yoksa true döner. Dinamik görünürlük kontrolü için kullanılır.

Parametreler

  • item: Kontrol edilecek kayıt

Döndürür

  • bool: Alanın görünür olup olmadığı

Kullanım Senaryoları

  • Kayıt durumuna göre alan gösterimi
  • Kullanıcı rolüne göre alan gösterimi
  • Değer bazlı koşullu görünürlük

Örnek

if field.IsConditionallyVisible(user) {
    // Alanı göster
}

func (*Schema) IsHidden

func (s *Schema) IsHidden(ctx VisibilityContext) bool

IsHidden, alanın belirli bir görünürlük bağlamında gizli olup olmadığını kontrol eder.

Bu metod, IsVisibleInContext metodunun tersini döner. Görünürlük kontrolü için kullanılır.

Parametreler

  • ctx: Görünürlük bağlamı (ContextIndex, ContextDetail, ContextCreate, ContextUpdate, ContextPreview)

Döndürür

  • bool: Alanın gizli olup olmadığı

Kullanım Senaryoları

  • Koşullu alan gösterimi
  • Bağlam bazlı görünürlük kontrolü
  • Form ve liste filtreleme

Örnek

if field.IsHidden(ContextCreate) {
    // Alanı oluşturma formunda gösterme
}

func (*Schema) IsPivot

func (s *Schema) IsPivot() bool

IsPivot, alanın pivot field olup olmadığını kontrol eder.

Döndürür

  • bool: Pivot field ise true

Örnek

if field.IsPivot() {
    resource := field.GetPivotResourceName()
}

func (*Schema) IsRepeaterField

func (s *Schema) IsRepeaterField() bool

IsRepeaterField, alanın bir repeater field olup olmadığını kontrol eder.

Döndürür

  • bool: Repeater field ise true

Örnek

if field.IsRepeaterField() {
    fields := field.GetRepeaterFields()
}

func (*Schema) IsSearchable

func (s *Schema) IsSearchable() bool

IsSearchable, alanın aranabilir olup olmadığını kontrol eder.

Döndürür

  • bool: Alanın aranabilir olup olmadığı

Örnek

if field.IsSearchable() {
    // Arama sorgusu oluştur
}

func (*Schema) IsVisible

func (s *Schema) IsVisible(ctx *core.ResourceContext) bool

IsVisible, alanın belirli bir bağlamda görünür olup olmadığını kontrol eder.

Bu metod, VisibilityCallback varsa onu çağırır, yoksa true döner. Dinamik görünürlük kontrolü için kullanılır.

Parametreler

  • ctx: Resource bağlamı (kullanıcı, izinler, vb.)

Döndürür

  • bool: Alanın görünür olup olmadığı

Örnek

if field.IsVisible(ctx) {
    // Alanı göster
}

func (*Schema) IsVisibleInContext

func (s *Schema) IsVisibleInContext(ctx VisibilityContext) bool

IsVisibleInContext, alanın belirli bir bağlamda görünür olup olmadığını kontrol eder.

Bu metod, ElementContext değerlerine göre görünürlük kontrolü yapar. Her bağlam için farklı kurallar uygulanır.

Parametreler

  • ctx: Görünürlük bağlamı

Döndürür

  • bool: Alanın görünür olup olmadığı

Bağlam Kuralları

**ContextIndex (Liste Görünümü)**:

  • HIDE_ON_LIST ise gizli
  • ONLY_ON_DETAIL ise gizli
  • ONLY_ON_FORM ise gizli
  • Diğer durumlarda görünür

**ContextDetail (Detay Görünümü)**:

  • HIDE_ON_DETAIL ise gizli
  • ONLY_ON_LIST ise gizli
  • ONLY_ON_FORM ise gizli
  • Diğer durumlarda görünür

**ContextCreate (Oluşturma Formu)**:

  • HIDE_ON_CREATE ise gizli
  • ONLY_ON_UPDATE ise gizli
  • ONLY_ON_LIST ise gizli
  • ONLY_ON_DETAIL ise gizli
  • Diğer durumlarda görünür

**ContextUpdate (Güncelleme Formu)**:

  • HIDE_ON_UPDATE ise gizli
  • ONLY_ON_CREATE ise gizli
  • ONLY_ON_LIST ise gizli
  • ONLY_ON_DETAIL ise gizli
  • Diğer durumlarda görünür

**ContextPreview (Önizleme)**:

  • HIDE_ON_DETAIL ise gizli
  • ONLY_ON_LIST ise gizli
  • ONLY_ON_FORM ise gizli
  • Diğer durumlarda görünür

Örnek

if field.IsVisibleInContext(ContextCreate) {
    // Alanı oluşturma formunda göster
}

func (*Schema) JsonSerialize

func (s *Schema) JsonSerialize() map[string]interface{}

JsonSerialize, alanı JSON uyumlu bir map'e serileştirir.

Bu metod, alanın tüm özelliklerini JSON encoding için hazır bir map'e dönüştürür. Frontend'e gönderilmek üzere alanın durumunu temsil eder.

Serileştirilen Özellikler

- **view**: Görünüm tipi (frontend bileşeni) - **type**: Veri tipi (ElementType) - **key**: Benzersiz tanımlayıcı - **name**: Görünen ad - **data**: Alan değeri - **props**: Ekstra özellikler - **context**: Görüntüleme bağlamı - **placeholder**: Yer tutucu metni - **label**: Etiket metni - **help_text**: Yardım metni - **read_only**: Salt okunur durumu - **disabled**: Devre dışı durumu - **required**: Zorunlu durumu - **nullable**: Boş bırakılabilir durumu - **sortable**: Sıralanabilir durumu - **filterable**: Filtrelenebilir durumu - **stacked**: Yığılmış (tam genişlik) durumu - **text_align**: Metin hizalama

Döndürür:

  • JSON encoding için hazır map[string]any

Örnek:

schema := &Schema{Key: "email", Name: "E-posta", View: "email-field"}
json := schema.JsonSerialize()
// json["key"] == "email"
// json["name"] == "E-posta"
// json["view"] == "email-field"

func (*Schema) Label

func (s *Schema) Label(label string) Element

Label, alan için etiket metni ayarlar.

Label, alanın yanında veya üstünde gösterilen açıklayıcı metindir. Name'den farklı olarak, daha uzun ve açıklayıcı olabilir.

Parametreler

  • label: Etiket metni

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Name vs Label

  • **Name**: Kısa, genel başlık (örn. "E-posta")
  • **Label**: Daha açıklayıcı (örn. "İş E-posta Adresiniz")

Örnek

field := Text("email", "E-posta").
    Label("Lütfen geçerli bir e-posta adresi girin")

func (*Schema) MarkRemoveEXIFData

func (s *Schema) MarkRemoveEXIFData() core.Element

MarkRemoveEXIFData, EXIF verilerinin kaldırılacağını belirtir.

Bu metod, yüklenen resimlerdeki EXIF metadata'sının (konum, kamera bilgisi, vb.) otomatik olarak kaldırılmasını sağlar. Gizlilik için önemlidir.

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

EXIF Verileri

  • GPS koordinatları
  • Kamera modeli
  • Çekim tarihi
  • Kamera ayarları

Kullanım Senaryoları

  • Gizlilik koruması
  • Güvenlik
  • Dosya boyutu azaltma

Örnek

field := File("photo", "Fotoğraf").
    Accept("image/jpeg", "image/png").
    MarkRemoveEXIFData()

func (*Schema) Mask

func (s *Schema) Mask(mask string) *Schema

Mask, input mask desenini ayarlar.

func (*Schema) MaskChar

func (s *Schema) MaskChar(maskChar string) *Schema

MaskChar, input mask'te boş karakter yer tutucusunu ayarlar.

func (*Schema) Max

func (s *Schema) Max(max interface{}) core.Element

Max, maksimum değer doğrulama kuralı ekler.

Bu metod, alanın belirtilen maksimum değerden küçük veya eşit olmasını zorunlu kılar. Sayısal alanlar için maksimum değer, string alanlar için maksimum uzunluk kontrolü yapar.

Parametreler

  • max: Maksimum değer (int, float64, string uzunluğu)

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Yaş kontrolü (max 100)
  • Fiyat kontrolü (max 999999)
  • Miktar kontrolü (max 1000)
  • String uzunluk kontrolü

Örnek

field := Number("quantity", "Miktar").Min(1).Max(1000)

func (*Schema) MaxLength

func (s *Schema) MaxLength(length int) core.Element

MaxLength, maksimum uzunluk doğrulama kuralı ekler.

Bu metod, string alanların belirtilen maksimum karakter sayısını aşmamasını zorunlu kılar. Boşluklar da karakter olarak sayılır.

Parametreler

  • length: Maksimum karakter sayısı

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Başlık uzunluğu (max 255 karakter)
  • Açıklama uzunluğu (max 1000 karakter)
  • Kullanıcı adı uzunluğu (max 50 karakter)

Örnek

field := Text("title", "Başlık").MaxLength(255)

func (*Schema) MaxRepeats

func (s *Schema) MaxRepeats(max int) core.Element

MaxRepeats, maksimum tekrar sayısını ayarlar.

Bu metod, repeater'da en fazla kaç tane alan grubu olabileceğini belirler. Kullanıcı bu sayının üstüne çıkamaz.

Parametreler

  • max: Maksimum tekrar sayısı

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Maksimum telefon sayısı sınırı
  • Maksimum adres sayısı sınırı
  • Performans optimizasyonu

Örnek

field := Repeater("emails", "E-posta Adresleri").
    Fields(
        Text("email", "E-posta").Email(),
    ).
    MinRepeats(1).
    MaxRepeats(3)

func (*Schema) MaxSize

func (s *Schema) MaxSize(bytes int64) core.Element

MaxSize, maksimum dosya boyutunu ayarlar.

Bu metod, yüklenebilecek dosyanın maksimum boyutunu byte cinsinden belirler. Daha büyük dosyalar reddedilir.

Parametreler

  • bytes: Maksimum dosya boyutu (byte cinsinden)

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Önerilen Boyutlar

  • Profil fotoğrafı: 2-5 MB
  • Döküman: 10-50 MB
  • Video: 100-500 MB

Boyut Hesaplama

  • 1 KB = 1024 bytes
  • 1 MB = 1024 * 1024 bytes
  • 1 GB = 1024 * 1024 * 1024 bytes

Örnek

field := File("document", "Döküman").
    Accept("application/pdf").
    MaxSize(10 * 1024 * 1024) // 10MB

func (*Schema) Min

func (s *Schema) Min(min interface{}) core.Element

Min, minimum değer doğrulama kuralı ekler.

Bu metod, alanın belirtilen minimum değerden büyük veya eşit olmasını zorunlu kılar. Sayısal alanlar için minimum değer, string alanlar için minimum uzunluk kontrolü yapar.

Parametreler

  • min: Minimum değer (int, float64, string uzunluğu)

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Yaş kontrolü (min 18)
  • Fiyat kontrolü (min 0)
  • Miktar kontrolü (min 1)
  • String uzunluk kontrolü

Örnek

field := Number("age", "Yaş").Min(18).Max(100)

func (*Schema) MinCharsForSuggestions

func (s *Schema) MinCharsForSuggestions(min int) core.Element

MinCharsForSuggestions, öneri gösterimi için minimum karakter sayısı ayarlar.

Bu metod, kullanıcının kaç karakter yazdıktan sonra önerilerin gösterileceğini belirler. Performans optimizasyonu için kullanılır.

Parametreler

  • min: Minimum karakter sayısı

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Önerilen Değerler

  • 1-2: Küçük veri setleri için
  • 3-4: Orta veri setleri için (önerilen)
  • 5+: Büyük veri setleri için

Örnek

field := Text("product", "Ürün").
    WithAutoComplete("/api/products/search").
    MinCharsForSuggestions(3)

func (*Schema) MinLength

func (s *Schema) MinLength(length int) core.Element

MinLength, minimum uzunluk doğrulama kuralı ekler.

Bu metod, string alanların belirtilen minimum karakter sayısına sahip olmasını zorunlu kılar. Boşluklar da karakter olarak sayılır.

Parametreler

  • length: Minimum karakter sayısı

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Şifre uzunluğu (min 8 karakter)
  • Kullanıcı adı uzunluğu (min 3 karakter)
  • Açıklama uzunluğu (min 10 karakter)

Örnek

field := Password("password", "Şifre").MinLength(8).MaxLength(128)

func (*Schema) MinRepeats

func (s *Schema) MinRepeats(min int) core.Element

MinRepeats, minimum tekrar sayısını ayarlar.

Bu metod, repeater'da en az kaç tane alan grubu olması gerektiğini belirler. Kullanıcı bu sayının altına inemez.

Parametreler

  • min: Minimum tekrar sayısı

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • En az bir telefon numarası zorunlu
  • En az bir adres zorunlu
  • Minimum varyant sayısı

Örnek

field := Repeater("addresses", "Adresler").
    Fields(
        Text("street", "Sokak"),
        Text("city", "Şehir"),
    ).
    MinRepeats(1)

func (*Schema) Modify

func (s *Schema) Modify(fn func(value interface{}, c *fiber.Ctx) interface{}) Element

Modify, alan için değer modifikasyon callback'i ayarlar.

Bu metod, alanın değerinin frontend'e gönderilmeden önce değiştirilmesini sağlar. Format dönüşümü, maskeleme, hesaplama gibi işlemler için kullanılır.

Parametreler

  • fn: Değer modifikasyonu yapan fonksiyon

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Tarih formatı dönüşümü
  • Para birimi formatı
  • Hassas veri maskeleme
  • Değer hesaplama

Örnek

field := Text("phone", "Telefon").Modify(func(value interface{}, c *fiber.Ctx) interface{} {
    phone := value.(string)
    return maskPhone(phone) // (555) ***-**-12
})

func (*Schema) Nullable

func (s *Schema) Nullable() Element

Nullable, alanın boş (null) değer alabileceğini belirtir.

Nullable alanlar, veritabanında NULL değer saklayabilir. Varsayılan olarak alanlar nullable değildir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Opsiyonel ilişkiler (foreign key'ler)
  • Opsiyonel tarih alanları
  • Opsiyonel sayısal değerler

Örnek

field := BelongsTo("author", "Yazar").Nullable()

func (*Schema) OnDependencyChange

func (s *Schema) OnDependencyChange(fn DependencyCallbackFunc) core.Element

OnDependencyChange, bağımlı alanlar değiştiğinde çağrılacak callback ayarlar.

Bu metod, bağımlı alanların değeri değiştiğinde özel işlemler yapılmasını sağlar. Hem oluşturma hem de güncelleme bağlamında çalışır.

Parametreler

  • fn: Bağımlılık değişikliği callback fonksiyonu

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Dinamik seçenek yükleme
  • Hesaplanan değerler
  • Koşullu validasyon
  • Alan değeri senkronizasyonu

Örnek

field := Select("city", "Şehir").
    DependsOn("country").
    OnDependencyChange(func(deps map[string]interface{}, ctx *fiber.Ctx) interface{} {
        countryID := deps["country"]
        return loadCitiesByCountry(countryID)
    })

func (*Schema) OnDependencyChangeCreating

func (s *Schema) OnDependencyChangeCreating(fn DependencyCallbackFunc) core.Element

OnDependencyChangeCreating, oluşturma bağlamında bağımlılık callback'i ayarlar.

Bu metod, sadece yeni kayıt oluşturulurken bağımlılık değişikliklerinde çalışır. Güncelleme işlemlerinde çalışmaz.

Parametreler

  • fn: Bağımlılık değişikliği callback fonksiyonu

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Oluşturma sırasında özel davranış
  • İlk değer hesaplama
  • Oluşturma bağlamına özel validasyon

Örnek

field := Text("slug", "Slug").
    DependsOn("title").
    OnDependencyChangeCreating(func(deps map[string]interface{}, ctx *fiber.Ctx) interface{} {
        return generateSlug(deps["title"].(string))
    })

func (*Schema) OnDependencyChangeUpdating

func (s *Schema) OnDependencyChangeUpdating(fn DependencyCallbackFunc) core.Element

OnDependencyChangeUpdating, güncelleme bağlamında bağımlılık callback'i ayarlar.

Bu metod, sadece kayıt güncellenirken bağımlılık değişikliklerinde çalışır. Oluşturma işlemlerinde çalışmaz.

Parametreler

  • fn: Bağımlılık değişikliği callback fonksiyonu

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Güncelleme sırasında özel davranış
  • Değer yeniden hesaplama
  • Güncelleme bağlamına özel validasyon

Örnek

field := DateTime("updated_at", "Güncelleme Tarihi").
    OnDependencyChangeUpdating(func(deps map[string]interface{}, ctx *fiber.Ctx) interface{} {
        return time.Now()
    })

func (*Schema) OnDetail

func (s *Schema) OnDetail() Element

OnDetail, alanı detay görünümünde gösterir.

Bu metod, alanın kayıt detay sayfasında görünür olmasını sağlar. Genellikle tüm alan bilgileri için kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Text("description", "Açıklama").OnDetail()

func (*Schema) OnForm

func (s *Schema) OnForm() Element

OnForm, alanı form görünümünde gösterir.

Bu metod, alanın hem oluşturma hem de güncelleme formlarında görünür olmasını sağlar. Kullanıcının düzenleyebileceği alanlar için kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Text("email", "E-posta").OnForm()

func (*Schema) OnList

func (s *Schema) OnList() Element

OnList, alanı liste görünümünde gösterir.

Bu metod, alanın tablo/liste görünümünde görünür olmasını sağlar. Genellikle özet bilgiler için kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Text("name", "İsim").OnList()

func (*Schema) OnlyOnCreate

func (s *Schema) OnlyOnCreate() Element

OnlyOnCreate, alanı sadece oluşturma formunda gösterir.

Bu metod, alanın yalnızca yeni kayıt oluşturma formunda görünür olmasını sağlar. Güncelleme formunda ve diğer görünümlerde gizlenir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Şifre alanları (ilk oluşturmada)
  • Başlangıç yapılandırma alanları
  • Bir kez ayarlanan değerler

Örnek

field := Password("password", "Şifre").OnlyOnCreate()

func (*Schema) OnlyOnDetail

func (s *Schema) OnlyOnDetail() Element

OnlyOnDetail, alanı sadece detay görünümünde gösterir.

Bu metod, alanın yalnızca kayıt detay sayfasında görünür olmasını sağlar. Liste ve formlarda gizlenir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Detaylı açıklamalar
  • İlişkili kayıt bilgileri
  • Metadata bilgileri

Örnek

field := Textarea("full_description", "Detaylı Açıklama").OnlyOnDetail()

func (*Schema) OnlyOnForm

func (s *Schema) OnlyOnForm() Element

OnlyOnForm, alanı sadece formlarda gösterir.

Bu metod, alanın hem oluşturma hem de güncelleme formlarında görünür olmasını, ancak liste ve detay görünümlerinde gizlenmesini sağlar.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Sadece düzenleme için gerekli alanlar
  • Kullanıcı girdisi gerektiren alanlar
  • Görüntülenmesi gerekmeyen form alanları

Örnek

field := Hidden("csrf_token", "CSRF Token").OnlyOnForm()

func (*Schema) OnlyOnList

func (s *Schema) OnlyOnList() Element

OnlyOnList, alanı sadece liste görünümünde gösterir.

Bu metod, alanın yalnızca tablo/liste görünümünde görünür olmasını sağlar. Diğer tüm görünümlerde (detail, form) gizlenir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Özet bilgiler (örn. kayıt sayısı)
  • Hesaplanmış değerler (örn. toplam tutar)
  • Hızlı erişim linkleri

Örnek

field := Text("summary", "Özet").OnlyOnList()

func (*Schema) OnlyOnUpdate

func (s *Schema) OnlyOnUpdate() Element

OnlyOnUpdate, alanı sadece güncelleme formunda gösterir.

Bu metod, alanın yalnızca kayıt güncelleme formunda görünür olmasını sağlar. Oluşturma formunda ve diğer görünümlerde gizlenir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Şifre değiştirme alanları
  • Durum güncelleme alanları
  • Sadece mevcut kayıtlar için geçerli alanlar

Örnek

field := Password("new_password", "Yeni Şifre").OnlyOnUpdate()

func (*Schema) Options

func (s *Schema) Options(options interface{}) Element

Options, alan için seçenek listesi ayarlar.

Bu metod, select, radio, checkbox gibi seçim alanları için kullanılır. Statik seçenek listesi sağlar.

Parametreler

  • options: Seçenek listesi (slice veya map olabilir)

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Sabit seçenek listeleri
  • Enum değerleri
  • Durum seçenekleri

Örnek

field := Select("status", "Durum").Options([]map[string]interface{}{
    {"value": "active", "label": "Aktif"},
    {"value": "inactive", "label": "Pasif"},
})

func (*Schema) Pattern

func (s *Schema) Pattern(pattern string) core.Element

Pattern, regex pattern doğrulama kuralı ekler.

Bu metod, alanın belirtilen regex pattern'ine uymasını zorunlu kılar. Özel format kontrolleri için kullanılır.

Parametreler

  • pattern: Regex pattern string'i

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Telefon numarası formatı
  • Posta kodu formatı
  • Özel kod formatları
  • Kimlik numarası formatı

Örnek

field := Text("phone", "Telefon").
    Pattern(`^(\+90|0)?[0-9]{10}$`).
    Placeholder("5XX XXX XX XX")

func (*Schema) Placeholder

func (s *Schema) Placeholder(placeholder string) Element

Placeholder, alan için yer tutucu metin ayarlar.

Placeholder, alan boşken gösterilen açıklayıcı metindir. Kullanıcıya ne girilmesi gerektiği hakkında ipucu verir.

Parametreler

  • placeholder: Yer tutucu metin

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

İyi Uygulamalar

  • Kısa ve açıklayıcı olmalı
  • Örnek değer gösterilebilir
  • Zorunlu alan açıklaması yerine kullanılmamalı

Örnek

field := Text("email", "E-posta").
    Placeholder("[email protected]")

func (*Schema) ReadOnly

func (s *Schema) ReadOnly() Element

ReadOnly, alanı salt okunur olarak işaretler.

Salt okunur alanlar, kullanıcı tarafından düzenlenemez ancak görüntülenebilir. Genellikle sistem tarafından oluşturulan veya hesaplanan değerler için kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Otomatik oluşturulan ID'ler
  • Timestamp alanları (created_at, updated_at)
  • Hesaplanan değerler
  • Sistem tarafından yönetilen alanlar

Örnek

field := Text("created_at", "Oluşturma Tarihi").ReadOnly()

func (*Schema) RemoveEXIFData

func (s *Schema) RemoveEXIFData(ctx interface{}, file interface{}) error

RemoveEXIFData, dosyadan EXIF verilerini kaldırır.

Bu metod, resim dosyalarındaki EXIF metadata'sını kaldırır. Şu an için placeholder implementasyon içerir.

Parametreler

  • ctx: İşlem bağlamı
  • file: Dosya nesnesi

Döndürür

  • error: İşlem hatası (nil ise başarılı)

func (*Schema) Required

func (s *Schema) Required() Element

Required, alanı zorunlu olarak işaretler.

Zorunlu alanlar, form gönderilmeden önce doldurulmalıdır. Frontend ve backend validasyonunda kullanılır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Önemli Notlar

  • Frontend'de otomatik validasyon eklenir
  • Genellikle kırmızı yıldız (*) ile gösterilir
  • Backend validasyonu ile birlikte kullanılmalıdır

Örnek

field := Text("email", "E-posta").Required().Email()

func (*Schema) Resolve

func (s *Schema) Resolve(fn func(value interface{}, item interface{}, c *fiber.Ctx) interface{}) Element

Resolve, alan için özel veri çıkarma callback'i ayarlar.

Bu metod, alanın resource'dan nasıl çıkarılacağını özelleştirmeye olanak tanır. İlişkili veriler, hesaplanan değerler veya özel dönüşümler için kullanılır.

Parametreler

  • fn: Veri çıkarma işlemini yapan fonksiyon

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • İlişkili veri çıkarma
  • Hesaplanan değerler
  • Format dönüşümü
  • Özel veri işleme

Örnek

field := Text("full_name", "Tam İsim").Resolve(func(value interface{}, item interface{}, c *fiber.Ctx) interface{} {
    user := item.(*User)
    return user.FirstName + " " + user.LastName
})

func (*Schema) ResolveDependencies

func (s *Schema) ResolveDependencies(context interface{}) bool

ResolveDependencies, bağımlılık kurallarını değerlendirir.

Bu metod, verilen bağlama göre bağımlılık kurallarının karşılanıp karşılanmadığını kontrol eder. Şu an için her zaman true döner (placeholder implementasyon).

Parametreler

  • context: Değerlendirme bağlamı

Döndürür

  • bool: Bağımlılıklar karşılanıyor mu?

func (*Schema) ResolveForDisplay

func (s *Schema) ResolveForDisplay(item interface{}) (interface{}, error)

ResolveForDisplay, alanın değerini görüntüleme için çözümler.

Bu metod, verilen kayıttan alanın değerini çıkarır ve görüntüleme için hazırlar. Reflection kullanarak struct field'larını veya map değerlerini okur.

Parametreler

  • item: Değer çıkarılacak kayıt (struct veya map)

Döndürür

  • interface{}: Çıkarılan değer
  • error: Hata durumunda hata mesajı (şu an her zaman nil)

Çalışma Mantığı

1. Item nil ise, mevcut Data değerini döner 2. Item struct ise, field adına göre değer çıkarır 3. JSON tag'leri de kontrol edilir 4. Item map ise, key'e göre değer çıkarır

Örnek

type User struct {
    Name string `json:"name"`
}
user := &User{Name: "John"}
value, err := field.ResolveForDisplay(user)
// value == "John"

func (*Schema) ResolveHandle

func (s *Schema) ResolveHandle(handle string) core.Element

ResolveHandle, client-side bileşen etkileşimi için handle ayarlar.

Bu metod, frontend bileşeninin özel işlemler için kullanacağı bir handle belirler. Genellikle özel bileşenler veya dinamik davranışlar için kullanılır.

Parametreler

  • handle: Resolve handle string'i

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Özel bileşen etkileşimi
  • Dinamik veri yükleme
  • Client-side işlem tetikleme

Örnek

field := Custom("map", "Harita").ResolveHandle("map-component")

func (*Schema) Rows

func (s *Schema) Rows(rows int) Element

Rows, textarea field'ı için satır sayısını ayarlar.

Bu metod, textarea field'larında görüntülenecek satır sayısını belirler. Satır sayısı bilgisi Props'a "rows" key'i ile kaydedilir.

Parametreler:

  • rows: Satır sayısı

Döndürür:

  • Element pointer'ı (method chaining için)

Örnek:

field := fields.Textarea("Description", "description").Rows(5)

func (*Schema) Rules

func (s *Schema) Rules(rules ...interface{}) core.Element

func (*Schema) Searchable

func (s *Schema) Searchable() Element

Searchable, alanın global aramada kullanılacağını belirtir.

Searchable alanlar, genel arama kutusunda aranabilir. Kullanıcı arama yaptığında, bu alanların içeriği taranır.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • İsim alanları
  • E-posta alanları
  • Açıklama alanları
  • Başlık alanları

Önemli Notlar

  • Performans için dikkatli kullanılmalı
  • Çok fazla alan searchable yapılmamalı
  • Genellikle text alanları için uygundur

Örnek

field := Text("name", "İsim").Searchable()

func (*Schema) SetContext

func (s *Schema) SetContext(context ElementContext) Element

SetContext, alanın görüntüleneceği bağlamı ayarlar.

Context, alanın hangi sayfalarda (list, detail, form) görüneceğini belirler. Bu metod, görünürlük kontrolü için temel mekanizmayı sağlar.

Parametreler

  • context: Görüntüleme bağlamı (ElementContext enum değeri)

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanılabilir Context Değerleri

  • SHOW_ON_LIST: Liste görünümünde göster
  • SHOW_ON_DETAIL: Detay görünümünde göster
  • SHOW_ON_FORM: Form görünümünde göster
  • HIDE_ON_LIST: Liste görünümünde gizle
  • HIDE_ON_DETAIL: Detay görünümünde gizle
  • HIDE_ON_CREATE: Oluşturma formunda gizle
  • HIDE_ON_UPDATE: Güncelleme formunda gizle
  • ONLY_ON_LIST: Sadece liste görünümünde göster
  • ONLY_ON_DETAIL: Sadece detay görünümünde göster
  • ONLY_ON_CREATE: Sadece oluşturma formunda göster
  • ONLY_ON_UPDATE: Sadece güncelleme formunda göster
  • ONLY_ON_FORM: Sadece formlarda göster

Örnek

field := &Schema{Key: "id"}
field.SetContext(HIDE_ON_FORM)

func (*Schema) SetContextForI18n

func (s *Schema) SetContextForI18n(c *fiber.Ctx)

SetContextForI18n, i18n çevirileri için fiber context'ini ayarlar.

func (*Schema) SetDependencies

func (s *Schema) SetDependencies(deps []string) Element

SetDependencies, alan bağımlılıklarını ayarlar.

Bu metod, alanın bağımlı olduğu diğer alanları belirler.

Parametreler

  • deps: Bağımlı alan adları listesi

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field.SetDependencies([]string{"country", "state"})

func (*Schema) SetKey

func (s *Schema) SetKey(key string) Element

SetKey, alanın benzersiz tanımlayıcısını ayarlar.

Key, alanı resource model'indeki bir field'a eşlemek için kullanılır. Genellikle veritabanı sütun adı veya struct field adı ile eşleşir.

Parametreler

  • key: Alanın benzersiz tanımlayıcısı (örn. "email", "user_name", "created_at")

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Önemli Notlar

  • Key, snake_case formatında olmalıdır
  • Key, resource model'deki field adı ile eşleşmelidir
  • Key değiştirildiğinde, veri çıkarma işlemi etkilenir

Örnek

field := &Schema{}
field.SetKey("email_address")

func (*Schema) SetName

func (s *Schema) SetName(name string) Element

SetName, alanın görünen adını ayarlar.

Bu metod, UI'da kullanıcıya gösterilecek alan adını belirler. Genellikle form etiketleri, tablo başlıkları ve detay görünümlerinde kullanılır.

Parametreler

  • name: Alanın görünen adı (örn. "E-posta Adresi", "Kullanıcı Adı")

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := &Schema{Key: "email"}
field.SetName("E-posta Adresi")

func (*Schema) SetTextAlign

func (s *Schema) SetTextAlign(align string) Element

SetTextAlign, alan içeriğinin hizalamasını ayarlar.

Text align, alanın içeriğinin nasıl hizalanacağını belirler. Genellikle liste görünümünde kullanılır.

Parametreler

  • align: Hizalama değeri ("left", "center", "right", "justify")

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Sayısal alanlar için sağa hizalama
  • Başlıklar için ortaya hizalama
  • Metin alanları için sola hizalama (varsayılan)

Örnek

field := Number("price", "Fiyat").SetTextAlign("right")

func (*Schema) ShouldDisplayUsingLabels

func (s *Schema) ShouldDisplayUsingLabels() bool

ShouldDisplayUsingLabels, etiket kullanarak görüntüleme yapılıp yapılmayacağını döner.

Döndürür

  • bool: Etiket kullanılacak mı?

Örnek

if field.ShouldDisplayUsingLabels() {
    // Değer yerine etiketi göster
}

func (*Schema) ShouldRemoveEXIFData

func (s *Schema) ShouldRemoveEXIFData() bool

ShouldRemoveEXIFData, EXIF verilerinin kaldırılıp kaldırılmayacağını döner.

Döndürür

  • bool: EXIF verileri kaldırılacak mı?

Örnek

if field.ShouldRemoveEXIFData() {
    // EXIF verilerini kaldır
}

func (*Schema) ShowCurrency

func (s *Schema) ShowCurrency(show bool) *Schema

ShowCurrency, money field için currency etiketinin formda gösterilip gösterilmeyeceğini ayarlar.

func (*Schema) ShowNumberControls

func (s *Schema) ShowNumberControls(show bool) Element

ShowNumberControls, number input alanındaki artı/eksi butonlarının görünürlüğünü ayarlar.

Varsayılan değer true'dur (butonlar görünür). false gönderildiğinde frontend'de +/- butonları gizlenir.

Parametreler

  • show: true ise kontroller gösterilir, false ise gizlenir

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

fields.Number("Fiyat", "price").ShowNumberControls(false)

func (*Schema) ShowOnGrid

func (s *Schema) ShowOnGrid() Element

ShowOnGrid, alanı grid görünümünde görünür hale getirir.

func (*Schema) ShowOnlyGrid

func (s *Schema) ShowOnlyGrid() Element

ShowOnlyGrid, alanı index kapsamlarında (table/grid) gösterir, detail ve form görünümlerinde gizler.

func (*Schema) Sortable

func (s *Schema) Sortable() Element

Sortable, alanın sıralanabilir olduğunu belirtir.

Sortable alanlar, liste görünümünde sıralama seçenekleri sunar. Kullanıcılar bu alana göre kayıtları artan veya azalan şekilde sıralayabilir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • İsim alanları
  • Tarih alanları
  • Sayısal alanlar
  • Durum alanları

Örnek

field := Text("name", "İsim").Sortable()

func (*Schema) Span

func (s *Schema) Span(span int) Element

Span, alanın form/detail grid içindeki kolon genişliğini ayarlar.

Span değeri 1 ile 12 arasındadır. Geçersiz değerler otomatik olarak clamp edilir:

  • 1'den küçükse 1
  • 12'den büyükse 12

Parametreler

  • span: Grid kolon genişliği (1-12)

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

fields.Text("Ad", "first_name").Span(6)
fields.Text("Soyad", "last_name").Span(6)

func (*Schema) Stacked

func (s *Schema) Stacked() Element

Stacked, alanın tam genişlikte görüntüleneceğini belirtir.

Stacked alanlar, formda kendi satırını kaplar (100% genişlik). Varsayılan olarak alanlar yan yana dizilir, stacked alanlar alt alta dizilir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Textarea alanları
  • Uzun text alanları
  • Önemli alanlar
  • Görsel vurgu gerektiren alanlar

Örnek

field := Textarea("description", "Açıklama").Stacked()

func (*Schema) Store

func (s *Schema) Store(disk, path string) core.Element

Store, dosya depolama ayarlarını belirler.

Bu metod, yüklenen dosyaların nerede saklanacağını belirler. Disk ve path bilgilerini ayarlar.

Parametreler

  • disk: Depolama disk adı (örn. "local", "s3", "gcs")
  • path: Depolama yolu (örn. "uploads/avatars", "documents")

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Disk Tipleri

  • **local**: Yerel dosya sistemi
  • **s3**: Amazon S3
  • **gcs**: Google Cloud Storage
  • **azure**: Azure Blob Storage

Kullanım Senaryoları

  • Yerel depolama
  • Cloud depolama
  • CDN entegrasyonu

Örnek

field := File("avatar", "Avatar").
    Store("s3", "uploads/avatars").
    Accept("image/*").
    MaxSize(5 * 1024 * 1024)

func (*Schema) StoreAs

func (s *Schema) StoreAs(fn StorageCallbackFunc) Element

StoreAs, alan için özel depolama callback'i ayarlar.

Bu metod, alanın veritabanına nasıl kaydedileceğini özelleştirmeye olanak tanır. Veri dönüşümü, şifreleme, hash'leme gibi işlemler için kullanılır.

Parametreler

  • fn: Depolama işlemini yapan fonksiyon

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Şifre hash'leme
  • Veri şifreleme
  • Format dönüşümü
  • Hesaplanan değerler

Örnek

field := Password("password", "Şifre").StoreAs(func(value interface{}, ctx *fiber.Ctx) interface{} {
    return bcrypt.HashPassword(value.(string))
})

func (*Schema) Tooltip

func (s *Schema) Tooltip(text string) Element

Tooltip, alana bir tooltip (bilgi balonu) ekler.

Tooltip, kullanıcıya alan hakkında ek bilgi sağlamak için kullanılır. Frontend'te label'ın yanında bir info ikonu olarak gösterilir ve üzerine gelindiğinde tooltip metni görüntülenir.

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Örneği

field := Text("Kullanıcı Adı", "username").
    Tooltip("Kullanıcı adınız benzersiz olmalıdır ve en az 3 karakter içermelidir")

field := Email("E-posta", "email").
    Tooltip("Geçerli bir e-posta adresi giriniz").
    Required()

Not

Bu metod, arka planda WithProps("tooltip", text) çağrısı yapar. Tooltip özelliği frontend bileşenleri tarafından desteklenmelidir.

func (*Schema) URL

func (s *Schema) URL() core.Element

URL, URL doğrulama kuralı ekler.

Bu metod, alanın geçerli bir URL içermesini zorunlu kılar. HTTP, HTTPS ve diğer protokoller desteklenir.

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Doğrulama Kuralları

  • Geçerli URL formatı
  • Protokol içermeli (http://, https://, vb.)
  • Geçerli domain formatı

Kullanım Senaryoları

  • Website alanları
  • Sosyal medya profil linkleri
  • API endpoint alanları

Örnek

field := Text("website", "Website").URL()

func (*Schema) Unique

func (s *Schema) Unique(table, column string) core.Element

Unique, benzersizlik doğrulama kuralı ekler.

Bu metod, alanın veritabanında benzersiz olmasını zorunlu kılar. Aynı değere sahip başka bir kayıt varsa hata verir.

Parametreler

  • table: Kontrol edilecek tablo adı
  • column: Kontrol edilecek sütun adı

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • E-posta benzersizliği
  • Kullanıcı adı benzersizliği
  • Slug benzersizliği
  • Kod benzersizliği

Önemli Notlar

  • Güncelleme işlemlerinde mevcut kaydın kendisi hariç tutulur
  • Performans için veritabanı indeksi önerilir
  • Büyük/küçük harf duyarlılığı veritabanına bağlıdır

Örnek

field := Text("email", "E-posta").
    Email().
    Unique("users", "email")

func (*Schema) UpdateRules

func (s *Schema) UpdateRules(rules ...interface{}) core.Element

func (*Schema) ValidateAttachment

func (s *Schema) ValidateAttachment(filename string, size int64) error

ValidateAttachment, dosya yükleme doğrulaması yapar.

Bu metod, dosya adı ve boyutuna göre doğrulama yapar. Şu an için placeholder implementasyon içerir.

Parametreler

  • filename: Dosya adı
  • size: Dosya boyutu (byte)

Döndürür

  • error: Doğrulama hatası (nil ise geçerli)

func (*Schema) ValidateRepeats

func (s *Schema) ValidateRepeats(count int) error

ValidateRepeats, tekrar sayısını doğrular.

Bu metod, verilen tekrar sayısının min/max sınırları içinde olup olmadığını kontrol eder. Şu an için placeholder implementasyon içerir.

Parametreler

  • count: Tekrar sayısı

Döndürür

  • error: Doğrulama hatası (nil ise geçerli)

func (*Schema) ValidateValue

func (s *Schema) ValidateValue(value interface{}) error

ValidateValue, değeri doğrulama kurallarına göre kontrol eder.

Bu metod, verilen değerin tüm doğrulama kurallarını karşılayıp karşılamadığını kontrol eder. Şu an için placeholder implementasyon içerir.

Parametreler

  • value: Doğrulanacak değer

Döndürür

  • error: Doğrulama hatası (nil ise geçerli)

func (*Schema) When

func (s *Schema) When(field string, operator string, value interface{}) core.Element

When, bağımlılık kuralı ekler.

Bu metod, belirli bir alanın belirli bir değere sahip olması durumunda bu alanın nasıl davranacağını belirler.

Parametreler

  • field: Kontrol edilecek alan adı
  • operator: Karşılaştırma operatörü ("=", "!=", ">", "<", ">=", "<=", "in", "not_in")
  • value: Karşılaştırılacak değer

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Koşullu alan gösterimi
  • Değer bazlı validasyon
  • Dinamik form davranışı

Örnek

field := Text("other_reason", "Diğer Sebep").
    DependsOn("reason").
    When("reason", "=", "other")

func (*Schema) WithAutoComplete

func (s *Schema) WithAutoComplete(url string) core.Element

WithAutoComplete, alan için otomatik tamamlama URL'i ayarlar.

Bu metod, önerilerin bir API endpoint'inden yüklenmesini sağlar. Callback yerine URL kullanarak server-side öneri sistemi oluşturur.

Parametreler

  • url: Otomatik tamamlama API endpoint'i

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

API Beklentileri

  • GET request ile çağrılır
  • Query parameter: ?q=arama_metni
  • Response: JSON array [{value, label}, ...]

Kullanım Senaryoları

  • Büyük veri setlerinde arama
  • Uzak API entegrasyonu
  • Performans optimizasyonu

Örnek

field := Text("city", "Şehir").
    WithAutoComplete("/api/cities/search").
    MinCharsForSuggestions(2)

func (*Schema) WithBadgeVariant

func (s *Schema) WithBadgeVariant(variant string) core.Element

WithBadgeVariant, badge varyantını ayarlar.

Bu metod, badge'in görsel stilini belirler. Farklı varyantlar farklı görünümler sunar.

Parametreler

  • variant: Badge varyantı ("solid", "outline", "subtle", "dot")

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Varyant Tipleri

  • **solid**: Dolu, renkli arka plan
  • **outline**: Sadece kenarlık
  • **subtle**: Hafif renkli arka plan
  • **dot**: Nokta ile gösterim

Örnek

field := Status("priority", "Öncelik").
    WithStatusColors(map[string]string{
        "high":   "red",
        "medium": "yellow",
        "low":    "green",
    }).
    WithBadgeVariant("solid")

func (*Schema) WithEditor

func (s *Schema) WithEditor(editorType string) core.Element

WithEditor, editör tipini ayarlar.

Bu metod, hangi zengin metin editörünün kullanılacağını belirler. Farklı editörler farklı özellikler sunar.

Parametreler

  • editorType: Editör tipi ("tinymce", "quill", "ckeditor", "markdown")

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Editör Tipleri

  • **tinymce**: Tam özellikli WYSIWYG editör
  • **quill**: Modern, hafif editör
  • **ckeditor**: Güçlü, özelleştirilebilir editör
  • **markdown**: Markdown formatı editörü

Örnek

field := RichText("content", "İçerik").
    WithEditor("tinymce").
    WithLanguage("tr").
    WithTheme("modern")

func (*Schema) WithLanguage

func (s *Schema) WithLanguage(language string) core.Element

WithLanguage, editör dilini ayarlar.

Bu metod, editör arayüzünün hangi dilde gösterileceğini belirler. Menüler, butonlar ve mesajlar bu dilde gösterilir.

Parametreler

  • language: Dil kodu ("tr", "en", "de", "fr", vb.)

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Desteklenen Diller

  • tr: Türkçe
  • en: İngilizce
  • de: Almanca
  • fr: Fransızca
  • es: İspanyolca

Örnek

field := RichText("description", "Açıklama").
    WithEditor("quill").
    WithLanguage("tr")

func (*Schema) WithPivotResource

func (s *Schema) WithPivotResource(resourceName string) core.Element

WithPivotResource, pivot resource adını ayarlar.

Bu metod, pivot alanın hangi resource'a ait olduğunu belirtir. İlişki yönetimi için kullanılır.

Parametreler

  • resourceName: Pivot resource adı

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Örnek

field := Number("quantity", "Miktar").
    AsPivot().
    WithPivotResource("order_products")

func (*Schema) WithProps

func (s *Schema) WithProps(key string, value interface{}) Element

WithProps, alana özel bir özellik ekler.

Props, alanın frontend bileşenine iletilecek ekstra özellikleri saklar. Bu metod, özel bileşen davranışları veya stil ayarları için kullanılır.

Parametreler

  • key: Özellik anahtarı
  • value: Özellik değeri (herhangi bir tip olabilir)

Döndürür

  • Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Özel bileşen yapılandırması
  • Frontend'e özel veri iletimi
  • UI davranış kontrolü
  • Stil ve tema ayarları

Örnek

field := Text("name", "İsim").
    WithProps("maxLength", 100).
    WithProps("autoFocus", true).
    WithProps("className", "custom-input")

func (*Schema) WithStatusColors

func (s *Schema) WithStatusColors(colors map[string]string) core.Element

WithStatusColors, durum renk eşleştirmesi ayarlar.

Bu metod, her durum değeri için bir renk tanımlar. Liste ve detay görünümlerinde renkli badge'ler gösterilir.

Parametreler

  • colors: Durum-renk eşleştirme map'i

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Renk Değerleri

  • Hex kodları: "#FF0000", "#00FF00"
  • Renk isimleri: "red", "green", "blue"
  • Tailwind sınıfları: "bg-red-500", "bg-green-500"

Kullanım Senaryoları

  • Sipariş durumları
  • Ödeme durumları
  • Kullanıcı durumları
  • Görev durumları

Örnek

field := Status("status", "Durum").
    WithStatusColors(map[string]string{
        "pending":   "yellow",
        "approved":  "green",
        "rejected":  "red",
        "cancelled": "gray",
    })

func (*Schema) WithSuggestions

func (s *Schema) WithSuggestions(fn func(string) []interface{}) core.Element

WithSuggestions, alan için öneri callback'i ayarlar.

Bu metod, kullanıcı yazarken gösterilecek önerileri dinamik olarak oluşturur. Callback, arama sorgusunu alır ve öneri listesi döner.

Parametreler

  • fn: Öneri oluşturma fonksiyonu (string -> []interface{})

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Otomatik tamamlama
  • Arama önerileri
  • Hızlı seçim listeleri
  • Dinamik filtreleme

Örnek

field := Text("email", "E-posta").
    WithSuggestions(func(query string) []interface{} {
        return searchEmails(query)
    }).
    MinCharsForSuggestions(3)

func (*Schema) WithTheme

func (s *Schema) WithTheme(theme string) core.Element

WithTheme, editör temasını ayarlar.

Bu metod, editörün görsel temasını belirler. Farklı temalar farklı görünümler sunar.

Parametreler

  • theme: Tema adı ("modern", "classic", "dark", "light")

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Yaygın Temalar

  • **modern**: Modern, minimal görünüm
  • **classic**: Klasik, geleneksel görünüm
  • **dark**: Koyu tema
  • **light**: Açık tema

Örnek

field := RichText("article", "Makale").
    WithEditor("ckeditor").
    WithTheme("dark")

func (*Schema) WithUpload

func (s *Schema) WithUpload(fn func(interface{}, interface{}) error) core.Element

WithUpload, özel dosya yükleme callback'i ayarlar.

Bu metod, dosya yükleme işlemini özelleştirmeye olanak tanır. Dosya işleme, dönüşüm, validasyon gibi işlemler için kullanılır.

Parametreler

  • fn: Dosya yükleme işlemini yapan fonksiyon

Döndürür

  • core.Element: Zincirleme çağrılar için Schema pointer'ı

Kullanım Senaryoları

  • Resim boyutlandırma
  • Dosya dönüşümü
  • Özel validasyon
  • Metadata çıkarma

Örnek

field := File("image", "Resim").
    WithUpload(func(file interface{}, item interface{}) error {
        // Resmi yeniden boyutlandır
        return resizeImage(file, 800, 600)
    })

type Searchable

type Searchable struct {
	// contains filtered or unexported fields
}

Searchable, alanların aranabilir olmasını sağlayan bir mixin'dir.

Aranabilir sütunlar ve özel arama callback'leri için yapılandırma sağlar. Bu callback'ler, özel arama mantığı uygulamak için veritabanı sorgusunu değiştirebilir.

Kullanım

type TextField struct {
    fields.Base
    fields.Searchable
}

field := &TextField{}
field.SetSearchableColumns([]string{"name", "email"})
field.SetSearchCallback(func(db *gorm.DB, term string) *gorm.DB {
    return db.Where("LOWER(name) LIKE ?", "%"+strings.ToLower(term)+"%")
})

Daha fazla örnek için docs/Fields.md dosyasına bakın.

func (*Searchable) GetSearchCallback

func (s *Searchable) GetSearchCallback() func(*gorm.DB, string) *gorm.DB

GetSearchCallback, arama callback fonksiyonunu döndürür. Hiçbir callback ayarlanmamışsa nil döndürür.

Döndürür:

  • Arama callback fonksiyonu veya ayarlanmamışsa nil

func (*Searchable) GetSearchableColumns

func (s *Searchable) GetSearchableColumns() []string

GetSearchableColumns, aranabilir sütunları döndürür. Hiçbir sütun yapılandırılmamışsa boş bir dilim döndürür.

Döndürür:

  • Aranabilir sütun adlarının dilimi

func (*Searchable) SetSearchCallback

func (s *Searchable) SetSearchCallback(cb func(*gorm.DB, string) *gorm.DB)

SetSearchCallback, özel bir arama callback fonksiyonu ayarlar.

Callback, GORM veritabanı örneğini ve arama terimini alır, ve arama sorgusu uygulanmış değiştirilmiş bir veritabanı örneği döndürmelidir.

Parametreler:

  • cb: Özel arama mantığı için veritabanı sorgusunu değiştiren fonksiyon

Örnek:

field.SetSearchCallback(func(db *gorm.DB, term string) *gorm.DB {
    return db.Where(
        "LOWER(name) LIKE ? OR LOWER(email) LIKE ?",
        "%"+strings.ToLower(term)+"%",
        "%"+strings.ToLower(term)+"%",
    )
})

func (*Searchable) SetSearchableColumns

func (s *Searchable) SetSearchableColumns(columns []string)

SetSearchableColumns, aranabilir sütunları ayarlar. Bu sütunlar global arama işlemlerinde kullanılır.

Parametreler:

  • columns: Aranabilir olması gereken sütun adlarının listesi

Örnek:

field.SetSearchableColumns([]string{"name", "email", "username"})

type Sortable

type Sortable struct {
	// contains filtered or unexported fields
}

Sortable, alanların sıralanabilir olmasını sağlayan bir mixin'dir.

Sıralanabilir davranış, varsayılan sıralama yönü ve özel sıralama callback'leri için yapılandırma sağlar. Bu callback'ler veritabanı sorgusunu değiştirebilir.

Kullanım

type TextField struct {
    fields.Base
    fields.Sortable
}

field := &TextField{}
field.SetSortable(true)
field.SetSortDirection("asc")
field.SetSortCallback(func(db *gorm.DB, direction string) *gorm.DB {
    return db.Order("LOWER(name) " + direction)
})

Daha fazla örnek için docs/Fields.md dosyasına bakın.

func (*Sortable) GetSortCallback

func (s *Sortable) GetSortCallback() func(*gorm.DB, string) *gorm.DB

GetSortCallback, sıralama callback fonksiyonunu döndürür. Hiçbir callback ayarlanmamışsa nil döndürür.

Döndürür:

  • Sıralama callback fonksiyonu veya ayarlanmamışsa nil

func (*Sortable) GetSortDirection

func (s *Sortable) GetSortDirection() string

GetSortDirection, varsayılan sıralama yönünü döndürür. Hiçbir yön ayarlanmamışsa "asc" döndürür.

Döndürür:

  • Sıralama yönü ("asc" veya "desc")

func (*Sortable) IsSortable

func (s *Sortable) IsSortable() bool

IsSortable, alanın sıralanabilir olup olmadığını döndürür.

Döndürür:

  • Alan sıralanabilirse true, değilse false

func (*Sortable) SetSortCallback

func (s *Sortable) SetSortCallback(cb func(*gorm.DB, string) *gorm.DB)

SetSortCallback, özel bir sıralama callback fonksiyonu ayarlar.

Callback, GORM veritabanı örneğini ve sıralama yönünü alır, ve sıralama sorgusu uygulanmış değiştirilmiş bir veritabanı örneği döndürmelidir.

Parametreler:

  • cb: Özel sıralama mantığı için veritabanı sorgusunu değiştiren fonksiyon

Örnek:

field.SetSortCallback(func(db *gorm.DB, direction string) *gorm.DB {
    return db.Order("LOWER(name) " + direction)
})

func (*Sortable) SetSortDirection

func (s *Sortable) SetSortDirection(direction string)

SetSortDirection, varsayılan sıralama yönünü ayarlar.

Parametreler:

  • direction: Artan sıralama için "asc" veya azalan sıralama için "desc"

Örnek:

field.SetSortDirection("desc")

func (*Sortable) SetSortable

func (s *Sortable) SetSortable(sortable bool)

SetSortable, alanın sıralanabilir olup olmadığını ayarlar.

Parametreler:

  • sortable: Sıralamayı etkinleştirmek için true, devre dışı bırakmak için false

Örnek:

field.SetSortable(true)

type StorageCallbackFunc

type StorageCallbackFunc = core.StorageCallbackFunc

StorageCallbackFunc, dosya depolama işlemlerini özelleştiren callback fonksiyonudur.

Bu tip, core.StorageCallbackFunc'ın bir alias'ıdır ve dosya yükleme alanlarında (Image, File, Video, Audio) depolama davranışını özelleştirmek için kullanılır.

Kullanım Örneği

field.Storage(func(file interface{}) (string, error) {
    // Özel depolama mantığı
    return "path/to/file", nil
})

Daha fazla bilgi için pkg/core/storage.go dosyasına bakın.

type Tab

type Tab struct {
	// Value, tab'ın benzersiz tanımlayıcısıdır (örn: "tr", "en", "general")
	Value string `json:"value"`

	// Label, tab'ın görünen adıdır (örn: "Türkçe", "English", "Genel Bilgiler")
	Label string `json:"label"`

	// Fields, tab içinde görüntülenecek alanların listesidir
	Fields []core.Element `json:"fields"`
}

Tab, bir tab'ın yapısını temsil eder.

Her tab, benzersiz bir değer (value), görünen bir etiket (label) ve içerdiği alanlardan (fields) oluşur.

Kullanım Örneği

tab := Tab{
    Value: "tr",
    Label: "Türkçe",
    Fields: []core.Element{
        fields.Text("Başlık", "title_tr"),
        fields.Textarea("Açıklama", "description_tr"),
    },
}

type TabsField

type TabsField struct {
	*Schema
	Tabs []Tab
}

TabsField, alanları tab'lara ayırmak için bir konteyner temsil eder.

TabsField, ilgili alanları tab'lar halinde organize etmek için kullanılır. Her tab, kendi başlığı ve içeriği ile ayrı bir bölüm oluşturur.

Kullanım Senaryoları

- **Çoklu Dil Desteği**: Türkçe, İngilizce, vb. tab'ları ile çeviri alanları - **Kategorize Edilmiş Formlar**: Genel Bilgiler, Adres, İletişim tab'ları - **Karmaşık Form Organizasyonu**: Uzun formları mantıksal bölümlere ayırma - **İlgili Alan Grupları**: Benzer alanları bir arada gösterme

Özellikler

- **Çoklu Tab**: Birden fazla tab ekleme - **Tab Pozisyonu**: Tab'ların konumu (top, bottom, left, right) - **Tab Variant**: Tab görünümü (default, line) - **Varsayılan Tab**: Sayfa yüklendiğinde aktif olacak tab

Kullanım Örneği

tabs := fields.Tabs("Ürün Bilgileri").
    AddTab("tr", "Türkçe",
        fields.Text("Başlık", "title_tr"),
        fields.Textarea("Açıklama", "description_tr"),
    ).
    AddTab("en", "English",
        fields.Text("Title", "title_en"),
        fields.Textarea("Description", "description_en"),
    ).
    WithSide("top").
    WithVariant("line").
    WithDefaultTab("tr")

func Tabs

func Tabs(title string) *TabsField

Tabs, alanları tab'lara ayırmak için yeni bir tabs konteyner oluşturur.

Bu fonksiyon, ilgili alanları tab'lar halinde organize etmek için bir konteyner oluşturur. Form sayfalarında alanları mantıksal tab'lara ayırmak için kullanılır.

Parametreler

- **title**: Tabs konteyner başlığı (örn. "Ürün Bilgileri", "Çeviriler")

Kullanım Örneği

tabs := fields.Tabs("Ürün Bilgileri")

Döndürür:

  • Yapılandırılmış TabsField pointer'ı

func (*TabsField) AddTab

func (t *TabsField) AddTab(value, label string, fields ...core.Element) *TabsField

AddTab, tabs konteyner'a yeni bir tab ekler.

Bu metod, tab'a benzersiz bir değer (value), görünen bir etiket (label) ve içerdiği alanları (fields) ekler.

Parametreler

- **value**: Tab'ın benzersiz tanımlayıcısı (örn: "tr", "en", "general") - **label**: Tab'ın görünen adı (örn: "Türkçe", "English", "Genel Bilgiler") - **fields**: Tab içinde görüntülenecek alanlar

Kullanım Örneği

tabs.AddTab("tr", "Türkçe",
    fields.Text("Başlık", "title_tr"),
    fields.Textarea("Açıklama", "description_tr"),
)

Döndürür:

  • TabsField pointer'ı (method chaining için)

func (*TabsField) GetFields

func (t *TabsField) GetFields() []core.Element

GetFields, tüm tab'lardaki alanları düz bir liste olarak döndürür.

Bu metod, tabs konteyner içindeki tüm alanları toplar ve tek bir liste halinde döndürür. Backend'de alan validasyonu ve veri işleme için kullanılır.

Kullanım Örneği

allFields := tabs.GetFields()
// Tüm tab'lardaki field'ları içerir

Döndürür:

  • Tüm tab'lardaki alanların birleştirilmiş listesi

func (*TabsField) WithDefaultTab

func (t *TabsField) WithDefaultTab(value string) *TabsField

WithDefaultTab, sayfa yüklendiğinde aktif olacak tab'ı ayarlar.

Bu metod, varsayılan olarak hangi tab'ın açık olacağını belirler. Belirtilen value, AddTab ile eklenen tab'lardan birinin value'su olmalıdır.

Parametreler

- **value**: Varsayılan aktif tab'ın value'su

Kullanım Örneği

tabs.WithDefaultTab("tr")  // Türkçe tab'ı varsayılan olarak açık

Döndürür:

  • TabsField pointer'ı (method chaining için)

func (*TabsField) WithSide

func (t *TabsField) WithSide(side string) *TabsField

WithSide, tab'ların pozisyonunu ayarlar.

Bu metod, tab'ların nerede görüntüleneceğini belirler. Geçerli değerler: "top", "bottom", "left", "right"

Parametreler

- **side**: Tab pozisyonu ("top", "bottom", "left", "right")

Kullanım Örneği

tabs.WithSide("top")    // Tab'lar üstte
tabs.WithSide("left")   // Tab'lar solda

Döndürür:

  • TabsField pointer'ı (method chaining için)

func (*TabsField) WithVariant

func (t *TabsField) WithVariant(variant string) *TabsField

WithVariant, tab'ların görünüm stilini ayarlar.

Bu metod, tab'ların nasıl görüntüleneceğini belirler. Geçerli değerler: "default", "line"

Parametreler

- **variant**: Tab görünümü ("default", "line")

Kullanım Örneği

tabs.WithVariant("default")  // Varsayılan tab görünümü
tabs.WithVariant("line")     // Çizgi altı tab görünümü

Döndürür:

  • TabsField pointer'ı (method chaining için)

type Tag

type Tag struct {
	// ID, etiketin benzersiz kimliğidir (primary key).
	ID int `json:"id"`

	// Name, etiketin adıdır.
	// Veritabanında UNIQUE constraint ile korunur.
	Name string `json:"name"`
}

Tag, bir etiketi temsil eden model yapısıdır.

Bu model, içerikleri kategorize etmek için kullanılan etiketleri tutar ve BelongsToMany ilişkisinin test edilmesinde kullanılır.

İlişkiler

- **BelongsToMany**: Posts (bir etiket birden fazla gönderiye ait olabilir) - **MorphTo**: Taggables (polimorfik ilişki ile farklı modellere etiket eklenebilir)

JSON Serileştirme

Tüm alanlar JSON olarak serileştirilebilir.

Örnek Kullanım

```go var tag Tag err := db.QueryRow("SELECT id, name FROM tags WHERE id = ?", 1).

Scan(&tag.ID, &tag.Name)

```

type Taggable

type Taggable struct {
	// ID, taggable kaydının benzersiz kimliğidir (primary key).
	ID int `json:"id"`

	// TaggableID, etiketlenen kaydın ID'sidir.
	// Bu, Post, Comment veya başka bir modelin ID'si olabilir.
	TaggableID int `json:"taggable_id"`

	// TaggableType, etiketlenen kaydın model türünü belirtir.
	// Örnek değerler: "post", "comment", "user", vb.
	TaggableType string `json:"taggable_type"`

	// TagID, etiketin ID'sidir (foreign key).
	TagID int `json:"tag_id"`
}

Taggable, polimorfik etiketleme ilişkisini temsil eden model yapısıdır.

Bu model, farklı türdeki modellere (Post, Comment, vb.) etiket eklenmesini sağlar. MorphTo (polimorfik) ilişkisinin test edilmesinde kullanılır.

Polimorfik İlişki

Polimorfik ilişki, bir modelin birden fazla farklı model türü ile ilişkilendirilmesini sağlar: - Bir etiket bir Post'a eklenebilir (taggable_type = "post") - Bir etiket bir Comment'e eklenebilir (taggable_type = "comment") - Gelecekte başka model türleri de eklenebilir

Veritabanı Yapısı

- taggable_id: İlişkilendirilen kaydın ID'si - taggable_type: İlişkilendirilen modelin türü (string) - tag_id: Etiketin ID'si

Avantajlar

- **Esneklik**: Yeni model türleri kolayca eklenebilir - **Tekrar Kullanılabilirlik**: Aynı etiket sistemi farklı modellerde kullanılabilir - **Genişletilebilirlik**: Yeni özellikler kolayca eklenebilir

Dezavantajlar

- **Foreign Key Constraint Yok**: taggable_id için doğrudan foreign key tanımlanamaz - **Tip Güvenliği**: taggable_type string olduğu için yazım hataları olabilir - **Performans**: Sorgular daha karmaşık olabilir

Önemli Notlar

- taggable_type değeri tutarlı olmalıdır (örn: "post", "comment") - Silme işlemlerinde cascade dikkatli yapılmalıdır - Sorgularda hem taggable_id hem de taggable_type kullanılmalıdır

Örnek Kullanım

```go // Bir gönderiye etiket ekle _, err := db.Exec(`

INSERT INTO taggables (taggable_id, taggable_type, tag_id)
VALUES (?, ?, ?)

`, 1, "post", 2)

// Bir gönderinin tüm etiketlerini getir (polimorfik sorgu) rows, err := db.Query(`

SELECT t.id, t.name
FROM tags t
JOIN taggables tg ON t.id = tg.tag_id
WHERE tg.taggable_id = ? AND tg.taggable_type = ?

`, 1, "post")

// Bir etiketin tüm gönderilerini getir rows, err := db.Query(`

SELECT p.id, p.title
FROM posts p
JOIN taggables tg ON p.id = tg.taggable_id
WHERE tg.tag_id = ? AND tg.taggable_type = ?

`, 1, "post") ```

type TestDB

type TestDB struct {
	// DB, aktif SQLite veritabanı bağlantısını tutar.
	// Bu bağlantı üzerinden tüm SQL işlemleri gerçekleştirilir.
	DB *sql.DB
	// contains filtered or unexported fields
}

TestDB, test senaryoları için veritabanı bağlantısı sağlayan ana yapıdır.

Bu yapı, SQLite in-memory veritabanı kullanarak izole test ortamları oluşturur. Her test için temiz bir veritabanı örneği sağlar ve test sonunda otomatik temizlik yapılmasını kolaylaştırır.

Özellikler

- In-memory SQLite veritabanı (disk I/O yok, hızlı testler) - Otomatik tablo oluşturma - Önceden tanımlı test verileri - Test context'i ile entegrasyon

Avantajlar

- **Hız**: In-memory veritabanı sayesinde çok hızlı test çalıştırma - **İzolasyon**: Her test kendi veritabanı örneğine sahip - **Temizlik**: Test sonunda otomatik temizleme - **Tutarlılık**: Her test aynı başlangıç durumu ile çalışır

Dezavantajlar

- SQLite sınırlamaları (bazı SQL özellikleri desteklenmez) - Gerçek veritabanı motorlarından farklı davranışlar gösterebilir - Büyük veri setleri için bellek kullanımı artabilir

Önemli Notlar

- Her test için yeni bir TestDB örneği oluşturun - Test sonunda mutlaka Close() metodunu çağırın (defer kullanın) - In-memory veritabanı, bağlantı kapandığında tüm verileri kaybeder

Örnek Kullanım

```go

func TestUserQueries(t *testing.T) {
    testDB := NewTestDB(t)
    defer testDB.Close()

    // Test kodunuz
    rows, err := testDB.DB.Query("SELECT * FROM users WHERE id = ?", 1)
    if err != nil {
        t.Fatal(err)
    }
    defer rows.Close()
}

```

func NewTestDB

func NewTestDB(t *testing.T) *TestDB

NewTestDB, yeni bir test veritabanı oluşturur ve başlatır.

Bu fonksiyon, SQLite in-memory veritabanı kullanarak tamamen izole bir test ortamı sağlar. Veritabanı otomatik olarak tüm gerekli tabloları oluşturur ve test verileri ile doldurur.

İşlem Adımları

1. In-memory SQLite veritabanı bağlantısı açar 2. Tüm test tablolarını oluşturur (users, posts, comments, tags, profiles, vb.) 3. Örnek test verilerini ekler 4. Hazır TestDB örneğini döndürür

Parametreler

- `t`: Test context'i. Hata durumlarında test başarısızlığını bildirmek için kullanılır.

Dönüş Değeri

Kullanıma hazır TestDB örneği döndürür. Bu örnek üzerinden tüm veritabanı işlemleri yapılabilir.

Hata Yönetimi

Herhangi bir hata durumunda (veritabanı açılamaz, tablolar oluşturulamaz, veri eklenemez) test otomatik olarak başarısız sayılır (t.Fatalf kullanılır).

Önemli Notlar

- **Bellek Kullanımı**: In-memory veritabanı RAM'de çalışır, disk I/O yoktur - **İzolasyon**: Her çağrı tamamen bağımsız bir veritabanı oluşturur - **Temizlik**: Mutlaka defer ile Close() çağrılmalıdır - **Performans**: Disk tabanlı veritabanlarından çok daha hızlıdır

Kullanım Örnekleri

```go // Temel kullanım

func TestBasicQuery(t *testing.T) {
    testDB := NewTestDB(t)
    defer testDB.Close()

    var count int
    err := testDB.DB.QueryRow("SELECT COUNT(*) FROM users").Scan(&count)
    if err != nil {
        t.Fatal(err)
    }
    if count != 3 {
        t.Errorf("Expected 3 users, got %d", count)
    }
}

// İlişkisel sorgu testi

func TestRelationships(t *testing.T) {
    testDB := NewTestDB(t)
    defer testDB.Close()

    // User'ın post'larını getir
    rows, err := testDB.DB.Query(`
        SELECT p.title FROM posts p
        JOIN users u ON p.user_id = u.id
        WHERE u.email = ?
    `, "[email protected]")
    if err != nil {
        t.Fatal(err)
    }
    defer rows.Close()
}

```

Test Verileri

Fonksiyon aşağıdaki örnek verileri otomatik olarak oluşturur: - 3 kullanıcı (John Doe, Jane Smith, Bob Johnson) - 3 gönderi (farklı kullanıcılara ait) - 3 yorum - 4 etiket (golang, database, testing, api) - 2 profil - Çeşitli ilişkisel veriler (post-tag, taggables)

func (*TestDB) Close

func (tdb *TestDB) Close() error

Close, test veritabanı bağlantısını kapatır ve kaynakları serbest bırakır.

Bu metod, test sonunda veritabanı bağlantısını düzgün bir şekilde kapatır. In-memory veritabanı kullanıldığı için, bağlantı kapandığında tüm veriler kaybolur.

Dönüş Değeri

Bağlantı kapatma işlemi sırasında oluşan hata varsa döndürür, yoksa nil döner.

Önemli Notlar

- **Mutlaka Çağrılmalı**: Her NewTestDB çağrısından sonra mutlaka Close çağrılmalıdır - **Defer Kullanımı**: En iyi pratik, defer ile kullanmaktır - **Veri Kaybı**: In-memory veritabanı olduğu için, Close sonrası tüm veriler kaybolur - **Kaynak Sızıntısı**: Close çağrılmazsa veritabanı bağlantısı açık kalır

Kullanım Örnekleri

```go // Önerilen kullanım (defer ile)

func TestExample(t *testing.T) {
    testDB := NewTestDB(t)
    defer testDB.Close() // Test bitince otomatik kapanır

    // Test kodunuz...
}

// Manuel kullanım (önerilmez)

func TestManual(t *testing.T) {
    testDB := NewTestDB(t)

    // Test kodunuz...

    if err := testDB.Close(); err != nil {
        t.Errorf("Failed to close database: %v", err)
    }
}

```

type User

type User struct {
	// ID, kullanıcının benzersiz kimliğidir (primary key).
	ID int `json:"id"`

	// Name, kullanıcının tam adıdır.
	Name string `json:"name"`

	// Email, kullanıcının benzersiz e-posta adresidir.
	// Veritabanında UNIQUE constraint ile korunur.
	Email string `json:"email"`
}

User, bir kullanıcıyı temsil eden model yapısıdır.

Bu model, sistemdeki kullanıcı bilgilerini tutar ve diğer modeller ile ilişkilendirilir. HasOne ve HasMany ilişkilerinin test edilmesinde kullanılır.

İlişkiler

- **HasOne**: Profile (bir kullanıcının bir profili vardır) - **HasMany**: Posts (bir kullanıcının birden fazla gönderisi olabilir) - **HasMany**: Comments (bir kullanıcının birden fazla yorumu olabilir)

JSON Serileştirme

Tüm alanlar JSON olarak serileştirilebilir. API yanıtlarında kullanılabilir.

Örnek Kullanım

```go var user User err := db.QueryRow("SELECT id, name, email FROM users WHERE id = ?", 1).

Scan(&user.ID, &user.Name, &user.Email)

```

type Validatable

type Validatable struct {
	// contains filtered or unexported fields
}

Validatable, alanların doğrulama kurallarına sahip olmasını sağlayan bir mixin'dir.

String tabanlı doğrulama kuralları ve karmaşık doğrulama mantığı uygulayabilen özel doğrulayıcı fonksiyonları için yapılandırma sağlar.

Kullanım

type EmailField struct {
    fields.Base
    fields.Validatable
}

field := &EmailField{}
field.SetRules([]string{"required", "email"})
field.AddValidator(func(value any) error {
    email, ok := value.(string)
    if !ok {
        return fmt.Errorf("email bir string olmalıdır")
    }
    if !strings.Contains(email, "@") {
        return fmt.Errorf("geçersiz email formatı")
    }
    return nil
})

Daha fazla örnek için docs/Fields.md dosyasına bakın.

func (*Validatable) AddValidator

func (v *Validatable) AddValidator(validator func(any) error)

AddValidator, özel bir doğrulayıcı fonksiyonu ekler.

Doğrulayıcı, alan değerini alır ve doğrulama başarısız olursa bir hata, doğrulama başarılı olursa nil döndürmelidir.

Parametreler:

  • validator: Alan değerini doğrulayan fonksiyon

Örnek:

field.AddValidator(func(value any) error {
    str, ok := value.(string)
    if !ok {
        return fmt.Errorf("değer bir string olmalıdır")
    }
    if len(str) < 8 {
        return fmt.Errorf("değer en az 8 karakter olmalıdır")
    }
    return nil
})

func (*Validatable) GetRules

func (v *Validatable) GetRules() []string

GetRules, doğrulama kurallarını döndürür. Hiçbir kural yapılandırılmamışsa boş bir dilim döndürür.

Döndürür:

  • Doğrulama kuralı tanımlayıcılarının dilimi

func (*Validatable) GetValidators

func (v *Validatable) GetValidators() []func(any) error

GetValidators, özel doğrulayıcı fonksiyonlarını döndürür. Hiçbir doğrulayıcı eklenmemişse boş bir dilim döndürür.

Döndürür:

  • Doğrulayıcı fonksiyonlarının dilimi

func (*Validatable) SetRules

func (v *Validatable) SetRules(rules []string)

SetRules, alan için doğrulama kurallarını ayarlar.

Kurallar, yerleşik doğrulayıcılara karşılık gelen string tabanlı tanımlayıcılardır (örn. "required", "email", "min:8", "max:255").

Parametreler:

  • rules: Doğrulama kuralı tanımlayıcılarının listesi

Örnek:

field.SetRules([]string{"required", "email", "max:255"})

type ValidationResult

type ValidationResult struct {
	IsValid bool                // Doğrulama başarılı mı?
	Errors  map[string][]string // Alan adı -> hata mesajları
}

ValidationResult, doğrulama sonucunu temsil eder.

Bu yapı, doğrulama işleminin başarılı olup olmadığını ve varsa hata mesajlarını içerir.

Kullanım Örneği

result := ValidationResult{
    IsValid: false,
    Errors: map[string][]string{
        "email": {"Geçerli bir e-posta adresi giriniz"},
    },
}

type ValidationRule

type ValidationRule struct {
	Name       string        // Kural adı (required, email, min, vb.)
	Parameters []interface{} // Kural parametreleri
	Message    string        // Hata mesajı
}

ValidationRule, bir alan için doğrulama kuralını temsil eder.

Doğrulama kuralları, form verilerinin belirli kriterlere uygun olup olmadığını kontrol eder. Her kural bir ad, parametreler ve hata mesajı içerir.

Kullanım Örneği

rule := fields.Required()
rule := fields.MinLength(5)
rule := fields.EmailRule()

Daha fazla bilgi için docs/Fields.md dosyasına bakın.

func EmailRule

func EmailRule() ValidationRule

EmailRule, e-posta formatı için doğrulama kuralı döndürür.

Bu kural, alanın geçerli bir e-posta adresi formatında olmasını zorunlu kılar. RFC 5322 standardına uygun e-posta adresleri kabul edilir.

Kullanım Örneği

field.Rules(fields.EmailRule())
// Geçerli e-posta formatı: [email protected]

Döndürür:

  • ValidationRule: "This field must be a valid email address" hata mesajı ile

func Exists

func Exists(table, column string) ValidationRule

Exists, veritabanı varlığı için doğrulama kuralı döndürür.

Bu kural, alanın veritabanında mevcut olmasını zorunlu kılar. Belirtilen değere sahip bir kayıt yoksa doğrulama başarısız olur.

Parametreler

- **table**: Tablo adı - **column**: Sütun adı

Kullanım Örneği

field.Rules(fields.Exists("categories", "id"))
// Kategori ID'si categories tablosunda mevcut olmalıdır

Döndürür:

  • ValidationRule: "This value does not exist" hata mesajı ile

func Max

func Max(max interface{}) ValidationRule

Max, maksimum değer için doğrulama kuralı döndürür.

Bu kural, sayısal alanların belirtilen maksimum değerden küçük veya eşit olmasını zorunlu kılar.

Parametreler

- **max**: Maksimum değer (int, float, vb.)

Kullanım Örneği

field.Rules(fields.Max(100))
// Değer en fazla 100 olmalıdır

Döndürür:

  • ValidationRule: "This field must be at most {max}" hata mesajı ile

func MaxLength

func MaxLength(length int) ValidationRule

MaxLength, maksimum string uzunluğu için doğrulama kuralı döndürür.

Bu kural, string alanların belirtilen maksimum karakter sayısından kısa veya eşit olmasını zorunlu kılar.

Parametreler

- **length**: Maksimum karakter sayısı

Kullanım Örneği

field.Rules(fields.MaxLength(255))
// String en fazla 255 karakter olmalıdır

Döndürür:

  • ValidationRule: "This field must be at most {length} characters" hata mesajı ile

func MergeValidationRules

func MergeValidationRules(base, extra []ValidationRule) []ValidationRule

func Min

func Min(min interface{}) ValidationRule

Min, minimum değer için doğrulama kuralı döndürür.

Bu kural, sayısal alanların belirtilen minimum değerden büyük veya eşit olmasını zorunlu kılar.

Parametreler

- **min**: Minimum değer (int, float, vb.)

Kullanım Örneği

field.Rules(fields.Min(18))
// Değer en az 18 olmalıdır

Döndürür:

  • ValidationRule: "This field must be at least {min}" hata mesajı ile

func MinLength

func MinLength(length int) ValidationRule

MinLength, minimum string uzunluğu için doğrulama kuralı döndürür.

Bu kural, string alanların belirtilen minimum karakter sayısından uzun veya eşit olmasını zorunlu kılar.

Parametreler

- **length**: Minimum karakter sayısı

Kullanım Örneği

field.Rules(fields.MinLength(5))
// String en az 5 karakter olmalıdır

Döndürür:

  • ValidationRule: "This field must be at least {length} characters" hata mesajı ile

func Pattern

func Pattern(pattern string) ValidationRule

Pattern, regex pattern eşleştirme için doğrulama kuralı döndürür.

Bu kural, alanın belirtilen regex pattern'ine uygun olmasını zorunlu kılar.

Parametreler

- **pattern**: Regex pattern (örn. "^[A-Z][a-z]+$")

Kullanım Örneği

field.Rules(fields.Pattern("^[0-9]{5}$"))
// 5 haneli sayı formatı (örn. 12345)

Döndürür:

  • ValidationRule: "This field format is invalid" hata mesajı ile

func Required

func Required() ValidationRule

Required, zorunlu alanlar için doğrulama kuralı döndürür.

Bu kural, alanın boş olmamasını zorunlu kılar. Boş string, nil, boş slice gibi değerler geçersiz sayılır.

Kullanım Örneği

field.Rules(fields.Required())
// Alan boş bırakılamaz

Döndürür:

  • ValidationRule: "This field is required" hata mesajı ile

func URL

func URL() ValidationRule

URL, URL formatı için doğrulama kuralı döndürür.

Bu kural, alanın geçerli bir URL formatında olmasını zorunlu kılar. HTTP, HTTPS gibi protokoller desteklenir.

Kullanım Örneği

field.Rules(fields.URL())
// Geçerli URL formatı: https://example.com

Döndürür:

  • ValidationRule: "This field must be a valid URL" hata mesajı ile

func Unique

func Unique(table, column string) ValidationRule

Unique, veritabanı benzersizliği için doğrulama kuralı döndürür.

Bu kural, alanın veritabanında benzersiz olmasını zorunlu kılar. Aynı değere sahip başka bir kayıt varsa doğrulama başarısız olur.

Parametreler

- **table**: Tablo adı - **column**: Sütun adı

Kullanım Örneği

field.Rules(fields.Unique("users", "email"))
// E-posta adresi users tablosunda benzersiz olmalıdır

Döndürür:

  • ValidationRule: "This value already exists" hata mesajı ile

type ValidatorFunc

type ValidatorFunc func(value interface{}, context interface{}) error

ValidatorFunc, bir değeri doğrulayan fonksiyondur.

Bu tip, özel doğrulama mantığı tanımlamak için kullanılır. Fonksiyon, değer geçerliyse nil, geçersizse hata döndürür.

Kullanım Örneği

validator := func(value interface{}, context interface{}) error {
    if value == nil {
        return fmt.Errorf("değer boş olamaz")
    }
    return nil
}

func GetCustomValidator

func GetCustomValidator(name string) (ValidatorFunc, bool)

GetCustomValidator retrieves a global custom validator

type VisibilityContext

type VisibilityContext = core.VisibilityContext

VisibilityContext, görünürlük kontrolü için bağlam bilgisini sağlar.

Bu tip, core.VisibilityContext'in bir alias'ıdır ve elemanların hangi işlem sırasında (oluşturma, güncelleme, listeleme, vb.) görüntüleneceğini belirler.

Daha fazla bilgi için pkg/core/visibility_context.go dosyasına bakın.

type VisibilityFunc

type VisibilityFunc = core.VisibilityFunc

VisibilityFunc, bir elemanın görünürlüğünü kontrol eden callback fonksiyonudur.

Bu tip, core.VisibilityFunc'ın bir alias'ıdır ve elemanların dinamik olarak gösterilip gizlenmesini sağlar.

Kullanım Örneği

field.ShowIf(func(ctx VisibilityContext) bool {
    return ctx == ContextCreate
})

Daha fazla bilgi için pkg/core/visibility.go dosyasına bakın.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL