Language

Why PHP is bad and why it isn’t

Nowadays programmers consider PHP as a very bad programming language. One of the example is in this comic strip, saving the princess with programming language. But why is PHP considered bad and why does it is very popular out there?

The good

In general, PHP is a good language to start learning programming with.

It’s easy to setup and start

PHP is very easy to setup, especially for beginner. Just use XAMPP (for windows) and LAMP (for linux), and drop the code in htdocs and everything will go well. Just search in google for “hello world php xampp” or “hello world php lamp” and you’re good to go.

Furthermore it’s one of the easiest language to setup shared hosting, making it very easy to make your own website.

It’s very forgivable

PHP is dynamic typing, meaning you don’t need to specify whether an variable is string, int, specific class, etc. And it’s string concatenation is different with numeric additional, making it less ambiguous than javascript’s dynamic and don’t need type conversion. It’s very easy for beginner to start with.

And PHP variables works very well with HTML. Almost all native variables can be printed to screen by using echo, while array and object need special treatment.

Furthermore, using undefined variable only resulting in notice, and can be easily suppressed. But beware, both are considered “bad habit” in programming, so take it as learning features. There are also more exceptions that usually result in error in other language, that can easily suppressed in PHP.

It’s both procedural and OOP

PHP can serve procedural code, and OOP one. It’s very common to start learning programming with procedural, and learning OOP next, and it’s easier in same language.

Furthermore, PHP is a C-like syntax programming language, and there are many good languages in C-like syntax, like Java, C# and javascript. It’s C-like syntax is better than python (which is also a good starting language) “if” you aim to move later to those language.

Frameworks and tutorials are abundant

With many framework and tutorials out there, someone can search any problem or topics that they currently worked at, and finding many pages of google results. It’s very easy to find answers to PHP problems nowadays.

Furthermore, many PHP framework are using MVC (Model View Controller) pattern, which is one of the most common pattern in web programming. Learning them can help transition to other good languages using MVC pattern, such as Java MVC spring, C# Asp.Net MVC, NodeJs MVC frameworks and many more.

Furthermore nowadays PHP has composer, which is good to handle library as packages, which is almost all new languages use. And PHP has many CMS which make creating webpage like wordpress CMS easy.

The bad

So why is PHP considered bad? Well you need to at least good in programming to know it’s limitation and bad side.

It is not strong, static typed

PHP starts as dynamic, weakly typing language, helping to customize HTML pages ages ago. Up to this day, it still support dynamic typing, while supporting some type hinting at arguments and property level. While dynamic typing is good to start learning programming, it’s not good at complex business process.

However, being interpret language means the type hinting can only trigger when executed. So we won’t get any type error up until the portion of code is executed, as opposed to Java/C# where it can be caught compile time.

Moreover, PHP7, even after getting scalar type hinting for string and int, still not having generics for array. Without any means to type checking array, it’s harder to do type checking and enforce reliability, especially in business process (accounting).

It doesn’t have multithreading options by native

Without using additional components “PThreads”, PHP doesn’t have any options to emulate multithreading. It isn’t that PHP cannot do multithreading, however the problem lies in how “PThreads” works. It copy the current “process” state (loaded classes, etc) into another process and execute them concurrently.

In my experience with PThreads for PHP 5.6, (maybe I just lack configuration, correct me if so) PThreads use bigger memory than other programming languages, notably C#, Java and NodeJs. Moreover it’s harder to catch exception and to debug process spawned by threads.

So it doesn’t support multi-core process

In case of heavy background process or batch processing, most of the time multi-core support is a requirement.

It doesn’t have memory-persistence cache

PHP is run-and-forget scripting language, which load all it’s needed reference class on beginning of request (and during execution for lazy loading one), and to flush them later. The process takes time, and while PHP7 doing JIT to cache some of it’s code, it’s still not efficient because they need to be loaded for every request.

