11. Ek Alanlar (xfields)

Ek alanlar, haberlere ve üyelere kullanıcı tanımlı ek bilgi eklemenizi sağlar. Eklenti geliştirirken bu veriyi okumak veya yazmak gerekebilir. Bu sayfa, verinin gerçekte nasıl saklandığını gösterir.

✕
"Ek alanlar artık JSON" ifadesi YANLIŞTIR İnternette "DLE ek alanları JSON formatına geçti" diye yazanlar var. Yalnızca alan tanımları JSON'a taşındı. Habere ait değerler hâlâ _post.xfields sütununda düz metin olarak durur. İkisini karıştırmak, eklentinizi çalışmaz hâle getirir.

İki ayrı şey: tanım ve değer

Alan tanımlarıHaber/üye değerleri
Nerede? engine/data/xfields.json
engine/data/userxfields.json
{prefix}_post.xfields sütunu
{prefix}_users.xfields sütunu
Biçim JSON Düz metin
İçerik Alan adı, tipi, varsayılanı, hangi kategoriye ait olduğu… Alanın o haberdeki karşılığı

Değerlerin saklama biçimi

Haber ek alanları tek bir metin sütununda şu kuralla saklanır:

alan1|deger1||alan2|deger2||alan3|deger3 └─ alan|değer çiftleri, kayıtlar || ile ayrılır

Kaçış kuralları:

Gerçek karakterSaklanan biçim
| (dikey çizgi)|
Yeni satır__NEWL__
Çoklu değer ayırıcı\x01 (aynı alan birden fazla kez geçerse değerler bu karakterle birleştirilir)

DLE'nin bu biçimi okuyan metodu DLEXFields::xfieldsdataload()'dur:

public static function xfieldsdataload($xfvalues) {

    $xfvalues = (string)$xfvalues;
    if( !$xfvalues ) return [];

    $xfieldsdata = explode( "||", $xfvalues );
    $data = [];

    foreach ( $xfieldsdata as $xfielddata ) {
        $parts = explode( "|", $xfielddata );
        if (count($parts) < 2) continue;

        $name  = str_replace(array("&#124;", "__NEWL__"), array("|", "\n"), $parts[0]);
        $value = str_replace(array("&#124;", "__NEWL__"), array("|", "\n"), $parts[1]);

        if (isset($data[$name])) {
            $data[$name] .= "\x01" . $value;   // çoklu değer
        } else {
            $data[$name] = $value;
        }
    }

    return $data;
}
★
Kendiniz ayrıştırmayın Bu biçimi elle explode('|', …) ile çözmeye çalışmak, kaçış karakterleri (&#124;, __NEWL__) yüzünden hatalı sonuç verir. Her zaman DLEXFields::xfieldsdataload() kullanın.

Ek alan değerlerini okumak

Sınıf engine/classes/xfields.class.php içindedir. Statik metotlar olduğu için nesne oluşturmanız gerekmez.

// Haber satırını çek
$row = $db->super_query("SELECT id, xfields FROM " . PREFIX . "_post WHERE id = '{$id}'");

// Ek alanları ilişkisel diziye çevir
$xf = DLEXFields::xfieldsdataload($row['xfields']);

// Artık alan adıyla erişebilirsiniz
if (isset($xf['fiyat'])) {
    echo "Fiyat: " . htmlspecialchars($xf['fiyat'], ENT_QUOTES, 'UTF-8');
}

// Çoklu değerli (dynamic) alan ise değer \x01 ile ayrılmıştır:
if (isset($xf['ozellikler'])) {
    $parcalar = explode("\x01", $xf['ozellikler']);
    foreach ($parcalar as $p) {
        echo htmlspecialchars($p, ENT_QUOTES, 'UTF-8') . "<br>";
    }
}

Alan tanımlarını okumak

Bir alanın tipi, varsayılan değeri veya hangi kategorilere ait olduğunu bilmeniz gerekiyorsa FieldsList() kullanılır:

DLEXFields::Init();                              // tanımları dosyadan yükler
$tanimlar = DLEXFields::FieldsList($row, 'site'); // $row bir haber satırı veya null

// $tanimlar ayrıştırılmış alan tanımlarını içerir

Tanımların kendisi engine/data/xfields.json dosyasında okunabilir biçimdedir. Bir alanın tanımında şu bilgiler bulunur:

AnahtarAnlamı
nameAlanın teknik adı (etiketlerde bunu kullanırsınız)
defaultVarsayılan değer / seçenek listesi
categoryBu alanın görüneceği kategoriler
allow_add_usergroupsHangi gruplar doldurabilir
dynamicÇoklu değer kabul ediyor mu. Doluysa değerler \x01 ile ayrılır.
is_publicGenel erişimle ilgili bayrak (dosya alanlarında kullanılır)

Ek alan değerlerini yazmak

Haber kaydedilirken DLE, formdan gelen veriyi DLEXFields::Parse() ile işleyip $filecontents üretir ve bunu xfields sütununa yazar. Eklentiniz değer yazacaksa aynı biçimi üretmelidir:

$xf = array(
    'fiyat'       => '19.90',
    'stok_kodu'   => 'ABC-123',
);

$parcalar = array();
foreach ($xf as $ad => $deger) {
    // Kaçışlar: | -> &#124;   yeni satır -> __NEWL__
    $ad    = str_replace(array("|", "\n"), array("&#124;", "__NEWL__"), $ad);
    $deger = str_replace(array("|", "\n"), array("&#124;", "__NEWL__"), $deger);
    $parcalar[] = $ad . "|" . $deger;
}

$xfields_text = implode("||", $parcalar);

$db->query("UPDATE " . PREFIX . "_post SET xfields = '" . $db->safesql($xfields_text) . "' WHERE id = '{$id}'");
!
Sütunun tamamını ezmeyin Yukarıdaki örnek xfields sütununu tamamen değiştirir; yani diğer alanların değerlerini siler. Var olan değerleri korumak istiyorsanız önce xfieldsdataload() ile okuyup, değişikliği o dizi üzerinde yapıp yeniden yazmalısınız.

Şablonlardaki etiketler

Tema geliştirirken ek alanlar şu etiketlerle kullanılır:

EtiketNe yapar?
[xfvalue_alan]Alanın değerini basar.
[xfgiven_alan] … [/xfgiven_alan]Alan doluysa içeriği basar.
[xfnotgiven_alan] … [/xfnotgiven_alan]Alan boşsa içeriği basar.
[xfvalue_thumb_url_alan]Görsel alanının küçük resim adresi.
[xfvalue_image_url_alan]Görsel alanının tam boy adresi.
[xfvalue_image_description_alan]Görselin açıklaması.

Üye (profil) ek alanları için başına profile_ eklenir: [profile_xfvalue_alan], [profile_xfgiven_alan], [profile_xfnotgiven_alan].

Çoklu değerli (dynamic) alanlarda belirli bir kaydı seçmek için item özniteliği kullanılır: [xfvalue_ozellikler item="2"].

Panel izni

Ek alan yönetimi admin_xfields izniyle korunur (engine/inc/xfields.php). Üye ek alanları için ayrıca admin_userfields izni vardır. Kendi modülünüzde bu izinleri Admin Panel Modülü'nde anlatıldığı gibi kontrol edebilirsiniz.

Ek alan kontrol listesi

  • Değerleri okumak için xfieldsdataload() kullanıyorum (elle ayrıştırmıyorum).
  • \x01 ayırıcısını çoklu değerlerde dikkate alıyorum.
  • Yazarken | ve yeni satır kaçışlarını uyguluyorum.
  • Sütunun tamamını ezmiyorum (önce oku, değiştir, yaz).
  • Tema etiketlerini kullanırken alan adının dynamic olup olmadığını kontrol ediyorum.
  • Çıktıları htmlspecialchars() ile kaçırıyorum.

Sırada: Dosya İşlemleri (DLEFiles).