This document is http://tnx.nl/php/ - If you replicate it, please do link. This page was written in 2003 (I think), is very out of date, and was never updated to reflect changes in PHP.
PHP is a nice tool for adding dynamic parts to a small website. It is popular because it integrates very well with the popular Apache webserver, but also because the basics of PHP are very easy to learn. But is it wise to build applications or large websites with PHP? Perhaps Perl is a better solution.
This document compares PHP to Perl, because its author is very familiar with these two languages. It would be nice if others could write comparisons to Ruby, Python, and other dynamic programming languages.
A follow-up document is available, at http://tnx.nl/php5.
To show this problem, here's a nice table of the functions that match a user
defined thing: (with something inconsistent like this, it's amazing to find
that the PHP documentation doesn't have such a table. Maybe
even PHP people will use this document, just to find out what
function to use :P)
replaces case gives s/m/x offset matches with insens number arrays matches flags (-1=end) ereg ereg no all no array no 0 ereg_replace ereg str no all no no no 0 eregi ereg yes all no array no 0 eregi_replace ereg str yes all no no no 0 mb_ereg ereg[1] no all no array no 0 mb_ereg_replace ereg[1] str/expr no all no no yes 0 mb_eregi ereg[1] yes all no array no 0 mb_eregi_replace ereg[1] str yes all no no no 0 preg_match preg[2] yes/no one no array yes 0 preg_match_all preg yes/no all no array yes 0 preg_replace preg str/expr yes/no n/all yes no yes 0 str_replace str str no all yes number no 0 str_ireplace str str yes all yes number no 0 strstr, strchr str/char no one no substr no 0 stristr str/char yes one no substr no 0 strrchr char no one no substr no -1 strpos str/char no one no index no n stripos str/char yes one no index no n strrpos char[3] no one no index no n strripos str yes one no index no -1 mb_strpos str[1] no one no index no n mb_strrpos str[1] yes one no index no -1
The problem exists for other function groups too, not just for matching.
(In Perl, all the functionality provided by the functions in this table is available through a simple set of 4 operators.)
[1] Handles multi-byte characters
[2] PCRE regex: so-called "Perl compatible" regular expressions.
[3] Also does strings in PHP 5
(This can be argued both ways. Some think it's good to have functions that combine functions, even if that means having dozens of extra names to remember)
In Perl, you use a double lc() (lowercase) or the /i flag where PHP usually provides a case insensitive variant. The case-insensitive versions have very inconsistent naming.
Perl: $foo cmp $bar lc $foo cmp lc $bar PHP: strcmp($foo, $bar) strcasecmp($foo, $bar) Perl: index($foo, $bar) index(lc $foo, lc $bar) PHP: strpos($foo, $bar) stripos($foo, $bar) Perl: $foo =~ s/foo/bar/ $foo =~ s/foo/bar/i PHP: $foo = str_replace('foo', 'bar', $foo) $foo = str_ireplace(...) PHP: $foo = ereg_replace('foo', 'bar' ,$foo) $foo = eregi_replace(...)
underscore no underscore: stream_get_line readline disk_free_space diskfreespace is_object isset mcal_day_of_week jddayofweek set_error_handler setlocale snmp_get_quick_print snmpget get_browser getallheaders base64_encode urlencode image_type_to_mime_type imagetypes msql_num_fields mysql_numfields php_uname phpversion strip_tags stripslashes bind_textdomain_codeset bindtextdomain cal_to_jd gregoriantojd str_rot13 strposPerl has no core function names with underscores in them.
Perl core functions are all "verb object" except the superseded dbm* functions. (Note that sys is a prefix, not an object. And that flock and lstat were named after the system calls. shm* and msg* are library calls)
ascii2ebcdic, bin2hex, deg2rad, ip2long, cal_to_jd (jdto*, *tojd), strtolower, strtotime,
Perl has lexical scope and dynamic scope. PHP doesn't have these.
For an explanation of why lexical scope is important, see Coping with Scoping.
PHP Perl Superglobal Yes Yes [1] Global Yes Yes Function local Yes Yes [2] Lexical (block local) No Yes Dynamic No Yes
[1] Perl has variables that are always in the main:: namespace. These are like
PHP's superglobals.
[2] Using a lexical variable in a sub routine's block, you get a function local
variable.
(Using the core binaries compiled with all possible extensions in the core distribution, using recent versions in November 2003.)
Number of PHP main functions: 3079 [1] Number of Perl main functions: 206 [2]
Median PHP function name length: 13 Mean PHP function name length: 13.67 Median Perl function name length: 6 Mean Perl function name length: 6.22
Note that Perl has short syntax equivalents for some functions:
readpipe('ls -l') ==> `ls -l` glob('*.txt') ==> <*.txt> readline($fh) ==> <$fh> quotemeta($foo) ==> "\Q$foo" lcfirst($foo) ==> "\l$foo" (lc is \L) ucfirst($foo) ==> "\u$foo" (uc is \U)
[1] Source: PHP Quick Reference
[2] Source: perldoc perlfunc
Why has PHP got 3079 functions while Perl does with only 206? In PHP, there are usually several functions that are very similar. In Perl, you have to know and remember less.
Another important factor is the use of modules, especially the DBI module which provides support for SQL databases, instead of bloating the core with lots of features that occupy memory but are rarely used.
(Modules that are more often not used than used don't count (This rules out PEAR for PHP and IO::File for Perl). Modules may be pulled in when the core provides no similar functionality. For simplicity, internal working is left out of this comparison.)
* Escaping: * PHP: (14) dbx_escape_string, escapeshellarg, escapeshellcmd, pg_escape_bytea, pg_escape_string, pg_unescape_bytea, addslashes, addcslashes, preg_quote, quotemeta, mysql_escape_string, mysql_real_escape_string, mysqli_real_escape_string, sqlite_escape_string * Perl: (2) [1] quotemeta, $dbh->quote * Sorting: * PHP: (16) sort, arsort, asort, krsort, ksort, natsort, natcasesort, rsort, usort, array_multisort, uasort, uksort, dbx_sort, imap_sort, ldap_sort, yaz_sort * Perl: (1) sort * Walking a list * PHP: (10) array_filter, preg_grep, array_search, array_unique, in_array, array_map, array_walk, array_count_values, array_change_key_case, array_sum * Perl: (2) map, grep * Splitting: * PHP: (8) split, explode, strtok, spliti, chunk_split, mb_split, preg_split, str_split * Perl: (1) split * Matching: * Strings: * PHP: (11) strstr, strchr, stristr, strpos, strrchr, stripos, mb_strpos, mb_strrpos, strrpos, strripos, substr * Perl: (3) index, rindex, substr * Regular expressions: * PHP: (6) ereg, eregi, mb_ereg, mb_eregi, preg_match, preg_match_all * Perl: (1) m// * Substituting a matched part: * PHP: (12) ereg_replace, eregi_replace, mb_ereg_replace, mb_eregi_replace, preg_replace, str_ireplace, str_replace, ltrim, rtrim, trim, nl2br * Perl: (1) s/// * Connecting to an SQL database: * PHP: (17) dbx_connect, fbsql_connect, ibase_connect, msql_connect, msql_pconnect, mssql_connect, mysql_connect, odbc_connect, pg_connect, pg_pconnect, sesam_connect, ifx_pconnect, ifx_connect, sqlite_open, sqlite_popen, mysqli_connect, mysqli_pconnect * Perl: (2) DBI->connect, DBI->connect_cached * Opening: * PHP: (5) dio_open, fopen, proc_open, popen, gzopen[2] * Perl: (2) open, sysopen * Reading/receiving: * PHP: (12) dio_read, fread, gzread[2], socket_read, socket_recv, socket_recvfrom, socket_recvmsg, readline, fgetc, fgets, stream_get_line, file * Perl: (5) read, readline, sysread, recv, getc * Printing/writing: * PHP: (14) print, echo, printf, fprintf, vprintf, dio_write, fwrite, fputs, gzwrite[2], socket_send, socket_sendmsg, socket_sendto, socket_write, socket_writev * Perl: (5) print, printf, syswrite, send, write * Closing: * PHP: (7) closelog, dio_close, fclose, gzclose[2], pclose, socket_close, proc_close * Perl: (1) close * Miscellaneous: * PHP: array_combine, array_fill, array_merge, list, range, count, create_function, strtr, pow, putenv, getenv, getmygid, getmypid, getmyuid * Perl: syntax or magic variables
[1] Because of system LIST syntax and DBI's placeholders, explicit escaping is
usually not even needed.
[2] Handled in Perl by a PerlIO layer
Slashdot, BBC creates 'Perl on Rails': I am going to create "PHP off the Rails" for developers of PHP websites. PHP developers will need no training, as most of them are off the rails already! -- Anne Thwacks
EFnet #php: 19:45 <+Dragnslcr> Comparing PHP to Perl is like comparing pears to newspapers
Perl Monks: PHP - it's "training wheels without the bike" -- Randal L. Schwartz
lesscode.org: PHP has a very low barrier to entry; consequently, a lot of eye-wateringly bad programmers are writing code in it; hence, a lot of code written in PHP is awful. This is arguably a good thing. -- Aristotle Pagaltzis
use Perl;: We all know that, due to the poor design of the language, security and PHP applications don't mix well, because PHP makes writing secure code difficult; apparently security doesn't mix well either with the mindset of the PHP core developers. -- Rafael Garcia-Suarez
Perl Buzz: Sure, PHP 6 may have a shorter release cycle than Perl 6 has, but at the end of it all, we'll have Perl 6, and you'll still have PHP. Just sayin'. -- Andy Lester
FOSDEM: :I chose PHP because I thought it would be a better fit for the community I was targeting, which tended to have a lot of non-programmers in it. -- Patrick Michaud