Kod Konvansiyonları

1.8k görüntülenme Markdown

Kod tabanı bilinçli olarak tek bir biçimde yazılır. Buna uyan kod, içinde durduğu dosya gibi okunur; başkasının yazdığını ilan etmez.

Genel Bakış

Bu kuralların çoğu, tersinin gerçek bir arızaya yol açtığı için vardır: varsayılansız okunan bir değer, meşru bir sıfırı yutan doğruluk kontrolü, sorguya ulaşan kaçırılmamış bir girdi.

Bir kurulumun içinde yazdığınız her şey için geçerlidir: modüller, temalar, kanca dinleyicileri ve bunları destekleyen kod.

Referans

Girdi ve Çıktı

Beş yardımcı, normalde uzanacağınız yerleşiklerin önünde durur. Hepsi statiktir ve varsayılanları vardır; okunacak şey ad değil imzadır.

Filter::init() İstekten gelen her değer. Superglobal'ler asla doğrudan okunmaz.
Utility::jencode() JSON kodlama. Sizinkilerin üzerine üç seçenek zorlanır; böylece çıktı her çağrı noktasında aynı olur.
Language::gc() İnsanın okuduğu her şey. Metin, tek bir dilde bir koşulun ya da exception'ın içine yazılmaz.
LinkGenerator::admin() Panel adresleri. Sabit yazılmış bir yol, admin dizini ya da rota çevirisi değiştiği anda kırılır.
Utility::strtolower() Harf dönüşümü; dil-farkındalıklı biçim ile PHP'nin yerleşiği Türkçede aynı sonucu vermez.
imzalar
// coremio/classes/Filter.php
public static function init($arg = null, $mod = false, $special = false);
public static function GET($arg = '');
public static function POST($arg = '');
public static function REQUEST($arg = '');
public static function FILES($arg = '');
public static function SERVER($arg = '');
public static function html_clear($arg = null, $allow = '');
public static function route($arg = '', $special = '');
public static function phone($arg = '');

// coremio/classes/Utility.php
public static function jencode($string = '', $flags = 0): string|false;
public static function jdecode($string = '', $mode = false);
public static function strtolower($str, $encode = 'UTF-8');
public static function strtoupper($str, $encode = 'utf8');
public static function AppAdress($prefix = false);

// coremio/classes/Language.php   -   coremio/classes/LinkGenerator.php
public static function g($key = '', $replaces = [], $slang = ''): string|int|array|bool;
public static function gc($name = '', $replaces = [], $slang = ''): string|int|array|bool;
public static function selected(): string;
public static function admin($route = '', $params = [], $lang = '', $wqs = []): string|bool;
public static function client($route = '', $params = [], $lang = '');
public static function wQS(null|string|bool $url, string|array $params = []): string;

Filter::init, Parametre Parametre

Birinci argüman kaynağı ve anahtarı adlandırır. GET/, POST/, REQUEST/, FILES/ ya da SERVER/ öneki diziyi seçer, sonraki bölü işaretleri dizinin içine yürür. Önek yoksa argüman, temizlenecek düz bir değer sayılır.

birinci argüman
$id   = Filter::init('POST/id', 'rnumbers');          // $_POST['id']         -> int
$name = Filter::init('POST/user/name', 'hclear');     // $_POST['user']['name']
$op   = Filter::init('REQUEST/operation', 'route');   // $_REQUEST['operation']
$ip   = Filter::init('SERVER/REMOTE_ADDR', 'ip');     // $_SERVER['REMOTE_ADDR']
$safe = Filter::init($someString, 'hclear');          // öneksiz: elinizdeki değeri temizler

İkinci argüman serbest bir dize değil, kapalı bir sözlüktür. Neyin hayatta kalacağına, hangi tipin döneceğine ve eksik bir anahtarın neye dönüşeceğine o karar verir. Son sütun önemlidir: cevap tek bir değer değildir, tek bir koruma her modu kapsamaz.

$modHayatta kalan$specialEksik anahtar döndürür
verilmedideğer olduğu gibitek başına kullanılırfalse
hclearetiketler silinir, önce varlıklar çözülüryok sayılır''
dtexthclear ile aynıyok sayılır''
textetiketler silinir, sonra tırnaklar varlığa çevriliryok sayılır''
lettersa-zA-Z ve etkin dilin kendi harflerieklenir''
letters_numbers0-9a-zA-Zeklenirfalse
noun0-9a-zA-Z, virgül, nokta, boşlukeklenir''
numbersrakamlar ve eksi işaretieklenirfalse
rnumbersyukarıdakinin int hâlieklenir0
amountrakam, eksi, nokta, virgül; dize kalıreklenir''
ratevirgül noktaya döner, fazla noktalar atılır, float olureklenir0.0
identityrakamlar ve eksi işaretiyok sayılırfalse
ip0-9a-zA-Z, eksi, nokta, iki noktaeklenirfalse
email0-9a-zA-Z ve @ . + _ -yok sayılır''
domainharf, rakam, nokta, eksi; küçük harfe çevriliryok sayılır''
folder0-9a-zA-Z ve / - _ .eklenir''
file0-9a-zA-Z, dil harfleri ve - _ .eklenir''
route0-9a-zA-Z ve - _ .; önce ../ silinireklenir''
passwordhiçbir şey silinmez, ham değer döneryok sayılırfalse

