Özel Alan Ekleme
Bir müşteriye ya da talebe kolon eklemeden ek bilgi iliştirin.
Genel Bakış
"Özel alan" adını iki motor paylaşır. Müşteri profili alanları users_custom_fields içinde dil başına tanımlanır, değerleri anahtar/değer satırlarıdır. Talep alanları tickets_custom_fields içinde iki eksene bağlanır.
İkisinde de şema değişikliği gerekmez: bir tanım satırı eklersiniz, değer genel bir depoya düşer.
Ön Koşullar
- Tanım ekranlarına erişen bir operatör hesabı ya da ayarlar ve talepler kapsamlı bir jeton.
- Kanca mekanizmasına aşinalık; dönüşüm iki filtre kancasıyla yapılır.
- Kurulu dil kodları: tanım dil başına bir satırdır, yani iki dil iki id demektir.
Yapı
Tanım ile değer ayrıdır; değer satırının adı field_ ile tanım id'sinin birleşimidir.
| Tablo | Ne tutar | Anahtarı |
|---|---|---|
users_custom_fields | Dil, tip, etiket, seçenekler, işaretler, sıra | id, dil başına bir satır |
users_informations | Değer, metin olarak | owner_id ve field_{id} |
tickets_custom_fields | Talep alanı ve departmanı | id; etiket ve tip _lang ikizinde |
tickets_access_groups | Yanıt tarafındaki gruplama ve alan id'leri | id; ilişki grupta durur |
Depo tipsiz metindir: çok seçimli alan virgülle birleşir, boş cevap eksik satır değil boş dizedir.
Adım Adım
Alanı Tanımlayın
- Tanımı dil başına bir kez oluşturun: Ayarlar altındaki müşteri alanları listesi ya da API kaynağı.
- Tipi seçin:
text,textarea,select,checkbox,radio; seçim tiplerindeoptionsvirgüllü liste alır. - Görünürlük işaretlerini ayarlayın; bağımsız mantıksal değerlerdir ve birlikte çalışırlar.
- Satıra verilen id'yi not edin; kodunuz etiketi değil id'yi kullanır.
Değeri Okuyun ve Yazın
- Bilgi yardımcısıyla,
field_{id}anahtarlarıyla yazın. - Bilgi okuyucusuyla okuyun: satırı olmayan ad eksik anahtar olarak değil
nullolarak döner. - Okuyucu istek boyunca hafızaya alır; yazdıktan sonra üçüncü argümanla atlayın.
- "Cevaplanmadı" anlamlıysa boşaltmak yerine silin: yedek yol yalnız kaldırılmış satırı arar.
Değeri Dönüştürün
- Kaydetme filtresine dinleyici kaydedin: her
field_*anahtarı için bir kez, yazmadan önce. - Okuma filtresine kaydedin: her okumada, satırlar toplandıktan sonra.
- İkisini simetrik tutun; yoksa profil ekranında şifreli metin kalır.
- Alan id'sini kontrol edin: iki filtre de her özel alan için çalışır.
Referans
Tanım İşaretleri
Altısının beşi 0 ya da 1 tutan tam sayı kolonudur; status bir dizedir ve onu diğerleri gibi ele alan kod her alanı kapalı okur.
active ya da inactive; kapalı alan yalnız operatörün listesinde görünür.
Değer Yardımcısı
// Upsert. $values bir ad => değer haritasıdır; özel alanın adı "field_{id}" biçimindedir.
// En az bir satır yazıldığında true döner.
public static function AddInfo($owner_id = 0, $values = []);
public static function setInfo($owner_id = 0, $values = []); // AddInfo takma adı
// Okuma. $names bir dizidir (virgüllü dize de kabul edilir ve bölünür).
// İSTENEN HER ad dönen haritada bulunur; satırı olmayan ad null okunur.
// $noCache = true istek-içi hafızayı atlar; yazdıktan hemen sonra buna ihtiyacınız olur.
public static function getInfo($owner_id = 0, $names = [], $noCache = false): array;
// Satırları tamamen kaldırır. $name tek bir ad ya da ad dizisidir.
public static function deleteInfo($owner_id = 0, $name = ''): int|bool;
// Var olan bir değerin satır id'si, yoksa 0.
public static function isInfo($owner_id = 0, $name = ''): int;
// Ters arama: bu değeri hangi müşteriler taşıyor. $first = true tek satır döndürür.
public static function findInfo($name = '', $value = '', $first = true): array;
// Bütünlük kapısı. Hâlâ boş olan her şey için [alan anahtarı => etiket] döner;
// boş dizi, hesabın müşteri panelini kullanabileceği anlamına gelir.
public static function missing_required_fields($id = 0): array;
phone ve company_name müşteri kaydına da yansır.
checkbox virgülle birleşir; diğer dört tip düz dizedir.
İki Değer Filtresi
İkisi de referansla ateşlenir ve field_ ile başlayan anahtarlarla sınırlıdır; timezone onlara hiç ulaşmaz.
// User::AddInfo() içinden, insert ya da update'ten hemen önce ateşlenir.
// $value mixed, referansla. Burada bıraktığınız şey saklanır.
// $field_id int, "field_5" içinden ayrıştırılan tanım id'si.
// $owner_id int, değerin ait olduğu müşteri.
Hook::add('filter:custom_field.save_value', 10, function (&$value, $field_id, $owner_id) {
// ...
});
// User::getInfo() içinden, satırlar toplandıktan sonra ve dönüşten önce ateşlenir.
// Aynı üç argüman, aynı sıra.
Hook::add('filter:custom_field.load_value', 10, function (&$value, $field_id, $owner_id) {
// ...
});
$value'yu yerinde değiştirin; dönüş kullanılmaz.
Tanımlar Nerelerde Okunur
Müşteriye bakan her sayfa kendi filtresini uygular ve bunlar bilerek farklıdır.
| Sayfa | Okuyucu | Uyguladığı filtre |
|---|---|---|
| Hesap profili | Hesap modelinde get_custom_fields() | aktif, gizli değil, müşterinin dili, rank sırası |
| Kayıt formu | Kayıt modelinde get_custom_fields() | aynısı, artı signForm = 1 |
| Fatura görünümü | invoice_custom_fields() | invoice = 1; boş değerler atılır |
| Tek alan doğrulaması | get_custom_field() | liste filtresi, tek id'ye |
| Operatör sayfaları | Kullanıcı modelinde get_custom_fields() | yalnız dil; gizli alanlar dahil |
Talep Alanları ve İki Ekseni
Aynı tanım tablosunu iki oluşturucu tüketir; iki üyelik iki ayrı yerde saklanır.
// Departman ekseni, talep OLUŞTURMA formu kullanır. $did = 0 her alanı döndürür.
// Satırlar yerelleştirilmiş name, description, type, properties, options ve
// department_name taşır. Sıra: did DESC, sonra rank ASC.
public static function custom_fields($lang = '', $did = 0, $status = '');
// Erişim grubu ekseni, YANIT oluşturucunun erişim bilgisi satırları kullanır. Grubun
// kendi virgüllü alan id listesini okur ve alanları TAM O SIRAYLA döndürür; bu, operatörün
// sürükle bırakla belirlediği sıradır. Boş grup [] döndürür.
public static function custom_fields_by_group($lang = '', $groupId = 0, $status = 'active');
// Seçiciyi kurmak için grupların kendisi.
public static function access_groups($lang = '', $status = 'active');
public static function get_access_group($id = 0, $lang = '', $select = '');
$status boş geçilirse kapalı tanımlar da döner.
password temizleyiciden geçmez.
API Üzerinden
| Uç | Ne yapar | Not |
|---|---|---|
GET /settings/client-fields | Tanımları listeler | Dil bir parametredir |
POST /settings/client-fields | Tek bir tanım oluşturur | İki dil, iki çağrı |
PATCH /settings/client-fields/{id} | Tek bir tanımı günceller | İşaretlerde kısmi değil: gönderilmeyen işaret 0 olur |
PUT /settings/client-fields/order | Listeyi sıralar | Rank gösterim sırasını belirler |
GET /tickets/custom-fields | Talep tanımlarını listeler | Ayrı motor ve kapsam |
Örnek
Değeri veritabanında asla açık durmaması gereken bir alan.
// Aynı mantıksal alanın, kurulu her dildeki tanım id'leri. Bir müşteri alanı dil başına
// bir satırdır, yani tek bir etiket birden çok id'ye karşılık gelir.
const ACME_TAX_FIELD_IDS = [11, 12];
Hook::add('filter:custom_field.save_value', 10, function (&$value, $field_id, $owner_id) {
if (!in_array($field_id, ACME_TAX_FIELD_IDS, true)) return;
$value = trim((string) $value);
if ($value === '') return; // boş cevap boş kalır
$value = Crypt::encode($value, Config::get('crypt/system') . '_ACME_TAX');
});
Hook::add('filter:custom_field.load_value', 10, function (&$value, $field_id, $owner_id) {
if (!in_array($field_id, ACME_TAX_FIELD_IDS, true)) return;
if ((string) $value === '') return;
// decode(), bu dinleyici var olmadan önce yazılmış bir değerde false döner; bu yüzden
// üyenin cevabını boşaltmak yerine özgün metin korunur.
$plain = Crypt::decode((string) $value, Config::get('crypt/system') . '_ACME_TAX');
if ($plain !== false) $value = $plain;
});
Aynı sözleşmenin okuma tarafı; sonraki hiçbir kod değerin şifreli olduğunu bilmez.
$uid = 42;
// İstediğiniz adları isteyin. Her ad geri döner, satırı olmayanlar null olarak.
$info = User::getInfo($uid, ['field_11', 'gsm']);
$tax = (string) ($info['field_11'] ?? '');
// Çok seçimli bir alan, virgülle birleştirilmiş tek bir dizedir; ayırmayı siz yapın.
$picked = array_values(array_filter(explode(',', (string) ($info['field_12'] ?? ''))));
// Yazma. Aynı adlar, aynı "field_{id}" kuralı.
User::setInfo($uid, ['field_11' => 'GB123456789']);
// Okuyucu istek başına hafızaya alır; yazdıktan sonra üçüncü argümanla yeniden okuyun.
$fresh = User::getInfo($uid, ['field_11'], true);
// Bir satırı kaldırmak, boş dize yazmakla aynı şey değildir: hesabı hiç cevap vermemiş
// gibi gösteren yalnızca kaldırmadır.
if ($tax === '') User::deleteInfo($uid, ['field_11']);
Operatör tarafı, modülünüz kendi alanını getiriyorsa: kurulumda dil başına bir tanım, id'ler saklanır.
$ids = [];
foreach (['en' => 'VAT Number', 'tr' => 'Vergi Numarası'] as $lang => $label) {
$ids[$lang] = WDB::insert('users_custom_fields', [
'lang' => $lang,
'type' => 'text', // text | textarea | select | checkbox | radio
'name' => $label,
'status' => 'active', // DİZE, aşağıdaki her bayrağın aksine
'required' => 0,
'uneditable' => 0,
'client_hidden' => 0,
'invoice' => 1,
'signForm' => 1,
'options' => '', // virgülle ayrılmış; select/checkbox/radio için
'rank' => 90,
]) ? WDB::lastID() : 0;
}
// Id'leri saklayın: alana giden tek kararlı tutamaktır ve dil başına farklıdır.
Config::setd('acme_vat_field_ids', Utility::jencode($ids));
Tuzaklar
Dil sürümlerini birleştiren ortak bir üst id yoktur; birinde gizlemek diğerini görünür bırakır. Id'leri küme olarak toplayın.
Kapı her zorunlu alan cevaplanana kadar profile yönlendirir, o yüzden zorunluluk sorguları gizli alanları dışlar. Kendi kuralınızı da oraya uygulayın.
Listeden çıkarmak, sahte bir gönderimin yok saydığı bir arayüz kararıdır; yazımı asıl durduran tekil okuyucudur. Kural iki okuyucuya birden yazılır.
Yeni bir işaret şunları ister: kolon, yazma yolu, form ve JavaScript dalları, liste kolonu, dil anahtarları, API'nin iki yönü ve tüm müşteri sayfaları. Kolonu koddan önce uygulayın.
Ad ve değer çiftleri verir, boş değerleri atar; id ile arayan bir test her zaman "yok" der.
İlgili Makaleler
Geri bildiriminiz için teşekkürler!
Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.