PHP Kod Standartları
31-03-2015 Okuma Modu
Kurumsal bir firmada çalışıyorsanız yada kendi ekibinizle kod yazıyorsanız. Kodların düzeni çoğunlukla sorun olmuştur. Kimi her gördüğü ifadeyi UpperCase yazar kimi camelCase. Kimi if'in yanına süslü parantezi "{" kimi alt satırına süslü parantezi koyar. Böyle uzayıp gider.
Sonuçta her türlü yazdığınız kod çalışır fakat sizin kodlarınıza başka biri baktığı zaman yada tam tersi siz başkasının kodlarına baktığınız zaman bi afallarsınız. Bu ufak tefek detaylar yüzünden projeler uzayıp gider ve sizi daha çok uğraştırır.
Çözüm nedir?
Projeye başlamadan önce neyi nasıl kullanacağınızı karar verin, karar vermiş olduğunuz kuralların dökümantasyonunu hazırlayın. Bu sizin ekibinizin kod standartı olacaktır. Fakat bu yöntem hem sizi uğraştırır hem de yeterli değildir çünkü çalışma arkadaşlarınız değiştiğinde standartlarınızda zırt pırt değişir. Daha güzel bir yöntem var o da yazılım dünyasının abileri toplanmış oylama sonucu belli kurallar belirlemişler ve bu kuralları oylamaya devam ediyorlar. Bu çatının adı "PHP Framework Interop Group". Sizlerde bu gruba katılabilir yorumlarda bulunabilirsiniz.
Kimler var?
PSR - PHP Standart Tavsiyeleri
PHP-FIG tarafından 4+1 konu ele alınmış. Bunlar:
- PSR-0 : Autoloading(Otomatik Yükleme) Standartları { Artık Önerilmemektedir. PSR-4 yeni alternatifidir }
- PSR-1 : Temel Kodlama Standartları
- PSR-2 : Kodlama Stili
- PSR-3 : Logger Interface
- PSR-4 : Geliştirilmiş Autoloader
PSR-0 : Autoloading(Otomatik Yükleme) Standartları { Artık Önerilmemektedir. PSR-4 yeni alternatifidir }
- Bir namespace'in ve class'ın sahip olması gereken yapı\<Sağlayıcı Adı>\(<Namespace>\)*<Class Adı>
- Her namespace'in üst seviye bir namespace'i olması gerekir.
- Her namespace'e alt namespace'ler eklenebilir.
- Her namespace dosya sistemi tarafından yüklenirken DIRECTORY_SEPARATOR dönüştürülür.
- Class adındaki her "_" karakteri DIRECTORY_SEPARATOR dönüştürülür. Namespaces'lerdeki "_" karakterinin özel bir anlamı yoktur.
- Bir namespace'in ve class'ın sahip olması gereken yapı dosya sisteminden yüklendiğinde sonuna .php eklenir.
- Sağlayıcı adı, namespaces'ler ve class adları büyük veya küçük harflerin herhangi bir kombinasyonundan oluşabilir.
Bir kaç örnek
- \Doctrine\Common\IsolatedClassLoader =>/path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
- \Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
- \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
- \namespace\package_name\Class_Name =>/path/to/project/lib/vendor/namespace/package_name/Class/Name.php
Örnek Uygulama
Aşağıdaki örnek autoload fonksiyonu, PSR-0 standartların nasıl otomatik yüklendiğini gösterir.
<?php
function autoload($className)
{
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if ($lastNsPos = strrpos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
require $fileName;
}
spl_autoload_register('autoload');
PSR-1 : Temel Kodlama Standartları
- Sadece <?php ve <?= etiketlerini kullanın.
- PHP kodları için sadece UTF-8 (BOM suz) kullanın.
- Yan etkileri ve açıklamaları birbirinden ayırın.
- PSR-0 yada PSR-4 uygulayın.
- Class adlarını StudlyCaps olarak yazın.
- Class constant'larını tamamiyle büyük harfler ile yazılmalı ayraç olarak sadece "_" kullanılmalıdır.
- Metot adları camelCase kullanılarak yazılmalıdır.
Yan etki ve açıklama satırı ayrım örneği (side effect: = yan etki)
<?php
// side effect: change ini settings
ini_set('error_reporting', E_ALL);
// side effect: loads a file
include "file.php";
// side effect: generates output
echo "\n";
// declaration
function foo()
{
// function body
}
// şartlı tanımlamalar yan etki değil açıklamadır.
if (! function_exists('bar')) {
function bar()
{
// function body
}
}
PSR-2 : Kodlama Stili
- PSR-1’in devamıdır.
- Her satırda önerilen karakter sayısı 80, maksimum 120'dir.
- Satırlarda tab kullanmayın onun yerine 4 boşluk karakteri kullanın. Kod editörlerinizde bunun ayarlaması yapılıyor.
- Namespace ve use tanımlarının ardından bir satır boş bırakın.
- Operatörler ile değişkenler arasında bir karakter boşluk bırakın.
- Metot ve class oluşturduğunuzda açılan süslü parantezler “{” ismin bitişinde değil alt satırına açılmalı.
- true,false,null küçük kullanın.
- php kapama etikeni ?> kullanmayın.
Özet bir örnek
<?php
namespace Vendor\Package;
use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
class Foo extends Bar implements FooInterface
{
public function sampleFunction($a, $b = null)
{
if ($a === $b) {
bar();
} elseif ($a > $b) {
$foo->bar($arg1);
} else {
BazClass::bar($arg2, $arg3);
}
}
final public static function bar()
{
// method body
}
}
- Log tipi olarak Syslog Protocol(RFC 5424)'ün 8 tipi(debug, info, notice, warning, error, critical, alert ve emergency) tanımlanmalıdır.
-
İleti, bir string veya __toString() uygulayan nesne olmalıdır.
-
Mesaj içerisindeki yer tutucular gelen içerikteki anahtarla değiştirilebilir.
-
Yer tutucular süslü paranten içinde olmalıdır.
Log'lama verisi hazırlama (Interpolate = Aradaki veriyi değiştirmek)
<?php
/**
* Interpolates context values into the message placeholders.
*/
function interpolate($message, array $context = array())
{
// build a replacement array with braces around the context keys
$replace = array();
foreach ($context as $key => $val) {
$replace['{' . $key . '}'] = $val;
}
// interpolate replacement values into the message and return
return strtr($message, $replace);
}
// a message with brace-delimited placeholder names
$message = "User {username} created";
// a context array of placeholder names => replacement values
$context = array('username' => 'bolivar');
// echoes "User bolivar created"
echo interpolate($message, $context);
PSR-4 : Geliştirilmiş Autoloader
- \<NamespaceAdı>(\<AltNameSpaceler>)*\<ClassAdı>
- Tam nitelikli class adı "Sağlayıcı Namespace'si" olarak da bilinen bir üst düzey namespace'e sahip olmalı.
- Tam nitelikli class adının bir veya daha fazla namespace'i olabilir.
- Alt çizginin class adında herhangi bir bölümünü için özel bir anlamı yok
- Class adları büyük veya küçük harflerin herhangi bir kombinasyonundan oluşabilir.
PSR-0'da durum böyle iken:
vendor/
vendor_name/
package_name/
src/
Vendor_Name/
Package_Name/
ClassName.php # Vendor_Name\Package_Name\ClassName
tests/
Vendor_Name/
Package_Name/
ClassNameTest.php # Vendor_Name\Package_Name\ClassNameTest
PSR-4'de durum böyledir
vendor/
vendor_name/
package_name/
src/
ClassName.php # Vendor_Name\Package_Name\ClassName
tests/
ClassNameTest.php # Vendor_Name\Package_Name\ClassNameTest
Bu konuyu parça parça anlatmak istemediğimden tek yazı olarak paylaştım. Yazı biraz uzun olduğu için hatalar yada eksik bilgiler olabilir. Yorumlarınızla düzeltme yaparsanız sevinirim.
"Bu kod standartlarını ne yapıcam ben ya! ben böyle iyiyim" diyorsanız, siz bilirsiniz. Zaten kullanmak zorunda değilsiniz öyle bir durum olsa php kendini bir kalıba sokar, yazılıma php ile başlayan çoğu insanı bu işten soğuturdu. Niye kullancağını örnekle açıklayıp yazımı bitireyim.
Bu standartları uygularsan imajın iyi olacak, etrafındakileri de mutlu edeceksin. Kullanmazsan okul kıyafetlerinle sokak maçı yapıp ardından ekibini de kavgaya katıp dövüşüp duracaksın.
Kendinize iyi bakın. :)