Noticeable Changes between PHP/FI 2.0 and PHP 3.0
=================================================

This file was designed to be viewed with a tab size of 4 characters.

This file is divided into 4 sections:
1.  Downwards incompatible language changes.  This section includes all of
    the changes in the core language which may require people to modify
    their scripts before using them with PHP 3.0.  It does NOT list
    changes made in the behavior of specific functions.
2.  New language features.  This section includes all of the new additions
    to the core language, that may be used to enhance scripts designed for
    PHP 3.0.  Likewise, it does not include a listing of new functions.
3.  Structural changes not directly effecting the end user.  The core
    of PHP 3.0 is a complete rewrite.  As such, many issues effecting
    PHP/FI 2.0 were addressed and vastly improved in this version,
    resulting in a much more stable and efficient implementation.  This
    section lists these changes in design.
4.  Other changes that don't fit in any of the above categories.

Please remember that PHP 3.0's core is a complete rewrite, and thus,
there may be other undocumented incompatibilities we haven't thought
of ourselves.  If you think you've found a incompatibility (or a new
feature) which is not listed here, please mail us at
php-dev@php.iquest.net.



												- Zeev

------------------------------------------------------------------------------

Downwards incompatible language changes
=======================================

[1]	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;?>

	The ability to use the short start tag ('<?') can be turned on and
	off using the short_tags() function. Whether it is enabled or not by
	default is a compile-time option (normally set to enabled by default).


[2]	Semicolons in if/elseif/else must be replaced with colons.

	For example, the equivalent of:

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

	in PHP 3.0 would be:

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

	Note that the endif is followed by a semicolon and not a colon even in
	PHP 3.0, which marks the end of the entire IF sentence.

	Also note that the implementation of the colon-mode and curly-braces
	mode in PHP 3.0 is identical, one isn't buggier than the other (note
	that I'm not saying they're not buggy, though :)


[3]	Semicolons in while loops must also be replaced with colons.

	For example, the equivalent of:

		while (expr);
		  statements
		  ...
		endwhile;

	in PHP 3.0 would be:

		while (expr):
		  statements
		  ...
		endwhile;

	Note that the endwhile is followed by a semicolon and not a colon even
	in PHP 3.0, which marks the end of the WHILE sentence.  As with the IF
	statement, the implementation of the colon-mode and curly-braces mode
	in PHP 3.0 is identical, one isn't buggier than the other.

	Also note that 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.


[4]	$foo[0] is no longer identical to $foo.

	In PHP/FI 2.0, a side-effect of the implementation caused $foo[0] to be
	identical to $foo.  This is not the case in PHP 3.0.


[5]	Expressions determine their types differently.

	The way expressions are evaluated has changed radically in PHP 3.0.
	Expressions are no longer given the type of the left argument, but are
	assigned types taking both types into account, and regardless of which
	is on the left side and which is on the right side.  On simple scripts
	that should probably not effect you, but if you've relied on this fact
	(even without realizing you do) it may change the way your scripts work.
	Consider the next example:

		$a[0]=5;
		$a[1]=7;

		$key = key($a);
		while ("" != $key) {
			echo "$key\n";
			next($a);
		}


	In PHP/FI 2.0, this would display both of $a's indices.  In PHP 3.0, it
	wouldn't display anything.  The reason is that in PHP/FI 2.0, because the
	left argument's type was string, a string comparison was made, and indeed
	"" does not equal "0", and the loop went through.  In PHP 3.0, 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, and since 0==0, the loop doesn't
	go through even once.  The fix for this is simple, by replacing the
	while statement with:

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

	This would first convert the integer 0 to a string "0", and then
	compare "" and "0", which are not equal, and the loop would go through
	as expected.  As mentioned later, casting operators are supported in
	PHP 3.0 for a quicker and more readable way of changing variables'
	types. For example, you could use:

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


[6]	The structure of error messages has changed.

	Although the error messages are usually more accurate, you won't be shown
	the actual line of text and actual place in which the error occured.
	You'll be supplied with the line number in which the error has occured,
	though.


[7]	The format string argument to echo is no longer supported.

	Use printf(format,arg1,arg2,arg3,...) instead (unlimited arguments).


[8]	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 the multidimensional array support).


[9]	Apache versions older than 1.2 are not supported anymore.

	The apache module requires apache 1.2 or later (1.3-beta is supported).


[10] 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.

