PSR-1 dan PSR-12 adalah dua dokumen yang paling sering dimaksud orang ketika menyebut “coding standard PHP”. PSR-1 mendefinisikan aturan dasar yang harus dipatuhi agar kode dapat dibaca lintas tim: tag pembuka, penamaan class, method, dan konstanta. PSR-12 memperluas PSR-1 menjadi panduan gaya lengkap — indentasi, panjang baris, posisi kurung kurawal, hingga penempatan declare(strict_types=1). Pada chapter ini kita bedah aturan-aturan kuncinya dengan pasangan contoh sesuai dan tidak sesuai, lengkap dengan sejarah singkat mengapa PSR-12 menggantikan PSR-2.

Aturan Dasar PSR-1 #

PSR-1 memakai bahasa normatif standar RFC: MUST (harus) berarti kewajiban mutlak, SHOULD (sebaiknya) berarti rekomendasi kuat yang boleh menyimpul dengan alasan. Lima aturan dasarnya ringkas namun berdampak besar:

Aturan PSR-1Ketentuan
Tag pembukaBerkas PHP HARUS memakai <?php atau <?=
Simbol vs efek sampingBerkas SEBAIKNYA hanya mendeklarasikan symbol (class, function, konstanta) ATAU hanya menjalankan logika dengan efek samping — tidak keduanya
Nama classPascalCase (StudlyCaps): InvoiceGenerator
Konstanta classHuruf kapital semua dengan underscore: MAX_ITEM
Nama methodcamelCase: generateInvoice()

Aturan “simbol vs efek samping” sering dilewatkan padahal penting. Berkas yang mendeklarasikan class sebaiknya tidak sekaligus menjalankan echo, query database, atau menulis berkas di level atas. Pencampuran seperti itu membuat efek muncul hanya karena berkas di-include — misalnya oleh autoloader — dan memicu perilaku tak terduga yang sulit dilacak. Deklarasikan symbol di satu berkas; tarik logika bermuatan efek ke skrip masuk (entry point) terpisah.

Contoh Tidak Sesuai dan Sesuai PSR-1 #

Cara tercepat menanamkan aturan adalah membandingkan dua wujud kode. Blok berikut melanggar tiga aturan PSR-1 sekaligus tetapi tetap berjalan tanpa error — PHP tidak memaksa gaya, kesepakatanlah yang dilanggar:

php
<?php

class invoice_generator
{
    const max_item = 10;

    public function Generate_Invoice($items)
    {
        // isi method
    }
}

Tiga pelanggarannya: nama class invoice_generator memakai snake_case alih-alih PascalCase, konstanta max_item tidak ditulis kapital dengan underscore, dan method Generate_Invoice memakai gaya campuran alih-alih camelCase. Versi yang patuh terlihat seperti ini:

php
<?php

declare(strict_types=1);

class InvoiceGenerator
{
    public const MAX_ITEM = 10;

    final public function generateInvoice(array $items): string
    {
        $jumlahItem = count($items);

        return "Invoice berisi {$jumlahItem} item";
    }
}

$generator = new InvoiceGenerator();
echo $generator->generateInvoice(['Kopi', 'Teh', 'Gula']) . "\n";
echo 'Batas maksimal: ' . InvoiceGenerator::MAX_ITEM . "\n";

Output yang Dihasilkan:

text
Invoice berisi 3 item
Batas maksimal: 10

Mari kita bedah titik-titik kepatuhannya:

  1. Baris 3: declare(strict_types=1); berdiri sebagai statement pertama berkas — syarat penempatan dari PSR-12 yang akan kita bahas sebentar lagi.
  2. Baris 5: nama class InvoiceGenerator mengikuti PascalCase sesuai PSR-1.
  3. Baris 7: konstanta MAX_ITEM kapital semua dengan underscore, dan diberi visibility public sebagaimana diwajibkan PSR-12.
  4. Baris 9: method generateInvoice() camelCase; kata kunci final berada sebelum visibility public, bukan sesudahnya.
  5. Baris 11: variabel lokal $jumlahItem camelCase dan mengungkap isi tanpa perlu komentar.