Üçüncü argüman bir varsayılan değer değildir. Modun kurduğu olumsuzlanmış karakter sınıfının içine eklenen bir parçadır. Saydığınız karakterler kadar filtreyi genişletir.

üçüncü argüman, ölçülmüş çıktısıyla
$_POST['name'] = ' <b>Ada</b> Lovelace ';

Filter::init('POST/name', 'letters_numbers');        // 'AdaLovelace'
Filter::init('POST/name', 'letters_numbers', ' ');   // ' Ada Lovelace '   boşluk geri girer
Filter::init('POST/name', 'password');               // ' <b>Ada</b> Lovelace '  dokunulmaz

$_POST['rate'] = '1.234,50';
Filter::init('POST/rate', 'amount');                 // '1.234,50'   dize
Filter::init('POST/rate', 'rate');                   // 1234.5       float

İki yardımcı da bir dosyaya karşı çözülen bir anahtar alır. İkisi de ikinci bir dizi kabul eder ve bu dizi dil kodu değildir.

Çeviride bu dizi düz bir ara-değiştir işlemidir. Anahtarlar, yer tutucuların kayıtlı metinde göründüğü hâlidir, süslü parantezler dahil. Addan hiçbir şey çıkarılmaz.

yazan taraf, sonra okuduğu dosya
// Böyle yazılır:
$text = Language::gc('admin/services/cancel-credit-log-desc', ['{service_id}' => 41]);
// '#41 nolu hizmet iptal iadesi'

// coremio/locale/tr/cm/admin/services.php dosyasından okunur:
return [
    'cancel-credit-log-desc' => '#{service_id} nolu hizmet iptal iadesi',
];

// gc() bir bileşen dosyasını adresler: coremio/locale/<dil>/cm/ altında <klasör>/<dosya>/<anahtar>.
// g()  bir paket dosyasını adresler:   coremio/locale/<dil>/ altında <dosya>/<anahtar>.
$hint = Language::g('needs/password-needs-special', ['{characters}' => '! @ # $']);

Bağlantıda ise dizi, bir rota deseninin yer tutucularını sırayla doldurur. Yer tutucusu olmayan bir rota diziyi yola eklemek yerine yok sayar. Sorgu dizesi asla o yuvaya girmez, dördüncü argümandır.

rota haritası, sonra karşıladığı çağrılar
// coremio/locale/tr/admin-routes.php   ['url deseni', 'controller yolu']
return ['admin-routes' => [
    'services'    => ['services',            'services'],
    'users-1'     => ['users/(?)',           'users/(1)'],
    'financial-2' => ['financial/(?)/(?)',   'financial/(1)/(2)'],
]];

LinkGenerator::admin('services');                        // {admin}/services
LinkGenerator::admin('services', ['detail', 5]);         // {admin}/services   (?) yok, argümanlar düşer
LinkGenerator::admin('users-1', ['detail']);             // {admin}/users/detail
LinkGenerator::admin('financial-2', ['coupons', 'add']); // {admin}/financial/coupons/add

// Sorgu dizesi dördüncü argümandır; üçüncüsü dildir.
LinkGenerator::admin('users-1', ['detail'], '', ['id' => 42, 'tab' => 'invoices']);
// {admin}/users/detail?id=42&tab=invoices

// Elinizde zaten bir URL varsa wQS() kullanın; ? mi & mi gerektiğini kendisi seçer.
LinkGenerator::wQS($url, ['tab' => 'cards']);

Değer Okuma

Her dizi anahtarını varsayılanla okuyun. Bu savunmacı bir alışkanlık değil, ölçülmüş bir maliyettir. Eksik anahtar uyarı üretir ve hata işleyicisi her uyarıyı bir disk yazımına çevirir.

değerler
// Doğru: null-safe ve "0", "1", 0, 1, null hepsinde tutarlı.
if ((int) ($data['enabled'] ?? 0) === 1) { }
$name  = $data['name'] ?? '';
$limit = (int) ($data['limit'] ?? 0);

