Aşağıdaki kod stili Cotonti CMF çekirdeği ve resmi uzantıların geliştirilmesi için kullanılır. Çekirdeğe talep kodu çekmek istiyorsanız, bunu kullanmayı düşünün. Cotonti'ye dayalı uygulamanız için sizi bu kod stilini kullanmaya zorlamıyoruz. Size daha uygun olanı seçmekte özgürsünüz.
Bu genel kurallar, başka bir kural tanımlanmamışsa, projedeki tüm kaynak kodu dosyalarını (HTML, PHP, CSS, JS, vb.) dikkate alır.
Satır uzunluğu konusunda kesin bir sınır yoktur. Kodunuzdaki her metin satırı en fazla 120 karakter uzunluğunda olmalıdır.
Satır sonunu, 120 karaktere en yakın kırılma noktası olmak zorunda değil, en estetik anlam ifade eden yere koyun.
…genel kurallara ek olarak
PHP kodu, PSR-12, PSR-1 kodlama standartlarını ve PSR-4 otomatik yükleme standardını takip etmelidir.
Eğer PhpStorm kullanıyorsanız, gerekli kod stilini korumanıza yardımcı olabilir. Bunu açmak için Ayarlar
→ Editör
→ Kod Stili
→ PHP
→ Şuradan Ayarla
→ PSR12
yolunu izleyebilirsiniz.
<?php
veya <?=
açılış etiketlerini kullanmalı ve <?
gibi diğer etiket varyasyonlarını kullanmamalıdır.?>
etiketi olmamalıdır.$a + $b
, $string = $foo . 'bar'
, $i++
, ancak $a+$b
gibi değil.$one, $two
, ancak $one,$two
şeklinde değil.===
(ve eşitsizlik !==
) kullanılmalıdır.declare(strict_types=1);
yönergesi ile sıkı tür belirlemenin etkinleştirilmesi önerilir.//
ile başlamalıdır, #
ile değil.Tüm PHP dosyaları, PHPDoc biçiminde bazı dokümantasyon bilgileri içermelidir.
Başlığın, bu dosyada kullanılan ancak başka bir yerde tanımlanan değişkenleri açıklaması çok iyidir.
Yeni dosyalar için standart başlık (bu başlık şablonu tüm Cotonti dosyalarının başlangıcına eklenmelidir):
1 2 3 4 5 6 7 8 9 |
/** * @package {PACKAGENAME} * @version {VERSION} * @copyright (c) 2008-2023 Cotonti Team * @license BSD License * * @var array<string, mixed> $user * @var XTemplate $t */ |
@version
etiketi isteğe bağlıdır. Örneğin, bir eklenti geliştiriyorsanız, sürüm bilgisi zaten eklenti kurulum dosyasında tanımlandığı için @version
etiketini belirtmenize gerek yoktur ve bu diğer geliştiricileri yanıltabilir.
Sınıfı yorumlamayı unutmayın. Sınıfların ayrı bir @package tanımı olması gerekir, bu, başlık paket adıyla aynıdır.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * Cotonti MySQL Veritabanı adaptör sınıfı. * Standart PHP PDO sınıfına, Cotonti'ye özgü bazı ihtiyaçları karşılayan * küçük bir eklenti, kullanışlı fonksiyonlar ve sorgu oluşturucu içerir. * * @package cotonti * * @property-read int $affectedRows Son sorgudan etkilenen satır sayısı * @property-read int $count Toplam sorgu sayısı * @property-read int $timeCount Toplam sorgu yürütme süresi */ class MySQL extends Adapter |
Fonksiyonları yorumlamayı unutmayın. Her fonksiyonun en azından ne yaptığına dair bir açıklaması olmalıdır. Ayrıca parametreleri de belgelemek önerilir. @param
, @return
, @throws
sırasıyla kullanın.
1 2 3 4 5 6 7 |
/** * Bir tabloda bulunan toplam kayıt sayısını döndürür. * @param string $tableName Tablo adı * @return int * @throws Exception Eğer tablo adı mevcutsa */ public function countRows( $tableName ) |
Yerel türlerin kullanımı nedeniyle @param
veya @return
etiketleri gereksiz olduğunda, bunlar atlanabilir:
1 2 3 4 5 6 7 |
/** * Görevi yürütür. */ public function handle(AudioProcessor $processor ): void { // } |
Ancak, yerel tür jenerik olduğunda, jenerik türü @param
veya @return
etiketleri ile belirtin:
1 2 3 4 5 6 7 8 |
/** * Gönderiye ait ekleri alır. * @return array<int, Attachment> */ public function attachments(int $postId ): array { // ... } |
Tüm adlar açıklayıcı ancak öz olmalıdır. Bir sınıfın veya değişkenin adını gördüğünüzde, ne için kullanıldıkları açık olmalıdır. Örneğin: $CurrentUser
, getUserData($id)
.
Sınıf adları PascalCase formatında olmalıdır. Örneğin: Controller
, Model
.
Sabitler tamamen büyük harflerle ve alt çizgi ayracı kullanılarak tanımlanmalıdır. Örneğin: STATUS_PUBLISHED
.
Dizin/namespace adları küçük harflerle yazılmalıdır.
Sınıfın özel (private) özelliklerini ve metotlarını belirtmek için alt çizgi kullanılmaz.
Değişken adları camelCase biçiminde olmalıdır. İlk kelime küçük harfle başlamalı ve sonraki her kelime büyük harfle başlamalıdır. Örneğin: $currentUser
doğrudur, ancak $current_user
ve $currentuser
yanlıştır.
Tek karakterli değişken adlarının kullanılabileceği durumlar: dil dizgeleri: $L
, dizge kaynakları: $R
ve bir döngü yapısının indeks değişkeni olarak kullanıldığında.
Döngü İndeksleri:
Dış döngünün indeksi her zaman $i
olmalıdır. Eğer içinde bir döngü daha varsa, onun indeksi $j
, ardından $k
ve böyle devam eder. Eğer döngü zaten anlamlı bir isimle tanımlanmış bir değişken tarafından indeksleniyorsa, bu kural uygulanmaz. Örnek:
1 2 3 4 5 |
for ( $i = 0; $i < $outerSize ; $i ++) { for ( $j = 0; $j < $innerSize ; $j ++) { foo( $i , $j ); } } |
Fonksiyon ve metot adları camelCase formatında olmalıdır. İstisna olarak, Cotonti çekirdek fonksiyonları farklı olabilir. İyi fonksiyon adları şunlardır: printLoginStatus()
, getUserData()
vb.
Cotonti içinde, isim çakışmalarını önlemek için tüm fonksiyonlarda standart cot_
öneki kullanılır. Çekirdek API’nin yeniden kullanılabilir olması için bu bir standarttır: cot_mailPrepareAddress($address)
.
Ancak, eğer fonksiyonlarınızı yalnızca kendi eklentiniz içinde kullanacaksanız, cot_
önekini kullanmanız zorunlu değildir. Eklenti API’niz içinde kendi önekinizi kullanabilirsiniz.
Fonksiyon Argümanları değişken adlarıyla aynı kurallara tabidir.
Buradaki temel felsefe, tembellik uğruna kodun açıklığını bozmamaktır. Ancak, bu biraz sağduyu ile dengelenmelidir: Örneğin, printLoginStatusForAGivenUser()
çok uzun bir isim olur, bunun yerine printUserLoginStatus()
veya sadece printLoginStatus()
daha iyi bir seçimdir.
Tüm PHP türleri ve değerleri küçük harflerle kullanılmalıdır. Buna true
, false
, null
dahildir.
Tür dönüşümü için fonksiyonlar yerine operatörleri kullanıyoruz. Sadece kısa formlarını kullanıyoruz ve operatörden sonra bir boşluk bırakıyoruz.
1 2 3 4 5 |
$value1 = (int) $argument1 ; // doğru $value2 = (bool) $argument2 ; // doğru $value3 = (integer) $argument3 ; // yanlış $value4 = intval ( $argument2 , 8); // sadece gerçekten gerekli ise |
Var olan bir değişkenin türünü değiştirmek kötü bir uygulama olarak kabul edilir. Gerçekten gerekmedikçe bu tür kod yazmaktan kaçının.
1 2 3 4 5 |
public function save(Transaction $transaction , int $argument2 = 100) { $transaction = new Connection; // kötü $argument2 = 200; // iyi } |
Eğer string içinde değişkenler veya tek tırnak bulunmuyorsa, tek tırnak kullanın.
1 |
$str = 'Böyle olmalı.' ; |
Eğer string içinde tek tırnak varsa, fazladan kaçış karakteri kullanmamak için çift tırnak kullanabilirsiniz.
Değişken yerleştirme:
1 2 |
$str1 = "Merhaba $username!" ; $str2 = "Merhaba {$username}!" ; |
Aşağıdaki kullanım izin verilmez:
1 |
$str3 = "Merhaba ${username}!" ; |
Bitişik ekleme (Concatenation)
Stringleri birleştirirken nokta operatörünün etrafına boşluk bırakın:
1 |
$name = 'Cotonti' . ' CMF' ; |
Eğer string uzun ise şu format kullanılmalıdır:
1 2 3 |
$sql = 'SELECT * ' . 'FROM post ' . 'WHERE id = 121 ' ; |
Diziler için kısa dizi sözdizimini kullanıyoruz.
1 |
$arr = [3, 14, 15, 'Cotonti' , 'CMF' ]; |
Eğer bir satıra sığmayacak kadar çok eleman varsa, her eleman ayrı bir satıra yerleştirilir. Son elemenden sonra bir virgül konulur.
1 2 3 4 5 |
$mail = [ 'to' => 'user@domain.com' , 'from' => [ 'admin@site.com' , 'SiteTitle' ], 'cc' => [[ 'user2@example.com' , 'User2' ], 'user3@example.com' , 'User4 ' ], ]; |
1 2 3 4 5 6 7 8 9 10 |
if ( $expr1 ) { // if gövdesi } elseif ( $expr2 ) { // elseif gövdesi } else { // else gövdesi; } // Aşağıdaki kullanım YASAKTIR: if (! $model && null === $event ) throw new Exception( 'test' ); |
elseif
anahtar kelimesi, tüm kontrol yapısı anahtar kelimelerinin tek kelime gibi görünmesini sağlamak için else if
yerine kullanılmalıdır.
Parantez içindeki ifadeler, her bir sonraki satır en az bir kez girintilenerek birden fazla satıra bölünebilir. Bunu yaparken, ilk koşul bir sonraki satırda olmalıdır. Kapanış parantezi ve açılış süslü parantez, kendi satırlarında bir boşluk ile yerleştirilmelidir. Koşullar arasındaki mantıksal operatörler (&&
, ||
) satır başında olmalıdır.
1 2 3 4 5 6 |
if ( $expr1 && $expr2 ) { // if gövdesi } |
return
kullanıldıktan sonra mümkünse else
kullanımından kaçınılmalıdır:
1 2 3 4 5 6 |
$result = $this ->getResult(); if ( empty ( $result )) { return false; } else { // sonucu işle } |
Bunun yerine şu şekilde yazılmalıdır:
1 2 3 4 5 6 |
$result = $this ->getResult(); if ( empty ( $result )) { return false; } // sonucu işle |
switch
yapısı aşağıdaki gibi olmalıdır. Parantezlerin, boşlukların ve süslü parantezlerin yerleşimine dikkat edin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
switch ( $expr ) { case 0: echo 'Birinci durum, break ile sonlandırılıyor' ; break ; case 1: echo 'İkinci durum, break içermiyor ve devam ediyor' ; // break yok case 2: case 3: case 4: echo 'Üçüncü durum, break yerine return kullanıyor' ; return ; default : echo 'Varsayılan durum' ; } |
Üçlü operatörler yalnızca çok basit işlemler için kullanılmalıdır. Tercihen sadece atama işlemlerinde kullanılmalı, fonksiyon çağrıları veya karmaşık işlemler için tercih edilmemelidir. Yanlış kullanıldığında okunabilirliğe zarar verebilir, bu yüzden yazım tasarrufu yapmak uğruna yanlış kullanımdan kaçının. Örnekler:
1 2 3 4 5 |
// Kullanım için kötü bir örnek ( $i < $size && $j > $size ) ? do_stuff( $foo ) : do_stuff( $bar ); // Kullanım için uygun bir örnek $min = ( $i < $j ) ? $i : $j ; |
"Sınıf" terimi, tüm sınıfları, arayüzleri ve trait'leri kapsar.
extends
ve implements
anahtar kelimeleri, sınıf adıyla aynı satırda olmalıdır. implements
listesindeki her öğe ayrı bir satıra yerleştirilebilir ve her satır bir kez girintilenmelidir. Böyle yapıldığında, listedeki ilk öğe yeni bir satırda olmalı ve her satırda yalnızca bir arayüz bulunmalıdır.Public ve protected değişkenler, herhangi bir metodun tanımlanmasından önce sınıfın en üstünde tanımlanmalıdır. Private değişkenler de sınıfın en üstünde tanımlanmalıdır, ancak yalnızca belirli birkaç metoda özgü olduklarında, ilgili metotların hemen önüne de eklenebilir.
Bir fonksiyonun açılış süslü parantezi, fonksiyon tanımının yer aldığı satırdan sonraki satırda olmalı ve kapanış süslü parantezi fonksiyon gövdesinden sonra yeni bir satıra yerleştirilmelidir.
Parametre listesindeki her virgülden sonra bir boşluk bırakılmalıdır.
1 2 3 4 |
function foo(int $arg1 , string & $arg2 , array $arg3 = []) { // fonksiyon gövdesi } |
Argüman listeleri, sonraki her satırın bir kez girintilendiği birden fazla satıra bölünebilir. Bunu yaparken, listedeki ilk öğe bir sonraki satırda OLMALIDIR ve satır başına yalnızca bir argüman OLMALIDIR.
1 2 3 4 5 6 7 |
public function aVeryLongMethodName( ClassTypeHint $arg1 , string & $arg2 , array $arg3 = [] ) { // metot gövdesi } |
Metotlar/fonksiyonlar tanımlanırken, her zaman parametrelerin ve dönüş değerlerinin yerel türlerini belirtin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// Doğru /** * Görevi yürütür. */ public function handle(AudioProcessor $processor ): void { // } // Yanlış /** * Görevi yürütür. * @param AudioProcessor processor * @return void */ public function handle( $processor ) { // } // Kötü /** * Görevi yürütür. */ public function handle( $processor ) { // } |
Bir metot veya fonksiyon çağrılırken, metot veya fonksiyon adı ile açılış parantezi arasında boşluk OLMAMALIDIR, açılış parantezinden sonra boşluk OLMAMALIDIR ve kapanış parantezinden önce boşluk OLMAMALIDIR. Parametre listesindeki her virgülden önce boşluk OLMAMALI, ancak virgülden sonra bir boşluk bulunmalıdır.
SQL ifadeleri genellikle okunaklı olması için biçimlendirme gerektirir, çünkü bazen oldukça uzun olabilirler. SQL ifadelerinin okunaklılığını artırmak için şu şekilde biçimlendirilmelidir:
1 2 3 4 5 |
$sql = 'SELECT p.*, u.* ' . 'FROM ' . Cot:: $db ->pages . ' AS p ' . 'LEFT JOIN ' . Cot:: $db ->pages . ' AS u ON u.user_id = p.page_ownerid ' . "WHERE p.page_ownerid = 1 AND p.page_cat = 'news' " . 'LIMIT 10' ; |
Kullanıcı girdilerini güvenli bir şekilde sorguya eklemek için parametreler kullanın (değişkeninizin tek tırnak içeremeyeceğinden emin olsanız bile, girdiye asla güvenmeyin):
1 2 3 4 |
$result = Cot:: $db ->query( 'SELECT * FROM ' . Cot:: $db ->forum_topics . ' WHERE ft_cat = :cat AND ft_id = :topicId' , [ 'cat' => $section , 'topicId' => $param ] ); |
Veritabanına Özgü SQL Kullanımından Kaçının
!=
) operatörü SQL-92 standardına göre <>
olarak tanımlanmıştır. Çoğu veritabanı !=
operatörünü destekler ancak <>
kullanımı önerilir.INSERT ... ON DUPLICATE KEY UPDATE
sadece MySQL'e özgü bir eklentidir.`
) kullanımı MySQL'e özgüdür. Bunun yerine CotDB::quoteTableName()
ve CotDB::quoteColumnName()
veya bunların kısa versiyonları CotDB::quoteT()
, CotDB::quoteC()
kullanın.let
, sabitleri tanımlamak için const
kullanın.const COLOR_ORANGE = "#ffa500"
. Sabitler gibi değişmeyen ancak farklı fonksiyon çağrılarında farklı değerler alabilecek değişkenler için const
kullanmalı ve camelCase formatında adlandırılmalıdır.===
(eşitsizlik için !==
) kullanılmalıdır.let single = 'single-quoted';
.alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
.
Thanked: 48 kez
Насчёт стиля по закрывающим фигурным скобкам - очень спорный вопрос. Мне удобнее когда скобки находятся друг над или под другом - сразу видно какая скобка к чему относится и компиляторы подсвечивают блоки кода и таким образом расположенные скобки. У вас почему-то приняли за ствндарт когда открывающая скобка в конце строки открывающей блок кода , а закрываюзщая где-то там под блоком. По-моему это плохой стиль для таких блоков.
Thanked: 180 kez
Касательно расположения скобок я того же мнения + привык за всю историю существования кота именно к такому положению. Но принятый за основу psr-12 гласит именно о таком "кривом" расположении ... типа этот стандарт международно признаный ...
Thanked: 217 kez
Предлагаемый вариант с фигурными скобками хорош тем, что экономит место на экране. Занимать целую строку открывающей скобкой так себе дело. Плюс практически в любом редакторе есть индикация закрывающей/открывающей скобки. Так что здесь рациональнее именно так.
По замене табуляторов на 4 пробела не совсем интересно. Хотя табуляторы в разных редакторах имеют разную длину, так что пробелами нерационально, зато гарантировано ровно будет. ((