Chapter 11:  PHP3 Embedded Scripting


PHP is a server-side, HTML-embedded scripting language, and an easy alternative to CGI scripting. Stronghold Web Server 3.0 comes with two PHP modules:

This chapter describes


PHP Quick Start

If you already have PHP/FI 2.0 or PHP3 scripts that you want to serve through Stronghold Web Server 3.0, you can quickly install them.

To install PHP files

If httpd.conf does not already contain these lines, you must add them and reload the server.

Make sure your PHP filenames include the filename extension that matches their MIME type:

Stronghold processes requested files automatically with the appropriate PHP module based on the filename extension.

If a .php or .php3 file contains no PHP script elements, PHP simply inserts access information at the foot of the file. If PHP script elements are present, PHP processes them each time the file is requested before sending it to the client.

If you do not want footers appended to your PHP files, you can turn them off globally or on a per-file basis. To turn them on or off globally, use the phpShowInfo configuration directive. To turn them off in individual files, add this tag:

<?setshowinfo(0)>


PHP Configuration

PHP configuration takes two forms:

Recompiling The PHP Modules

When you install Stronghold, you also install its PHP modules. By default, the modules are installed with all special features disabled. In order to enable the following features, you must recompile the PHP module you are using:

In order to reconfigure the PHP module to implement these special features, you must;