[11]
		Some functions have changed names, are missing, or have been deprecated
		by other functions

	As a whole new rewrite, written by many more people and supporting many
	more APIs than it's predecessor, there's a good chance some of the functions
	you're used to from PHP/FI 2 aren't available in release 3, or have changed
	names.  Many functions that do exist behave a bit differently, mainly
	because they return different values for errors (false) but also for other
	reasons.  We can't list all of these functions here, simply because drawing
	a full comparison between the function sets of the two versions is way too
	much work.  If a converted PHP/FI 2 script doesn't work for you, nothing
	can replace the good old human eye going over the code, doublechecking
	with the online manual that each function still does what you expected it
	to do.

[12]	Other incompatibilities.

	It's not too unlikely that other documented behavior of PHP2 has changed
	in this release.  If you think you've found an example, please mail
	us at php-dev@php.iquest.net.  Even if you've found an undocumented
	feature of PHP2 that stopped working in PHP3, we'd like to know about it
	(although it's more than likely that it will not be supported).



------------------------------------------------------------------------------


New Language Features
=====================

[1]	Expressions

	PHP 3.0 includes a rich implementation of expressions, much more advanced
	than this of 2.0.  Just about any complex C-like or perl-like expression
	would work.  Support was added for assignment operators (+=, -=, *= etc),
	pre and post increment/decerement (e.g. $i++, ++$i) and the questionmark
	operator ( (expr?expr:expr) ).  Every assignment is now an expression
	with a value, which means stuff like $a = $b = $c = $d = 0;  would work.
	It is difficult to describe the power of expressions within a few lines
	of text, but if you're familiar with them, you probably get the picture.


[2]	for loops are now supported.

	for loops were fairly difficult to implement (in fact, we didn't find
	any parallel interpreter that supports for loops anywhere (no, perl is
	not an interpreter)).  The bottom line is that for loops work, and are
	around 5% slower than comparable while loops (that may vary), but often
	they're much nicer.

	The syntax is identical to the one of C:

		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,
	and after each iteration, the 3rd expression is evaluated.

	Colon-mode FOR loops are also supported:
	for (expr; expr; expr):
		statements
		...
	endfor;


[3]	do..while(expr) loops are now supported.

	Like 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);


[4]	break and continue statements are now supported inside loops.

	You can break out of loops, or continue to the next iteration of the
	loop using these 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.

	Note:  For this matter, switch statements are considered as loops.  So
	if you write "break 2;" inside a switch statement, you would be asking
	to break out of the switch, and the innermost loop in which is nested.


[5]	Switched to C-style declaration of functions.

	Here's a pretty useless function which makes a good example:

		function concat($str1,$str2)
		{
			return $str1.$str2;
		}

	NOTE:	The old style function definition is still supported, to
			allow easier upgrading from PHP/FI 2.0 scripts.  Simply
			change 'function' to 'old_function' for these functions.


[6]	OOP support

	Classes and inheritance are supported to a limited extent in PHP 3.0.
	Here's how to declare a simple class:

		class simple_class {
			var $property1,$property2;
			var $property3=5;

			function display() {
				printf("p1=%d, p2=%d, p3=%d\n",
					$this->property1,
					$this->property2,
					$this->property3);
			}
			function init($p1,$p2) {
				$this->property1 = $p1;
				$this->property2 = $p2;
			}
		};

	Here's how to create an object of that class:

		$obj = new simple_class;

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

		$obj->property1 = 7;

	would assign 7 to $property1 inside $obj.  Calling member functions is
	also simple:

		$obj->display()

	would run 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 pretty simple too:

		class complex_class extends simple_class {
			var $property4="test";

			function display() {
				printf("p1=%d, p2=%d, p3=%d, p4=%d\n",
					$this->property1,
					$this->property2,
					$this->property3,
					$this->property4);
			}
		}	

	Basically, 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 init() function, complex_class
	objects would have the same init() function as simple_class objects do.

	As with expressions, it's impossible to teach OOP in a few lines, and
	personally I'm unclear as to how useful this would be in day to day
	scripting.  If you like this, play with this until you figure it out :)

	Objects can reside in arrays, and can contain arrays.  However,
	a limitation of the current implementation doesn't allow an object
	to contain an array of objects (actually, this is allowed, but
	there's no way to address the properties of such an object directly,
	but only indirectly).  For example, assuming $a[3] is an object,
	$a[3]->b[2] is an object as well, you can't address the properties
	of $a[3]->b[2] (i.e. you can't write $a[3]->b[2]->foo = "bar", for
	instance).  


[7]	Function pointers are now supported.

	A simple illustrative example:

		$func_ptr = "time";
		$current_time = $func_ptr();

	is identical to

		$current_time = time();