In contrast with PHP’s scripting, NodeJs and C# Asp.Net MVC (haven’t use java, but should be similar) run a server, and keeping the loaded classes (scripts) in memory, making them more efficient.

It’s dynamic typing takes too much memory

Looks like it’s mitigated in PHP 7, however in PHP 5.6 below, the dynamic variable in PHP takes too much memory. It’ll soon be a hassle when working with big variables, big file or many records of data.

And even if PHP7 is more efficient, it still can’t beat C/C++ level of memory usage per variable. And arguably, so do as in comparison with static typed language, such as Java and C# and the currently rising golang.

It’s data access doesn’t support multiple-result sets

Apply for MySql at least (looks like it supported in PostgreSQL). PHP cannot return multiple tables in one query. Let’s say that you have one procedure that returns 3 select queries, PHP MySql driver can only return one.

Many of it’s library support is configured at installation level

Some of the native library for PHP is configured during installation (gcc make and phpize). Some of the examples are zip (–enable-zip), thread safety (–enable-zts) for pthreads. It makes binding configuration to app repository level harder and reduce portability.

In conclusion

PHP is a good language to start programming with, easy to setup and have many libraries / framework / CMS. However in case of advanced use by expert programmers, PHP doesn’t really meet up the requirement.

Oh PHP empty…

Salah satu kelemahan terbesar PHP menurut saya adalah di null / value checking. Melihat bagaimana PHP adalah interpret language berarti validasi undefined value tidak dapat dilakukan di level compiler. Lalu bagaimana PHP adalah dynamic typing juga membuat null checking lebih sulit.

Null / Undefined

Ada 2 jenis variable kosong, yaitu null dan undefined. Variable null berarti variable tersebut pernah di-declare, dan di-initialize nilainya sebagai NULL. Undefined variable, adalah variable yang tidak pernah di-declare atau sudah di-declare namun tidak pernah di-initialize. Contoh:

$null = NULL; //null variable
$null2; //masih undefined
$null = $null + 1; //nilai $null jadi 1
$null = NULL;
echo $null["key"] === NULL ? "true" : "false"; //hasilnya true
$undefined = $undefined + 1; //error undefined variable

Lucunya di PHP, NULL dianggap sebagai sebuah value. Hal ini membuat operasi matematik / string yang berinteraksi dengan NULL tidak error, seperti contoh penambahan di atas. Untuk operasi matematik, NULL dianggap 0 dan untuk operasi string maka null dianggap string kosong. Bahkan untuk array, NULL hanya akan menghasilkan nilai NULL lagi dan tidak error.

empty / isset

Tadi kita sudah melihat bagaimana null dianggap sebagai value. Tetapi tidak pada pengecekan empty / isset. Anehnya lagi, kedua operasi tersebut tidak 100% berlainan dengan arti kata !empty == isset. Anggap kita menggunakan satu set variable sebagai berikut untuk mengecek validasi empty / isset:

$one = 1;
$two = 0;
$three = "";
$four = " ";
$five = "0";
$six = "false";
$seven = false;
$eight = [];
$null = NULL;
$null2;

Snippet untuk mengecek empty

echo 'empty($one) ';
echo empty($one) === true ? "true" : "false";
echo "\n";
echo 'empty($two) ';
echo empty($two) === true ? "true" : "false";
echo "\n";
echo 'empty($three) ';
echo empty($three) === true ? "true" : "false";
echo "\n";
echo 'empty($four) ';
echo empty($four) === true ? "true" : "false";
echo "\n";
echo 'empty($five) ';
echo empty($five) === true ? "true" : "false";
echo "\n";
echo 'empty($six) ';
echo empty($six) === true ? "true" : "false";
echo "\n";
echo 'empty($seven) ';
echo empty($seven) === true ? "true" : "false";
echo "\n";
echo 'empty($eight) ';
echo empty($eight) === true ? "true" : "false";
echo "\n";
echo 'empty($null) ';
echo empty($null) === true ? "true" : "false";
echo "\n";
echo 'empty($null2) ';
echo empty($null2) === true ? "true" : "false";
echo "\n";
echo 'empty($undefined) ';
echo empty($undefined) === true ? "true" : "false";
echo "\n";