PSR-12 sebagai Penerus PSR-2 #

Sejarahnya, gaya lengkap dulunya diatur PSR-2 yang diterima pada 2012. Seiring PHP menambahkan traits, sintaks pendek, dan fitur baru lainnya, PSR-2 kehilangan banyak kasus yang belum diaturnya, sehingga berstatus deprecated dan digantikan PSR-12 pada 2019 — dokumen yang memperluas PSR-1, bukan menggantikannya. PSR-12 juga ditulis agar dapat ditegakkan oleh alat seperti PHP_CodeSniffer dan PHP CS Fixer. Aturan-aturan kuncinya:

Aturan PSR-12Ketentuan
IndentasiEmpat spasi, bukan tab
Panjang barisTidak ada hard limit; soft limit 120 karakter; disarankan tidak melebihi 80
Satu class per berkasKonsekuensi praktis PSR-4: nama class = nama berkas
declare(strict_types=1)Jika dipakai, HARUS menjadi statement pertama berkas
Posisi final/abstractSebelum visibility: final public function
Posisi staticSetelah visibility: public static function
Kata kunciHuruf kecil semua: true, false, null
VisibilityWAJIB dideklarasikan pada semua property dan konstanta
Kurung kurawalClass: buka di baris baru; struktur kontrol: buka di akhir baris yang sama
Prefix _Tidak boleh dipakai untuk menandai method private/protected

Sebagian besar aturan di atas berbunyi sepele, dan justru itu intinya: karena semuanya mekanis, formatter dapat memperbaikinya sekali jalan. Yang tidak bisa diserahkan ke mesin adalah kebiasaan menulis dalam pola yang benar sejak awal.

Gaya Struktur Kontrol dan Penempatan strict_types #

Struktur kontrol adalah bagian yang paling sering ditulis, jadi gayanya paling terasa. Pola PSR-12: satu spasi setelah keyword, kurung buka di akhir baris yang sama, } elseif (...) { menyatu dalam satu baris:

php
<?php

declare(strict_types=1);

$poin = 87;

if ($poin >= 85) {
    $predikat = 'A';
} elseif ($poin >= 75) {
    $predikat = 'B';
} else {
    $predikat = 'C';
}

echo "Predikat: {$predikat}\n";

Output yang Dihasilkan:

text
Predikat: A

Pada blok tersebut, setiap cabang if/elseif/else membuka kurung kurawal di akhir baris kondisinya dan menutupnya pada baris tersendiri, sementara isi cabang terindentasi empat spasi. Kontras dengan class pada contoh sebelumnya yang kurung bukanya berada di baris baru setelah nama class — perbedaan yang disengaja oleh standar.

Sekarang penempatan declare(strict_types=1). Blok berikut sengaja menunjukkan penempatan yang salah — declare diletakkan setelah deklarasi namespace:

php
<?php

namespace App;

declare(strict_types=1);

Jika Anda menjalankan berkas tersebut, PHP menghentikan eksekusi dengan pesan Fatal error: strict_types declaration must be the very first statement in the script di baris declare. Pesan ini adalah compile error — skrip tidak berjalan sama sekali, sebelum baris mana pun tereksekusi.

Ringkasan #

PSR-1 menjaga fondasi — tag pembuka, pemisahan deklarasi dari efek samping, dan penamaan class, konstanta, serta method. PSR-12 melengkapi dengan aturan gaya menyeluruh: indentasi empat spasi, soft limit 120 karakter, posisi kurung kurawal, urutan final sebelum visibility, hingga posisi declare(strict_types=1) sebagai statement pertama. Aturan yang mekanis sebaiknya diserahkan ke formatter agar energi tim habis untuk logika. Setelah bentuk kode terjaga, pertanyaan berikutnya adalah di mana berkas class seharusnya berada — jawabannya adalah standar PSR-4 pada chapter berikutnya.

Referensi #