Static Analysis Tools untuk PHP: Phan, PHPStan dan Psalm

3 min read

Disclaimer
Saya bekerja di AWS, semua opini adalah dari saya pribadi. (I work for AWS, my opinions are my own.)
3 PHP Static Analysis Tools: Phan, PHPStan, Psalm
Background image Photo by Shahadat Rahman on Unsplash

TeknoCerdas.com – Salam cerdas untuk kita semua. PHP adalah bahasa pemograman yang dijalankan menggunakan PHP interpreter. Artinya source code PHP tidak perlu di-compile terlebih dulu untuk dijalankan. Ini sangat menguntungkan untuk pengembangan karena tanpa proses compile maka proses pengembangan lebih cepat. Namun kerugiannya adalah error tidak terlihat dan kemungkinan akan terjadi saat runtime. Tulisan ini akan membahas 3 static analysis tools untuk PHP yaitu:

Pada bahasa pemrograman yang bertipe static typing, dimana variabel atau suatu fungsi harus dideklarasikan tipenya. Untuk itu souce code dari program tersebut harus diubah terlebih dahulu ke bahasa mesin atau managed code sebelum dijalankan. Proses ini dilakukan oleh sebuah tools yang dinamakan compiler. Bahasa seperti C, Rust, Golang, Java, dan C# adalah static typed sehingga perlu di-compile terlebih dahulu sebelum dijalankan.

Baca Juga
Menjalankan PHP pada .NET Core

Sehingga sebelum program dijalankan compiler akan melakukan pengecekan tipe data dari variabel atau fungsi apakah sesuai dengan yang dideklarasikan. Sehingga sebelum program berjalan error sudah dapat diketahui.

Berbeda dengan bahasa pemrograman yang dynamic typing seperti PHP, Javascript atau Ruby, dimana variabel atau fungsi tidak perlu didefinisikan tipenya. Source code tidak perlu di-compile terlebih dahulu akan tetapi langsung dijalankan oleh sebuah interpreter. Karena tidak ada proses pengecekan tipe data maka kemungkinan runtime error lebih besar daripada static typing.

Baik dynamic typing atau static typing memiliki kelebihan dan kekurangan tergantung bagaimana digunakan. Namun yang jelas, runtime error pada production adalah hal buruk dan sebisa mungkin dihindari.

Dengan menggunakan static analysis tools pada PHP maka kelebihan yang dimiliki static typing dapat digunakan yaitu mengenali runtime error bahkan sebelum program dijalankan. Untuk program berskala besar dan dengan jumlah anggota tim yang banyak static analysis tools akan sangat membantu.

Contoh file example1.php dengan kode tanpa static typing yang biasanya pengembang PHP lakukan.

$login = false;

if ($login) {
    $msg = "Hello World";
}

echo $msg;

Kode diatas secara syntax tidak error namun ketika dijalankan akan menghasilkan runtime error karena variabel $msg tidak dikenali. Hal ini bisa ditangkap dengan static analyzer tools.

Contoh lain yaitu example2.php tentang kesalahan tipe data yang digunakan.

/**
 * @param $args array
 * @return int
 */
function testArray($args) {
    return $args[0];
}

$numbers = [1, "two", 3];
echo testArray($numbers);

Kode diatas sebelum dijalankan akan error karena static analyzer mendeteksi bahwa parameter dari fungsi testArray yang dikirimkan adalah array of mixed (int dan string) bukan yang diharapkan yaitu array of integer.

Phan

Phan adalah static analyzer tools yang ditulis dengan PHP. Phan memerlukan C extension php-ast untuk berjalan. Karena menggunakan C extension maka harus ada proses compile lewat PECL atau metode lain sebelum dapat menggunakan Phan. Hal itu bisa dihindari jika anda menggunakan Docker image.

Dengan Phan pengembang dapat menemukan berbagai error sebelum program dijalankan.

Cara instalasi Phan lewat Composer.

$ composer require --dev phan/phan

Kemudian Phan memerlukan sebuah konfigurasi file dimana konfigurasi ini menentukan seberapa detil tingkat pengecekan yang akan dilakukan. Konfigurasi file ini diletakkan di .phan/config.php. File ini dapat dibuat sendiri atau melalui perintah phan --init --init-level=X.

Berikut adalah hasil analisa dari Phan dari dua file example1.php dan example2.php.

$ ./vendor/bin/phan
Parsing files...
░░                                                     2 / 2 (100%) 9MB
Analyzing classes...
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 12MB
Analyzing functions...
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 12MB
Analyzing files...
░░                                                     2 / 2 (100%) 30MB