Snippet untuk mengecek isset

echo 'isset($one) ';
echo isset($one) === true ? "true" : "false";
echo "\n";
echo 'isset($two) ';
echo isset($two) === true ? "true" : "false";
echo "\n";
echo 'isset($three) ';
echo isset($three) === true ? "true" : "false";
echo "\n";
echo 'isset($four) ';
echo isset($four) === true ? "true" : "false";
echo "\n";
echo 'isset($five) ';
echo isset($five) === true ? "true" : "false";
echo "\n";
echo 'isset($six) ';
echo isset($six) === true ? "true" : "false";
echo "\n";
echo 'isset($seven) ';
echo isset($seven) === true ? "true" : "false";
echo "\n";
echo 'isset($eight) ';
echo isset($eight) === true ? "true" : "false";
echo "\n";
echo 'isset($null) ';
echo isset($null) === true ? "true" : "false";
echo "\n";
echo 'isset($null2) ';
echo isset($null2) === true ? "true" : "false";
echo "\n";
echo 'isset($undefined) ';
echo isset($undefined) === true ? "true" : "false";
echo "\n";

Hasilnya

empty($one) false
empty($two) true
empty($three) true
empty($four) false
empty($five) true
empty($six) false
empty($seven) true
empty($eight) true
empty($null) true
empty($null2) true
empty($undefined) true

isset($one) true
isset($two) true
isset($three) true
isset($four) true
isset($five) true
isset($six) true
isset($seven) true
isset($eight) true
isset($null) false
isset($null2) false
isset($undefined) false

Untuk isset logikanya cukup mudah, semua variable yang sudah di set dengan nilai apapun terkecuali NULL menghasilkan true. Untuk empty cukup beragam, sebuah variable dianggap empty bila bernilai string kosong($three), string 0 ($five), boolean false ($seven), int 0 ($two) dan array kosong ($eight).

Encapsulate in function

Khusus untuk validasi undefined, saya belum menemukan cara lain kecuali dengan empty atau isset. Contoh dalam snippet kode berikut:

function isNullOrEmpty($str){
	return !(isset($str) && $str != '');
}
echo 'isNullOrEmpty($six) ';
echo isNullOrEmpty($six) ? "true" : "false";
echo "\n";
echo 'isNullOrEmpty($null) ';
echo isNullOrEmpty($null) ? "true" : "false";
echo "\n";
echo 'isNullOrEmpty($undefined) ';
echo isNullOrEmpty($undefined) ? "true" : "false";
echo "\n";

Hanya kode yang menggunakan variable $undefined saja yang menghasilkan PHP notice / error, lainnya tidak. Hal ini berarti kita tidak dapat meng-encapsulate function empty ke beberapa function validasi lain, seperti stringIsNullOrEmpty dan stringIsNullOrWhitespace.

Kesimpulan dan saran

Variable null dan undefined di-handle berbeda oleh PHP. Function empty dan isset juga menghasilkan validasi yang berbeda. Khusus untuk validasi variable undefined, saya belum menemukan function selain empty dan isset yang dapat meng-handle nya.

Sebagai programmer yang sudah lama menggunakan static type dan compiled language (C#), saya sudah terbiasa untuk melakukan variable declaration sehingga kemungkinan terjadinya undefined variable lebih kecil. Cukup baik untuk terbiasa melakukan variable declaration di awal function terlebih dulu untuk meminimalisir validasi empty / isset.

Pergunakan isset bila ingin me-validasi false dan empty value. Pergunakan empty bila sudah tahu kriteria-kriteria validasi yang dilakukan empty.