• user warning: Unknown column 'u.signature_format' in 'field list' query: SELECT c.cid as cid,, c.nid, c.subject, c.comment, c.format, c.timestamp,, c.mail, c.homepage, u.uid, AS registered_name, u.signature, u.signature_format, u.picture,, c.thread, c.status FROM comments c INNER JOIN users u ON c.uid = u.uid WHERE c.nid = 19383 AND c.status = 0 ORDER BY c.cid LIMIT 0, 50 in /var/www/ on line 991.
  • warning: file_get_contents( [function.file-get-contents]: failed to open stream: HTTP request failed! in /var/www/ : eval()'d code on line 4.

PHP: It can do it!

by Thibaud Arguillère

Over several posts, I am spending some time on major new features of 4D v12 (released last June). Today, I’ll focus on a new major major-new-feature: The PHP Execute command, which allows the execution of PHP code.


Well, having written “PHP Execute allows the execution of PHP code,” I realize that the name clearly stands for the function. 4D should give enigmatic names to the commands, so I can avoid stating the obvious. For example, “The Execute a script of the kind Hyper Text Preprocessor allows executing PHP code”. Now, we feel like we’re really learning something.


Before 4D v12, it was possible to execute PHP code since 2004 (and the 4D version of the same year) via a call to LAUNCH EXTERNAL PROCESS (short name: “LEP”). But the comparison stops there because PHP Execute is so much powerful. Here are 10 reasons to prove this statement (In blue, the good things. In red, the less-good things):



PHP Execute



Need to install PHP




Can run a .php script




Interpreter re-launched for each call




Can execute a function inside a script




Can pass parameters to the function




Can receive results




Can execute a native PHP function (no need for a .php file)




Can send environment variables to the PHP interpreter




Is much more powerful than LEP




Is a major new feature of 4D v12




(1) Depending on the required version, yes, under Mac OS
(2) Unless PHP is installed
(3) Or difficult. Exchange BLOBs, extract info, etc.
(4) But not that easily. That’s why it’s red.
(5) Eventually, using


It rocks!

And the winner is… PHP Execute, with all the blue points! Okay. You may have noticed that some points have clearly been exaggerated, and others are there only to paint more blue in the appropriate column. The second and fifth points, for example, make sense only if the previous point is valid. That said, the fact is that PHP Execute rocks!

  • Interpreter compiled in FastCGI mode (more on this later) provided => no need to install PHP.
  • No need for the Web server to be running. I’m adding this important detail because most often, PHP is conceptually mixed with “the Web”. This is not the case here: The command works perfectly when 4D Web server is not started. And of course, it also works the same way if the server is running.
  • You can call a function inside a .php script, pass parameters to it, and receive a result. This really, really rocks! To my knowledge, no other tool in the whole universe provides such an easy way to use PHP: One executes full scripts, and then extracts the result sent in stdout.

    In fact, it is not exactly “To my knowledge”. It is more to the knowledge of my colleague Alexandre, who knows all about PHP and worked to develop the feature.
  • Customization: Preferences and calls to SET DATABASE PARAMETER/PHP SET OPTION let the 4D developer change the behavior at runtime.


The PHP world is colossal, possibilities are infinite. Prior to 4D v12, when I need a feature that…


  • Either just did not exist in 4D
  • or would have required a lot of development time (lot sof code, methods, even some hacks)


…I looked for a plug-in that could do it.


Whereas now, before looking for a plug-in, I will look on the PHP side. It is very likely that I will find some PHP code, modules, or examples that fit my needs. For example:

  • Your customer needs to communicate with LDAP? PHP can do it! See the “LDAP and v12” US TechNote, and the PHP LDAP module documentation.
  • You need to zip a file or check the content of a zip archive? PHP can do it!
  • You want to get a hash? Use SSL with SMTP? Handle images on disk? Create incredible charts? Encrypt credit card data? Generate PDFs? PHP can do it!


If you don’t know PHP, you still can use it. Get the code (text files, .php extension), put it in the right place (I use a “php” folder inside the “resources” folder) and that’s all. You just need to call the script you need, and/or the function inside the script.


Well, in fact, you’ll sometimes need to look inside the code. Eventually, you’ll want to write the killer function you need. But the vast quantity of code and examples available on the internet are, most of the time, ok. Back to the “Need to zip a file” example I gave above. When you look at the zip documentation, you can’t miss the “Examples” chapter. The first example explains how to create a new archive and to add elements to it. We quickly can see what looks important for our own use: Here, four routines look very interesting:

PHP example

Using this example (copy-paste), I wrote this script (quick, fast, no error checking, etc.):


function DoZipFile($fileToZipPath, $archivePath)
     $zip = new ZipArchive();

     if ($zip->open($archivePath, ZIPARCHIVE::CREATE))

I save the file as “Zip_Tools.php” (plural form: I’m going to add routines to if, for sure) and put it in {MyDB}/Resources/php.


Zipping a file from 4D is now that easy:


// Quick test, hard-coded names
$scriptPath:=Get 4D folder(Current Resources folder)+"php"+Folder separator+"Zip_Tools.php"
$filePath:=Convert path system to POSIX(System folder(Desktop)+"TheTestFileToZip.txt")
$ok:=PHP Execute($scriptPath;"DoZipFile";*;$filePath;$zipPath)

Please note the use of the Folder separator constant and of Convert path system to POSIX. Cool, hmm?


I owe my readers The Truth: The original code (from the example) that was copy/pasted did not work at all on the first try because I removed or moved too many square brackets and parentheses. Thanks to PHP GET FULL RESPONSE, I was able to find my errors.


Last word of advice: Don’t forget to create the file to zip on your desktop, if you know what I mean. (Yes, it was the last error of the test.)

“Flash Your Charts with PHP”

Let’s move on to a more sophisticated example. At 4D Summit 2009, the “Flash Your Charts With PHP” session was totally amazing. By mixing PHP code and a Web area, here is an example of the kind of things you can do:


The demo application can be downloaded here.


Tip : A bug in 4D v12.0 makes PHP Execute fail to run if 4D is installed in “Program Files” and you are not the administrator of the machine. This is fixed for 12.1 (and in 12.0HF1 if you are a Partner and have access to the Hot Fixes). As a workaround, you must “Run as administrator.” More details here:


The PHP interpreter provided with 4D is compiled using the “FastCGI mode.” This is what allows us to be much, much faster than LEP (though speed is not the one and only advantage of FastCGI). Indeed, in FastCGI mode, the PHP interpreter is loaded in memory only once, upon first execution. The time saved for subsequent executions is huge, because loading a program in memory is a long task. Let’s use an example of calculating the md5 hash of a text. Here is the LEP code:

1) The PHP Script:

echo md5('Hello') ;


2) The 4D code

LAUNCH EXTERNAL PROCESS("php -f /Users/thibaud/Desktop/EchoMD5.php";$in;$out;$err)

Note as a tip/trick: You can get the same result without a .php file (point #7 of the comparison array):

LAUNCH EXTERNAL PROCESS("php -r ‘$foo = md5(\"Hello\");var_dump($foo);";$in;$out;$err)
// The result of var_dump is <string(32) "The md5"
// => we must remove the beginning, string(32) + pace + quotes


And now, the 4D v12 development style code:

$ok:=PHP Execute("";"md5";$result;"Hello")

See how easy, efficient and elegant it is? Isn’t it nicer to just write "md5" than $result than the ugly
"php -f /Users/thibaud/Desktop/EchoMD5.php"?

If I run this test 100 times, the results are crystal clear on my Mac: It takes 10 seconds for LEP to run the 100 iterations while PHP Execute does the same in 500ms. And if I re-launch the test, then PHP Execute takes only 100ms – one hundred times faster! This is because at first call, 4D launches the interpreter. This takes time, as explained previously so I’m not going to repeat that it’s because of the initializations, loading libraries and system resources, etc. Oh, it sounds like if I repeated it after all. Too bad. Let’s move on. Only the first call has this overhead. Subsequent calls will have a PHP/FastCGI ready to go.


On the other hand, each call to LEP loads the shell (we are under Mac OS) which initializes itself. The shell then loads the PHP executable, which initializes itself. Then the script is executed, PHP is unloaded, the shell is unloaded. And – would you look at that – all this is done again at next call.


The same test launched on Windows shows that PHP Excecute is “only” 20 times faster than LEP. This is because Windows does not have a Shell – in the UNIX sense – to initialize, and also because loading libraries and system resources are well optimized. But at 20 times faster, it’s still a killer.


The End of Plug-ins?

Given the facts that the PHP world is so rich, and how easy it is to find code, examples, and modules on the internet (most of the time free and reusable, but you should always check the licensing scheme, of course), we can figure that the needsfor plug-ins will decrease. Especially since reading PHP code when you don’t know PHP is easier than reading C++ code when you don’t know C++.


The subtitle about “The End Of Plug-ins” is provocative on purpose. Plug-ins used for interface (4D Write, Canvas, ALP, hmCal, …) cannot be replaced by PHP (Well, I’ve never tried to at least), but furthermore, PHP is an interpreted scripting language. If speed is critical, use a plug-in. Or 4D compiled code. Back to the previous example, the same 100 iterations takes only 2ms for a plug-in. (Here is the MD5 Plug-in by Pluggers Software, free!) It takes only 12ms for 4D compiled code (interpreted code is out: 2.5s). If you need to calculate an md5 in a trigger, don’t hesitate for a second – use a plug-in!


Ok. That’s all for this post. A long one, wasn’t it? I’ll try to be shorter next time but here, I have two main excuses: First of all, PHP Execute is so huge. I only talked about a few points points, but one could fill pages and pages on this topic. Secondly, I’m going on vacation: Naps, board games, swimming pool, rest, eat, Mojito, pool, etc…

See you in a few weeks!

RSS 0 comment(s) to this post