src/example1.php:5 PhanImpossibleConditionInGlobalScope Impossible attempt to cast $login of type false to truthy in the global scope (may be a false positive)
src/example1.php:9 PhanPossiblyUndeclaredGlobalVariable Global variable $msg is possibly undeclared
src/example2.php:12 PhanTypeMismatchArgument Argument 1 ($args) is $numbers of type array{0:1,1:'two',2:3} but \testArray() takes int[] defined at src/example2.php:7

Phan menangkap 3 kesalahan pada file example1 baris 5 dan baris 9. Pada file example2 ada pada baris 12.

PHPStan

PHPStan adalah static analyzer tools yang ditulis dengan PHP. PHPStan tidak menggunakan C extension untuk parser namun menggunakan parser PHP murni yaitu nikic/PHP-Parser. PHPStan juga dapat mengenali berbagai type error yang dapat ditemukan seperti bahasa yang menggunakan static typing.

Untuk melakukan instalasi PHPStan dapat menggunakan Composer.

$ composer require --dev phpstan/phpstan

PHPStan tidak memerlukan konfigurasi file untuk dijalankan. Setelah PHPStan terinstal misal dengan Composer maka sudah langsung dapat dijalanakan untuk menganalisa source code.

Berikut adalah hasil analisa dari PHPStan dari dua file example1.php dan example2.php.

$ ./vendor/bin/phpstan analyse --level 8 src/
2/2 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ -------------------------------------
  Line   example1.php
 ------ -------------------------------------
  5      If condition is always false.
  9      Variable $msg might not be defined.
 ------ -------------------------------------

 ------ --------------------------------------------------------------------------------------------
  Line   example2.php
 ------ --------------------------------------------------------------------------------------------
  12     Parameter #1 $args of function testArray expects array, array given.
 ------ --------------------------------------------------------------------------------------------


 [ERROR] Found 3 errors

Sama dengan Phan, PHPStan juga menangkap 3 kesalahan pada file example1 baris 5 dan baris 9. Pada file example2 ada pada baris 12.

Baca Juga
Composer 2.0 Telah Dirilis – Seberapa Cepat?

Psalm

Psalm adalah static analysis tools yang ditulis dengan PHP. Psalm dikembangkan oleh salah satu perusahaan layanan video terbesar yaitu Vimeo. Sama dengan PHPStan, Psalm menggunkan PHP parser murni dari nikic/PHP-Parser. Psalm dapat melakukan berbagai pengecekan static error atau pun kemungkinan logic error.

Cara melakukan instalasi Psalm dapat dilakukan dengan Composeer.

$ composer require --dev vimeo/psalm

Psalm memerlukan sebuah file konfigurasi dalam bentuk XML file. File tersebut dapat dibuat secara otomatis dengan menggunakan perintah psalm --init. Mirip dengan Phan karena Psalm terinspirasi dari project tersebut.

Berikut adalah hasil analisa dari Psalm dari dua file example1.php dan example2.php.

Scanning files...
Analyzing files...

EE

ERROR: TypeDoesNotContainType - src/example1.php:5:5 - if (false) is impossible (see https://psalm.dev/056)
if ($login) {


ERROR: PossiblyUndefinedGlobalVariable - src/example1.php:9:6 - Possibly undefined global variable $msg, first seen on line 6 (see https://psalm.dev/126)
echo $msg;


ERROR: MixedArgument - src/example1.php:9:6 - Argument 1 of echo cannot be mixed, expecting string (see https://psalm.dev/030)
echo $msg;


ERROR: InvalidScalarArgument - src/example2.php:12:16 - Argument 1 of testArray expects array, array{int(1), string(two), int(3)} provided (see https://psalm.dev/012)
echo testArray($numbers);


------------------------------
4 errors found
------------------------------

Checks took 0.34 seconds and used 38.360MB of memory
Psalm was able to infer types for 87.5000% of the codebase

Berbeda dengan Phan dan PHPStan, Psalm mengeluarkan 4 error. Dimana error tamabahan yang spesifik pada Psalm adalah error tentang perintah echo $msg. Psalm mengindikasikan nilai dari $msg bukan string jadi harusnya diubah terlebih dahulu.

Kesimpulan

Dengan menggunakan static analysis tools maka error yang biasanya muncul saat runtime dapat dihindari. Baik itu berupa type error atau berupa logic error.

Jika mengembangkan aplikasi berskala besar dengan jumlah anggota tim yang banyak maka menambahkan static analysis tools pada proses CI/CD akan memastikan kualitas kode lebih baik.