// Yanlış: empty("0") true döner, yani "0" değeri kaybolur.
// if (!empty($data['enabled'])) { }

// Yanlış: gereksiz uzun ve cast'in söylemediği hiçbir şeyi söylemiyor.
// if (isset($data['enabled']) && (int) $data['enabled'] === 1) { }

Kodun Biçimi

KuralYazınYazmayın
Açılış etiketi<?php, şablonda <?=kısa açılış etiketi
Diziler[]array()
Varsayılanlar$x ?? $yisset($x) ? $x : $y
Tek ifadesüslü parantezsiztek satır için üç satırlık blok
Derin iç içelikerken return ya da throwiç içe koşullar
İmzalarparametre ve dönüş tipleritipsiz
Çok satırlı listelersondaki virgülyok
Dizelerinterpolasyon yoksa tek tırnakher yerde çift tırnak
Arrow functiontek ifadede kısa gövdetek ifadeyi süslü paranteze almak

Yorumlar

Varsayılan hiç yorum yazmamaktır. Yazmadan önce kodun onsuz okunamaz olup olmadığını sorun. Okunan koda yazılan yorum, zamanla gerçeklikten kopan bir gürültüdür. Gereken yorum neden'i açıklar, asla ne'yi açıklamaz ve İngilizce yazılır.

Üç tür yorumun kodda yeri yoktur. Bir şeyin nereden kopyalandığına dair notlar, geliştirme sürecine ait notlar ve zaten kendini söyleyen bir satırı tekrar eden açıklamalar.

Örnek

Bir operation ve dağıttığı anahtarları karşılayan iki dosya.

operation
public function update(Operation $operation): bool
{
    $operation->demo();

    $id = Filter::init('POST/id', 'rnumbers');
    if (!$id) throw new Exception(Language::gc('admin/example/error-id-required'));

    $name = Filter::init('POST/name', 'hclear');
    if ($name === '') throw new Exception(Language::gc('admin/example/error-name-required'));

    $data = [
        'name'    => $name,
        'enabled' => Filter::init('POST/enabled', 'rnumbers'),
    ];

    // Yeniden denemeler başarısızlık olarak saklanır; güncellenecek bir success kolonu yok.
    if (!$this->model->update($id, $data))
        throw new Exception(Language::gc('admin/example/error-save-failed', ['{id}' => $id]));

    return $operation->output([
        'status'   => 'successful',
        'redirect' => LinkGenerator::admin('users-1', ['detail'], '', ['id' => $id]),
    ]);
}
anahtarların çözüldüğü yer
// coremio/locale/tr/cm/admin/example.php
return [
    'error-id-required'   => 'Bir kayıt seçilmelidir.',
    'error-name-required' => 'Ad alanı zorunludur.',
    'error-save-failed'   => '{id} numaralı kayıt kaydedilemedi.',
];

// coremio/locale/tr/admin-routes.php
return ['admin-routes' => [
    'users-1' => ['users/(?)', 'users/(1)'],
]];

Tuzaklar

Üçüncü argüman iki ailede de dildir

LinkGenerator::admin($route, $params, $lang, $wqs) sorgu dizesini dördüncü sıraya koyar. Üçüncü sıraya yazılan bir dizi sessizce dil koduna dönüşür ve parametreler kaybolur. Statik çeviri yardımcıları değiştirmeleri ikinci, dili üçüncü alır. Arkalarındaki instance metodu ise ikisini ters alır: Language::g($key, $replaces, $slang) karşısında $lang->get($key, $slang, $replaces). Hatırladığınız imzayı değil, çağırdığınız imzayı okuyun.

Eksik anahtar null olarak dönmez

Moda göre false, '', 0 ya da 0.0 döner, null asla dönmez. Yani filtre çağrısından sonra yazılan ?? $varsayilan ölü koddur ve !== null ile yazılan bir varlık kontrolü her zaman doğrudur. Modun gerçekten döndürdüğü değerle karşılaştırın.

Doğruluk kontrolü varlık kontrolü değildir

"0" değeri bir ayar, bir adet ya da bir durum için gerçek bir cevaptır ve doğruluk testi onu çöpe atar. Açıkça karşılaştırın ya da cast edip karşılaştırın.

İçinde bulunduğunuz dosyaya uyun

Yerel bir desen bu sayfayla çelişiyorsa genellikle yerel desen kazanır. Tek bir dosyanın içindeki tutarlılık, bir belgeyle tutarlılıktan daha değerlidir.

Faydalı oldu mu?

Geri bildiriminiz için teşekkürler!

Hâlâ Yardıma mı İhtiyacınız Var?

Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.