[8]	Indirect references are much more powerful.

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

		$a = "b";
		$b = "c";
		$c = "d";
		$d = "e";
		$e = "Testing\n";

		echo $$$$$a;

	Would display $e's content, which is "Testing\n".

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

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

	would assign 5 to $test123.

[9]	A string concatenation operator was added, '+' no longer concatenates strings.

	A perl-like string concatenation operator was added, the '.' operator.
	It converts both of its arguments to strings, and concatenates them.
	For example:

		$result = "abcd".5;

	assigns "abcd5" to result.  Note that under PHP 3.0, the '+' operator
	no longer performs concatenation if its arguments are strings.  Use
	the '.' operator instead.

[10]	Supports passing function arguments by references instead of by value.

	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, but, when calling the function, you can
	decide on whether the variable you supply would actually be changed by
	the function, or a copy of it.

	Example:

		function inc($arg)
		{
			$arg++;
		}

		$i=0;
		inc($i);  # here $i in the outer scope wouldn't change, and remain 0
		inc(&$i); # here $i is passed by reference, and would change to 1


[11]	Support for multidimensional arrays.

	(Or as Andi calls them, 'hyperdimensional variables'.)

	The easiest way to define this support of PHP 3.0 is inductive -
	arrays can contain any type of variables, including other arrays.
	A simple example:

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

	Ok, so it may be not so simple.  Play with it, it's pretty powerful.


[12]	Array initialization is now supported.

	For example, let's say you want to initialize a lookup table to convert
	number to month names:

		$months = array("January", "February", "March",
						"April", "May", "June", "July", "August",
				 		"September", "October", "November", "December");

	would assign $months[0] to be January, $months[1] to be February, etc.
	Alternately, 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");

	Also, you can specify an index for every entry, not just the first one:

		$first_names = array("Doe"=>"John", "Gates"=>"William",
							"Clinton"=>"Bill" });

	would assign $first_names["Doe"]="John", etc.


[13]	Perl style lists now supported.

	Multiple values from arrays may now be assigned into 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);
	
	Would assign 'johndoe' into $username, 'x' into $passwd, etc.


[14]	Colons are supported in 'case' and 'default' statements.

	For example:

		switch($value) {
			case 'A':
				statement;
				break;
			case 'B':
				statement;
				break;
			case 'C':
				statement;
				/* fall-through */
			default:
				statement;
		}
	
	Semicolons are still supported, but when writing new scripts, they
	should be phased out in favour of colons.


------------------------------------------------------------------------------


Non Language Related New Features
=================================

[1]	Persistent resource lists.

	In plain english 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 PHP 3.0a1, 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).


[2]	Configuration file.

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


[3]	Syntax Highlighting.

	A syntax highlighter has been built into PHP 3.0, which means PHP 3.0 can
	display your code, syntax highlighted, instead of executing it.
	There are currently two ways to use the syntax highlighter.  One is to
	use the show_source() statement.  This statement is identical to the
	include() statement, except instead of executing the file, it displays
	its source syntax highlighted.
	The second way is possible only when running as an apache module, and is
	to define a special extension for PHP 3.0 source files (e.g. .php3s)
	and instruct apache to automatically syntax highlight them.


[4]	Loadable modules.

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


------------------------------------------------------------------------------


Other Interesting Issues
========================


[1]	Improved performance.

	The performance of PHP 3.0 is much better than the one of PHP/FI 2.0.
	Memory consumption has been dramatically reduced in many cases, due
	to the use of an internal memory manager, instead of apache's pools.
	Speedwise, PHP 3.0 is somewhere between 2 and 3 times faster than
	PHP/FI 2.0.


[2]	More reliable parser.

	After PHP 3.0 is well tested, it'll be pretty safe to say that it's
	more reliable than PHP/FI 2.0 is.  While PHP/FI 2.0 performed well on
	simple, and fairly complex scripts, a fundamental design difference
	from PHP 3.0 makes it more prone to errors.  In PHP 3.0, obscure parser
	problems are much less likely.


[3]	Improved C API.

	If you're a C coder, adding functionality to PHP was never easier.
	A pretty 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) - but of course,
	you can mess up here too :)


[4]	Name change.

	PHP/FI 2.0 was renamed to PHP 3.0, and the meaning has changed from
	'Personal Home Pages / Forms Interpreter' to 'PHP: Hypertext Preprocessor'.
	'Personal' home pages was an understatement for PHP/FI 2.0, and is
	definitely an understatement for PHP 3.0.