To reconfigure PHP3

  1. Switch to the PHP3 source directory:

    # cd ServerRoot/src/php3

  2. Run the setup script:

    # ./setup
    The script first asks you whether you want to compile PHP3 as an Apache module.

  3. Enter "Y" to compile PHP3 as a module.
  4. Enter the absolute path to the <ServerRoot> directory.
  5. Enter "Y" to enable character transfer tables or "N" to disable them.
    Transfer tables are useful if you are using mod_charset to support Cyrillic character sets. The mod_charset module is a third-party module that
    is not included with Stronghold. It is available from the Apache Module Registry at http://modules.apache.org/.
  6. Enter "N" to instruct the script not to compile PHP3 as an the httpd module.
  7. Enter "Y" to enable GD support or "N" to disable it.
    If you enter "Y," you must next enter the path to the directory that contains the installed GD library (available at http://www.boutell.com/gd/).
  8. Enter "Y" to enable Oracle support or "N" to disable it.
    If you enter "Y," you must next enter the path to the Oracle directory.
  9. Enter "Y" to enable iODBC support or "N" to disable it.
    If you enter "Y," you must next enter the path to the iODBC directory.
  10. Enter "Y" to enable OpenLink ODBC support or "N" to disable it.
    If you enter "Y," you must next enter the path to the OpenLink ODBC directory. OpenLink ODBC is available at http://www.openlinksw.com/.
  11. Enter "Y" to enable Adabas D support or "N" to disable it.
    If you enter "Y," you must next enter the path to the Adabas D directory. Adabas D is available at http://www.adabas.com/.
  12. Enter "Y" to enable Sybase support or "N" to disable it.
    If you enter "Y," you must next enter the path to the Sybase directory.
  13. Enter "Y" to enable Sybase-CT support or "N" to disable it.
    If you enter "Y," you must next enter the path to the Sybase-CT directory.
  14. Enter "Y" to enable MySQL support or "N" to disable it.
    If you enter "Y," you must next enter the path to the MySQL directory.
  15. Enter "Y" to enable mSQL support or "N" to disable it.
    If you enter "Y," you must next enter the path to the mSQL directory.
  16. Enter "Y" to enable PostgreSQL support or "N" to disable it.
    If you enter "Y," you must next enter the path to the PostgreSQL directory.
  17. Enter "Y" to enable Solid support or "N" to disable it.
    If you enter "Y," you must next enter the path to the Solid directory.
  18. Enter "Y" to enable LDAP support or "N" to disable it.
    If you enter "Y," you must next enter the path to the LDAP directory.
  19. Enter "Y" to enable Velocis support or "N" to disable it.
    If you enter "Y," you must next enter the path to the Velocis directory.
  20. Enter "Y" to enable CODBC support or "N" to disable it.
    If you enter "Y," you must next enter the path to the CODBC directory.
  21. Enter "Y" to enable unified ODBC support or "N" to disable it.
    If you enter "Y," you must next enter the path to the ODBC directory.
  22. Enter "Y" to enable the bundled dBase library or "N" to disable it.
  23. Enter "Y" to enable the bundled filePro library or "N" to disable it.
  24. Enter the path to your php3.ini file: Enter an absolute path to the directory that contains the php3.ini file. Enter "Y" to accept the default path. Enter "N" to ignore the php3.ini file.
  25. Enter "Y" to use the existing system's regular expression library or "N" to use the bundled one.
  26. Enter "Y" to enable debug information or "N" to disable it.
  27. Enter "Y" to enable PHP3's safe mode or "N" to disable it.
    If you enter "Y," you must next enter the path to the directory you want to use as a safe mode directory. Executables that can be run in safe mode should be located here.
  28. Enter "Y" to enable variable tracking or "N" to disable it.
    Variable tracking enables PHP3 to set the HTTP_GET_VARS, HTTP_POST_VARS and HTTP_COOKIE_VARS environment variables.
  29. Enter "Y" to enable magic quotes or "N" to disable them.
  30. Enter "Y" to enable remote debugging or "N" to disable it.
  31. Enter "Y" to enable BC-style math functions or "N" to disable them.
    Enter "Y" to enable the memory limit or "N" to disable it.
  32. Enter "Y" to enable support for short PHP HTML tags or "N" to disable it.
    See "Close-PHP and Open-PHP Tags" on page 11-7 for information about the short format.
  33. Enter "Y" to enable URL fopen wrappers or "N" to disable them.The script configures PHP3 and exits.
  34. Run make:

    # make

    Make creates new libphp.a and mod_php3.* files and saves them in ServerRoot/src Check that directory to make sure the new files were copied there; if not, you must copy them manually.
  35. Check your Configuration file to make sure it includes these three lines:

    Rule WANTHSREGEX=yes
    EXTRA_LIBS= ... -lphp -lm ...
    Module php3_module mod_php3.o

    If you are linking database connectivity or other libraries, the EXTRA_LIBS line must include those libraries.

  36. Recompile Stronghold as described in "Recompiling Stronghold" on page 8-6.

Configuring PHP

If you installed Stronghold Web Server 3.0 from scratch, the default server configuration file includes basic enablement for PHP3 files:

# config sample goes here

All PHP3-compliant scripts automatically work with this configuration if they


Major Changes from PHP 2.0 to PHP3

The core of PHP has been completely rewritten from scratch to create PHP3. Several improvements were made to the language that also render it backwards-incompatible. Some low-level, undocumented features of PHP 2.0 may not to work in PHP3. It's possible that some documented behaviour of PHP 2.0 has also changed in this release and is not specified here.

The PHP3 module comes with a conversion program that can automatically convert your old PHP/FI 2.0 scripts. It can be found in the convertor/ subdirectory of the PHP3 distribution. However, this program only catches the syntax changes; your scripts may still require manual modification. Read this section carefully and take all changes into account.

This section explains three kinds of changes:

Backward Incompatibilities

Several new aspects of the language render PHP 2.0 code incompatible with PHP3. Affected features include

Close-PHP and Open-PHP Tags

The close-PHP tag has changed from > to ?>. This means that instead of writing

<?echo $title;>

you should write:

<?echo $title;?>

PHP3 also includes support for a longer-form start tag that is XML-compliant:

<?php echo $title;?>

Support for the short start tag (<?) can be enabled and disabled using the php3_short_open_tag directive.

Semicolons in `if,' elseif,' and 'else' Statements

Semicolons in if, elseif, and else statements must be replaced with colons. For example, the equivalent of

if (expr);
   statements
   ...
elseif (expr);
   statements
   ...
else;
   statements
endif;

in PHP3 is

if (expr):
   statements
   ...
elseif (expr):
   statements
   ...
else:
   statements
endif;

Note that the endif is followed by a semicolon and not a colon. Even in PHP3, a semicolon must mark the end of the entire if sentence. Also note that the implementation of the colon mode and curly braces mode in PHP3 is identical; one is not preferable to the other.

Semicolons in `while' Loops

Semicolons in while loops must be replaced with colons. For example, the equivalent of

while (expr);
   statements
   ...
endwhile;

in PHP3 is:

while (expr):
   statements
   ...
endwhile;

Note that the endwhile is followed by a semicolon and not a colon. Even in PHP3, the semicolon marks the end of the while sentence. As with the if statement, the implementation of the colon-mode and curly-braces mode in PHP3 is identical; one is not preferable over the other.


Failing to change the semicolon to a
colon can result in scripts that get stuck in the while loop because the
loop-condition never changes.

`$foo[0]' and `$foo'

In PHP 2.0, a side-effect of the implementation made $foo[0] identical to $foo. In PHP3, the two are no longer identical.

Expression Type Determination

The way expressions are evaluated has changed radically in PHP3. Expressions are no longer given the type of the left argument, but are assigned types taking both types into account, regardless of which is on the left side and which is on the right side. This should not affect simple scripts, but it may change the way some scripts work.

Consider this example:

$a[0]=5;
$a[1]=7;
$key = key($a);
while ("" != $key) {
echo "$keyn";
next($a);
}
In PHP 2.0, this would display both of $a's indices. In PHP3, it doesn't display anything. The reason is that in PHP 2.0, a string comparison was made because the left argument's type was string and "" does not equal "0," so the loop went through. In PHP3, when a string is compared with an integer, an integer comparison is made (the string is converted to an integer). This results in comparing atoi(""), which is 0, and $key, which is also 0. Since 0==0, the loop doesn't go through at all.

The fix for this is simple. If we replace the while statement with

while ("" != stringval($key)) {

the script would first convert the integer 0 to a string "0," then compare "" and "0," which are not equal, and the loop would go through as expected. Casting operators are supported in PHP3 as a quicker and more readable way of changing variables' types. For example, you could use the following:

while ("" != (string)$key) {

Plus (+) and Minus (-) Operators

In PHP2, you could add two strings together to get their concatenation, and subtract them to remove all occurences of one from the other. In PHP3, you should use the string concatenation operator (.) to concatenate strings, and the ereg_replace function to replace or remove substrings from a string. For example:

$a = 123;
$string = "This is as easy as " . $a;
$string = ereg_replace("This is as easy as ", "", $string);

Error Messages

The structure of error messages has changed. Although the error messages are usually more accurate in PHP3, they don't include the actual line of text or the actual place in which the error occurred. They do include the line number in which the error has occurred.

No Support for The Format String Argument to `echo'

The format string argument to echo is no longer supported.Use printf(format,arg1,arg2,arg3,...) instead. Arguments are unlimited.

No Support For Read-Mode `$array[]'

The use of read-mode $array[] is no longer supported. That is, you cannot traverse an array by having a loop that does $data = $array[]. Use current() and next() instead. Also, $array1[] = $array2 does not append the values of $array2 to $array1, but appends $array2 as the last entry of $array1. See "Support for Multidimensional Arrays or `Hyperdimensional Variables'" on page 11-16.

Short-Circuited Boolean Evaluation

In PHP3 boolean evaluation is short-circuited. This means that in an expression like

(1 || test_me())

the function test_me() would not be executed since the nothing can change the result of the expression after the 1. This is a minor compatibility issue, but may cause unexpected side effects.

Function True/false Return Values

Most internal functions have been rewritten so they return TRUE when successful and FALSE when failing, as opposed to 0 and -1 in PHP/FI 2.0, respectively. The new behaviour allows for more logical code, like $fp = fopen("/your/file") or fail("darn!");. Because PHP/FI 2.0 had no clear rules for what functions should return when they failed, most such scripts will probably have to be checked manually after using the 2.0 to 3.0 convertor.

An example of the old return values:

$fp = fopen($file, "r");
if ($fp == -1);
   echo("Could not open $file for reading<br>\n");
endif;

An example of the new return values:

$fp = @fopen($file, "r") or print("Could not open $file for reading<br>\n");

No Support For Page Logging or Access Restrictions

The PHP development team believes that this functionality does not belong in the core of PHP. Page logging can be implemented using auto-appended or prepended scripts without internal support in the core. Stronghold Web Server 3.0 has its own access control features.

No Support For Indirect References Inside Quoted Strings

PHP2-style indirect reference inside quoted strings is no longer supported. That is, if $foo="bar", and $bar="abc", in PHP2, "$$foo" would print out "abc". In PHP3, this would print "$bar" (the contents of $foo is replaced with "bar"). To use indirect reference in PHP3 inside quoted strings, you should use the new notation: "${$foo}". The standard $$foo notation will work outside of the quoted string. See also "More Powerful Indirect References" on page 11-16.

Function Changes

As a whole new rewrite, written by many more people and supporting many more APIs than its predecessor, some of the functions from PHP/FI 2 are not available in release 3, or have changed names. Many functions that do still exist behave differently, mainly because they return different values for errors (false), but also for other reasons. This guide cannot list all of these functions, simply because drawing a full comparison between the function sets of the two versions is an enormous task. If a converted PHP/FI 2 script does not work, analyze the code manually and double-check with original PHP3 manual at:
http://www.php.net/manual/.

New Language Features

PHP3 includes some new language features, including:

advanced expressions support for `for' loops support for `do...while(expr)' loops support for `break' and `continue' statements inside loops support for C-style declaration of functions OOP support support for function pointers more powerful indirect references new string concatenation operator support for passing function arguments by reference support for multidimensional arrays or `hyperdimensional variables' support for array initialization support for perl-style lists support for colons in `case' and `default' statements

Advanced Expressions

PHP3 includes a rich implementation of expressions. Nearly any complex C-like or perl-like expression works. Support has been added for:

assignment operators (+=, -=, *= etc.), pre and post increment/decrement (for example $i++, ++$i), and the question mark operator ( (expr?expr:expr) ). Every assignment is now an expression with a value, which means that code like $a = $b = $c = $d = 0; work.

Support for `for' Loops

Although for loops work, they are about five percent slower than comparable while loops, but they're often preferable. The syntax is identical to that of C, as in

for (expr; expr; expr) statement;
or

for (expr; expr; expr) { statements ... }
The first expression is executed the first time the loop is encountered. The loop is run as long as the second expression is evaluated as TRUE. After each iteration, the 3rd expression is evaluated.


There is no support for colon-mode for loops (for:...endfor,). and notsupport is planned.

Support for `do...while(expr)' Loops

As with its C parallel, the statements inside a do...while loop are run once the first time the loop is encountered, and then as long as the expression evaluates as true.

For example:

do {
statements;
} while ($i++ < $max);

Support for `break' and `continue' statements inside loops

A script can break out of loop, or continue to the next iteration of the loop using "break" and "continue" statements. A special feature of PHP is the ability to specify an expression argument to break or continue, which specifies how many loops you want to break out from or continue to. For example:

for ($i=0; $i<10; $i++) {
   for ($j=0; $j<10; $j++) {
      if ($j>5)
         break;
      if ($i>5)
         break 2;
   }
}

The first break statement would end the inner loop every time $j is greater than 5. The second break statement would end both the inner and outer loop when $i is greater than 5.


In addition, switch statements are treated as loops. If you write "break 2;" inside a switch statement, you are asking to break out of the switch and the innermost loop in which it is nested.

Support for C-Style Declaration of Functions

For example:

function concat($str1,$str2)
{
   return $str1.$str2;
}
Old-style function declarations should be changed from function to old_function.

OOP Support

Classes and inheritance are supported to a limited extent in PHP3. The following example shows how to declare a simple class:

class simple_class {
   var $property1,$property2;
   var $property3=5;
function display() {
   printf("p1=%d, p2=%d, p3=%dn,"
      $this->property1,
      $this->property2,
      $this->property3);
}
function init($p1,$p2) {
   $this->property1 = $p1;
   $this->property2 = $p2;
}
};

The next example shows how to create an object of that class:

$obj = new simple_class;

At this point, $obj is an object with two uninitialized variables, one initialized variable, and two member functions. No protection is made on the internals of the object, and using its properties is simple:

$obj->property1 = 7;

This assigns 7 to $property1 inside $obj. Calling member functions is also simple:

$obj->display()

This runs the display() member function of $obj. Note that the implementation of display() uses the special variable $this, which is replaced with the object the function is called on.

Inheritance is also simple:

class complex_class extends simple_class {
   var $property4="test";
function display() {
   printf("p1=%d, p2=%d, p3=%d, p4=%dn,"
      $this->property1,
      $this->property2,
      $this->property3,
      $this->property4);
}
}
The class complex_class inherits everything from its parent, simple_class, except properties or member functions which override the ones in the parent. In this example, since we supply an alternative display() function, it would be used with complex_class objects instead of the display() function that was declared in simple_class. On the other hand, since we don't supply an alternative in it() function, complex_class objects would have the same init() function as simple_class objects do.

For example, you can do

$a[0] = $obj;

but you cannot reference to $a[0]'s properties using

$a[0]->...

This will be implemented in a later release of PHP.

Support for Function Pointers

For example,

$func_ptr = "time";
$current_time = $func_ptr();
is identical to

$current_time = time();

More Powerful Indirect References

For example, one can use the dollar operator an infinite amount of times:

$a = "b";
$b = "c";
$c = "d";
$d = "e";
$e = "Testing";
echo $$$$$a;

This displays $e's content, which is "Testing."

In addition, one can use complex expressions to generate variable names using a perl-like notation:

$i="123";
${"test"+$i} = 5;

This assigns 5 to $test123.

Support for Passing Function Arguments By Reference

Support for passing function arguments by reference instead of by value has been added. This doesn't result in having to change the function implementations in any way. However, when calling the function you can decide whether the variable you supply will actually be changed by the function, or a copy of it.

For example:

function inc($arg)
{
   $arg++;
}
$i=0;
inc($i); /* here $i in the outer scope remains 0 */
inc(&$i); /* here $i is passed by reference and becomes 1 */

Support for Multidimensional Arrays or `Hyperdimensional Variables'

The easiest way to define this support of PHP3 is inductive: arrays can contain any type of variables, including other arrays. For example:

$a[0]=5;
$a[1]["testing"]=17;
$b["foo"]=$a;

Support for Array Initialization

For example, imagine that you want to initialize a lookup table to convert month numbers to month names:

$months = array("January," "February," "March,"
   "April," "May," "June," "July," "August,"
   "September," "October," "November," "December");
This example assigns $months[0] to be January, $months[1] to be February, and so on. Alternatively, you may want the count to start at 1 instead of 0. You can do so easily:

$months = array(1=>"January," "February," "March,"
   "April," "May," "June," "July," "August,"
   "September," "October," "November," "December");
You can also specify an index for every entry, not just the first one:

$first_names = array("Doe"=>"John,"
   "Gates"=>"William," "Clinton"=>"Bill" });
This example assigns $first_names["Doe"]="John" and so on.

Support for Perl-Style Lists

Multiple values from arrays may now be assigned to several variables using one assignment. For example:

$str = "johndoe:x:555:555:Doe, John:/home/johndoe:/bin/tcsh";
list($username,$passwd,$uid,$gid,$realname,$homedir,$shell) = explode(":,"$str);

This example assigns "johndoe" to $username, "x" to $passwd, and so on.

Support for Colons in `case' and `default' Statements

For example:

switch($value) {
case `A':
   statement;
   break;
case `B':
   statement;
   break;
case `C':
   statement;
   /* fall-through */
default:
   statement;
}

Other New Features

PHP3 includes some new features that are not language-related:

Persistent Resource Lists

This means that there's now an easy way of writing the SQL drivers so that they don't open and close the SQL link every time, but instead open it the first time it's required, and then use it on every later hit. As of PHP3a1, only the MySQL, mSQL and PostgresSQL drivers have been changed (rewritten) to take advantage of this option. To use it, use mysql_pconnect() instead of mysql_connect() (or the equivalents for the two other databases).

Configuration File

PHP now has its own configuration file, and many compile-time options of PHP2 are now configurable at runtime.

Syntax Highlighting

A syntax highlighter has been built into PHP3, which means PHP3 can display your code, syntax highlighted, instead of executing it. Right now, it's only easy to do this by telling Stronghold to execute a certain extension (for example, .php) and syntax highlighting another extension (for example, .phps). A future version will probably include display_source (filename) which works like include(), only it displays the syntax highlighted source instead of executing the included code.

Loadable Modules

This has a huge impact on the Windows version, and will probably be used in the UNIX environment as well. One can now add PHP internal functions at runtime by loading a dynamic module. This is known to work under Solaris, Linux, and Win32 at this time, but will be ported to any other capable platform if an incompatibility is found.

Improved Performance

The performance of PHP3 is much better than that of PHP 2.0. Memory consumption has been dramatically reduced in many cases, due to the use of an internal memory manager, instead of Stronghold's pools. Speed-wise, PHP3 is somewhere between 2 and 3 times faster than PHP 2.0.

More Reliable Parser

While PHP 2.0 performed well on simple, and fairly complex scripts, a fundamental design difference from PHP3 makes it more prone to errors. In PHP3, obscure parser problems are much less likely.

Improved C API

If you're a C coder, adding functionality to PHP was never easier. A well-documented API is available (apidoc.txt), and you no longer have to touch the parser or scanner code when adding your function. Also, it's more complicated to "go wrong" when implementing a PHP3 function than it was in PHP2 (no stack to maintain).