WordPress Web Sitesinde Teknik Kodlama Standartları

WordPress ekosistemi milyonlarca site, on binlerce eklenti ve tema barındırır. Bu ölçek; yalnızca fonksiyonel çözümler değil, okunabilirlik, güvenlik, performans, erişilebilirlik, test edilebilirlik ve geri uyumluluk gibi “mühendislik” ölçütleri gerektirir. “Çalışıyor” demek; sürdürülebilirlik ve ekipler arası devri garanti etmez. Teknik kodlama standartları, proje ömrü boyunca aynı kalite çizgisini koruyan bir “takım anlaşması”dır: WordPress Coding Standards (WPCS), güvenlik (nonce/izin/kaçış), veritabanı (hazırlanmış sorgular), REST & blok (Gutenberg) desenleri, varlık (asset) yükleme, i18n/l10n, tema hiyerarşisi, şablon ayrımı, hook/aksiyon isimlendirme, test/CI, “deprecation” politikası ve sürümleme.
1) Kod Standardı Kaynağı: WPCS + Proje Üstü Kurallar
WPCS (WordPress Coding Standards); PHP, JS, CSS, i18n ve güvenlik için kuralları PHPCS/Eslint stilinde sağlar.
-
PHPCS: Projede kökte
.phpcs.xml
—kural seti, özel istisnalar, minimum PHP/WordPress hedefi. -
Eslint/Stylelint: JS/TS ve CSS/SCSS için kurallar.
-
Proje üstü ekler: İsimlendirme (prefix/namespace), dizin yapısı, modülerlik, “deprecation” politikası, commit/PR kuralları.
Kural: Kod review, WPCS hatasız değilse onaylanmaz.
2) Dosya ve Dizin Yapısı: Anlaşılır Mimari
-
Eklenti:
my-plugin/
my-plugin.php // eklenti bootstrap
src/ // PHP kaynak
assets/ (js, css, images)
languages/ // .pot/.po/.mo
templates/ // tema üstünden override edilebilen parçalar (gerekliyse)
includes/ // küçük bağımlı parçalar (service, traits)
tests/ // PHPUnit/Playwright
-
Tema/Child:
functions.php
,template-parts/
,inc/
,assets/
,block-templates/
,block-patterns/
,theme.json
.
İlke: Tek sorumluluk—dosya ve sınıflar işlev açısından dar ve net.
3) İsimlendirme: Önek (prefix) ve Namespace Disiplini
-
Global fonksiyon/değişken: Çakışmayı önlemek için benzersiz önek:
acme_
. -
Sınıf/namespace: PHP 7+ projelerde
Acme\Plugin\...
tercihi. -
Hook adları:
acme/product/created
,acme/cache/purge
. -
Dosya adları: Küçük harf, tire:
class-order-repository.php
,product-controller.php
.
4) Kaçış–Doğrulama–Kullanıcı Yetkisi Üçlüsü (Escaping–Sanitization–Capability)
WordPress’te güvenlik, nonce + yetki + kaçış üçlüsüdür.
-
Giriş ($_POST/$_GET):
sanitize_text_field()
,absint()
,esc_url_raw()
,wp_kses()
. -
Çıkış:
esc_html()
,esc_attr()
,esc_url()
,wp_kses_post()
. -
Yetki:
current_user_can( 'manage_options' )
gibi capability kontrolleri. -
Nonce: Form/aksiyonlarda
wp_nonce_field()
vecheck_admin_referer()
.
Uygulamalı örnek:
if ( isset( $_POST[‘acme_save’] ) && check_admin_referer( ‘acme_settings_action’, ‘acme_nonce’ ) ) {
if ( ! current_user_can( ‘manage_options’ ) ) {
wp_die( esc_html__( ‘Yetkiniz yok.’, ‘acme’ ) );
}
$title = isset( $_POST[‘title’] ) ? sanitize_text_field( wp_unslash( $_POST[‘title’] ) ) : ”;
update_option( ‘acme_title’, $title );
}
5) Veritabanı Erişimi: $wpdb->prepare()
Zorunlu
-
Hazırlanmış ifadeler:
global $wpdb;
$sql = $wpdb->prepare(
“SELECT ID, post_title FROM {$wpdb->posts} WHERE post_type = %s AND post_status = %s LIMIT %d”,
‘product’,
‘publish’,
20
);
$rows = $wpdb->get_results( $sql );
-
Tablo adı:
$wpdb->prefix
kullanın; sabit yazmayın. -
Migration: Büyük şema değişikliklerinde kilit/minimum kesinti planı;
dbDelta()
yalnız küçük değişimler için.
6) Hooks (Action/Filter): Sözleşme, İsimlendirme ve Dokümantasyon
-
İsimlendirme:
acme/domain/action_name
. -
Parametre sırası: Filtrelerde en sonda
$value
döner; aksi takdirde zincir bozulur. -
Docblock: Hook ne yapar, parametre türleri, örnek kullanım.
-
Kırılganlık:
_doing_it_wrong()
ile yanlış kullanım uyarısı.
7) REST API Standartları: Yetki, Şema, Hata Sözleşmesi
-
Kayıt:
register_rest_route( 'acme/v1', '/product', [ ... ] )
. -
İzin:
permission_callback
şart; kullanıcı yetkisi/jwt/nonce stratejisi. -
Şema:
args
ile tip/doğrulama; dönen veri sabit sözleşme. -
Hata:
new WP_Error( 'acme_error', __( 'Açıklama', 'acme' ), [ 'status' => 400 ] )
.
8) Gutenberg/Blok Geliştirme: Script İzolasyonu ve Pattern’lar
-
register_block_type: PHP kaydı +
block.json
. -
Varlık izolasyonu:
wp_enqueue_script()
yalnızca blok kullanıldığı sayfada; global JS yüklemeyin. -
React/JSX: Eslint kuralları; DOM manipülasyonunda
@wordpress/data
/@wordpress/components
tercih. -
Pattern’lar: Tekrar eden tasarımlar için pattern kütüphanesi—editör üretkenliğini artırır.
9) Asset (JS/CSS) Yükleme: Koşullu ve Bağımlılık Bilinçli
-
Admin vs Front: Yönetici varlıklarını
admin_enqueue_scripts
, ön yüzüwp_enqueue_scripts
. -
Koşullu: Yalnız ilgili sayfada—ör. sadece ürün sayfasında galeri JS.
-
Bağımlılık:
wp_enqueue_script( 'acme', '...', [ 'wp-element', 'wp-components' ], '1.2.0', true );
-
Bütçeler: Mobil JS ≤ 150KB (gzip), CSS ≤ 100KB (gzip).
10) Uluslararasılaştırma (i18n) ve Yerelleştirme (l10n)
-
Text domain: Eklenti klasörü adı; tema domain’i
style.css
’te. -
Fonksiyonlar:
__()
,_e()
,_x()
,esc_html__()
,esc_attr__()
. -
Plurals:
_n()
ile çoğul. -
JSON çeviri: Blok betikleri için
wp_set_script_translations()
.
11) Tema Hiyerarşisi ve Şablon Ayrımı
-
Tema → Görünüm; Eklenti → İş mantığı.
-
Template parts:
get_template_part( 'template-parts/content', 'product' )
. -
Child theme: Override’lar child’da; vendor/çekirdek dosyaları asla modifiye etmeyin.
-
theme.json: Tipografi, renk, spacing, varyasyonlar.
12) Erişilebilirlik (A11y): Etiketler, Odak, Kontrast
-
Semantik: H1–H2 hiyerarşisi; landmark roller (
main
,nav
). -
Formlar:
label for
, hata iletileri;aria-live
. -
Klavye erişimi: Odak tuzağı yok; odak halkası gizlenmesin.
-
Medya:
alt
metin, video altyazı.
13) Performans Kalıpları: CWV (LCP/INP/CLS) İçin Kod Disiplini
-
LCP: Hero görsel
preload
+ uygun boyut; kritik CSS inline; fontpreload
+font-display
. -
INP: Uzun görevleri böl; gereksiz
addEventListener
ve 3P script azalt. -
CLS: Görsel/iframe oranı; dinamik içerik yüklenirken boşluk rezervasyonu.
-
RUM: Gerçek kullanıcı verisi olmadan Lighthouse tek başına yetmez.
14) Hata Kayıtları ve Gözlemlenebilirlik
-
WP_DEBUG_LOG: Üretimde kapalı; özel log kanalı.
-
JS hataları:
window.onerror
/unhandledrejection
yakalanıp raporlanır. -
Panolar: 5xx/JS error, P95 TTFB, LCP/INP/CLS, istek sayısı.
-
Korelasyon: Son dağıtım SHA’sı log’a yazılır.
15) Testler: Unit/Integration/E2E ve Fixture’lar
-
PHPUnit: Servis ve yardımcı fonksiyonlar.
-
Integration: WP yüküyle birlikte, DB’ye temas eden akışlar.
-
E2E (Playwright): Form gönderimi, login, ödeme, blok düzenleme.
-
Fixture: Sentetik, maskelenmiş veriler; PII yok.
16) CI/CD Kapıları: Kırmızıysa Yayın Yok
-
PHPCS (WPCS), Eslint, Stylelint zorunlu.
-
PHPStan/Psalm—statik analiz.
-
Lighthouse bütçeleri, görsel regresyon (Percy/Loki), a11y (Axe).
-
Composer audit ve bağımlılık taraması.
17) Geri Uyumluluk ve “Deprecation” Politikası
-
SemVer: Minor’de yeni özellik, major’da kırıcı değişim (mecbur kaldıysanız).
-
Deprecated uyarıları:
_deprecated_function()
/_deprecated_argument()
; sürüm ve alternatif. -
Adaptasyon süresi: Kaldırmadan önce en az 2 minor sürüm uyarı.
18) Kod Kokuları (Code Smells) ve Antipattern’lar
-
Global state: Rastgele
global
kullanımı. -
Çok amaçlı “util” sınıfları: SRP ihlali.
-
Kopyala–yapıştır: Hook içeriklerinde mükerrer kod.
-
Doğrudan SQL string birleştirme:
prepare()
olmadan asla.
19) Güvenlik Başlıkları ve 3P Kaynaklar
-
CSP: Inline yerine nonce/hash; 3P domain minimizasyonu.
-
SRI: CDN’den çekilen JS/CSS için bütünlük.
-
Referrer-Policy / Permissions-Policy / HSTS: Varsayılan güvenli politika.
20) Medya ve Yüklemeler: Sanitizasyon ve Boyut Politikası
-
MIME doğrulama:
wp_check_filetype()
. -
SVG: Yalnız sanitize eden kütüphane ile.
-
Boyut: Otomatik kırpma/optimizasyon; orijinal saklama politikası.
-
CDN:
srcset/sizes
veloading="lazy"
.
21) Tarih/Saat ve Zaman Dilimi
-
WP zaman fonksiyonları:
current_time( 'timestamp' )
,wp_date()
. -
UTC vs site TZ: UI’de site TZ; depoda UTC.
-
İnsan okunur:
human_time_diff()
.
22) Multisite ve Çok Dilli Uyum
-
Site-bağımlı seçenekler:
get_blog_option( $blog_id, '...' )
. -
Switching:
switch_to_blog()
/restore_current_blog()
. -
Hreflang/canonical: Tema/SEO katmanında otomatik üretim.
23) Kod İncelemesi (PR) Kontrol Listesi
-
WPCS ihlali var mı?
-
Nonce + capability + escaping üçlüsü tam mı?
-
$wpdb->prepare()
kullanılmış mı? -
Koşullu asset ve bütçe limitleri sağlanmış mı?
-
i18n doğru mu (text domain, _n, _x)?
-
A11y & SEO meta’ları bozuldu mu?
-
Testler/CI geçti mi?
-
Dokümantasyon ve changelog eklendi mi?
24) Örnek Modül: Yönetici Ayar Sayfası (Tam Akış)
Senaryo: Basit bir metin ayarı—güvenlik, i18n, WPCS uyumlu.
namespace Acme\Settings;
class AdminPage {
const OPTION_KEY = ‘acme_title’;
public function hooks() {
add_action( ‘admin_menu’, [ $this, ‘register_page’ ] );
add_action( ‘admin_init’, [ $this, ‘register_settings’ ] );
}
public function register_page() {
add_options_page(
esc_html__( ‘ACME Ayarları’, ‘acme’ ),
esc_html__( ‘ACME’, ‘acme’ ),
‘manage_options’,
‘acme-settings’,
[ $this, ‘render_page’ ]
);
}
public function register_settings() {
register_setting(
‘acme_group’,
self::OPTION_KEY,
[
‘type’ => ‘string’,
‘sanitize_callback’ => ‘sanitize_text_field’,
‘default’ => ”,
]
);
add_settings_section( ‘acme_main’, ”, ‘__return_false’, ‘acme-settings’ );
add_settings_field(
‘acme_title’,
esc_html__( ‘Başlık’, ‘acme’ ),
[ $this, ‘render_field’ ],
‘acme-settings’,
‘acme_main’
);
}
public function render_field() {
$value = get_option( self::OPTION_KEY, ” );
printf(
‘<input type=”text” name=”%1$s” value=”%2$s” class=”regular-text” />’,
esc_attr( self::OPTION_KEY ),
esc_attr( $value )
);
}
public function render_page() {
if ( ! current_user_can( ‘manage_options’ ) ) {
wp_die( esc_html__( ‘Yetkiniz yok.’, ‘acme’ ) );
}
?>
<div class=”wrap”>
<h1><?php echo esc_html__( ‘ACME Ayarları’, ‘acme’ ); ?></h1>
<form method=”post” action=”options.php”>
<?php
settings_fields( ‘acme_group’ );
do_settings_sections( ‘acme-settings’ );
submit_button();
?>
</form>
</div>
<?php
}
}
Neden iyi?
-
Capability kontrolü, i18n, kaçış/sanitize tam.
-
Ayarlar API ile güvenli depolama.
-
HTML çıktısında
esc_*
kullanımı.
25) Vaka A: “Küçük Bir Script” LCP’yi Nasıl Bozar?
Belirti: Blog yazılarında mobil LCP P95 +350ms.
Kök neden: Eklenti, tüm sayfalara global 300KB slider JS yüklüyor.
Çözüm: Koşullu enqueue (yalnız galeri sayfasında).
Sonuç: LCP P95 -320ms, INP iyileşmesi; WPCS + Lighthouse kapıları sayesinde regress engellendi.
26) Vaka B: SQL Enjeksiyonu Eşiğinden Dönüş
Belirti: Güvenlik tarayıcısı risk raporu.
Kök neden: $_GET['q']
doğrudan LIKE
içinde birleştirilmiş.
Çözüm: $wpdb->prepare()
+ joker karakter kaçışı; sonuçlar limitli/paginate.
Ders: “Çalışıyor” yetmez; hazırlanmış ifadeler standarttır.
27) 90 Günlük Uygulama Planı
-
Ay 1: WPCS/PHPCS, Eslint/Stylelint, PHPStan;
.phpcs.xml
ve Eslint konfigleri; dizin/isimlendirme kılavuzu; PR şablonu ve review checklist. -
Ay 2: REST/nonce/capability kalıpları;
$wpdb->prepare()
gözetimi; asset bütçeleri; a11y denetimleri; i18n şablonları (.pot
). -
Ay 3: CI/CD kapıları (Lighthouse+a11y+görsel regresyon); deprecation politikası; RUM panoları; eğitim (kod kokuları, güvenlik, CWV); iki örnek eklentide refaktör.
KPI: WPCS ihlalleri ↓, Lighthouse “performance” ve “best practices” ↑, P95 LCP/INP iyileşmesi, güvenlik taramasında kritik 0, PR başına düzeltme turu sayısı ↓.
Sonuç: Standartlar, “Yavaşlatan Bürokrasi” Değil; Hızlandıran Otomasyondur
WordPress’te teknik kodlama standartları; bireysel tercihi baskılayan bir kurallar bütünü değil, ekip hızını ve üretim kalitesini artıran otomasyon destekli bir uzlaşıdır. WPCS + güvenlik üçlüsü (nonce/yetki/kaçış) + $wpdb->prepare()
+ REST/blok sözleşmeleri + koşullu asset + i18n + a11y + test/CI + deprecation politikası; kodu yalnız bugün değil, gelecek sürümler için de sağlıklı kılar.
Öneri: Bugün .phpcs.xml
ve Eslint/Stylelint’i projeye ekleyin, PR checklist’inizi yazın ve asset bütçelerini belirleyin. Ardından REST/nonce/capability kalıplarını ve $wpdb->prepare()
denetimlerini standartlaştırın; CI kapılarıyla “kırmızıysa yayın yok” disiplinini kurun. Üç ay içinde kod tabanınızın okunabilir, güvenli, hızlı ve test edilebilir hale geldiğini; onarım maliyetlerinin ve regresyonların belirgin biçimde azaldığını göreceksiniz.