php-doc-en/appendices/migration.xml
Mehdi Achour 406be9eedc more CS
git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@147957 c90b9560-bf6c-de11-be94-00142212c4b1
2004-01-06 09:23:31 +00:00

419 lines
12 KiB
XML

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- $Revision: 1.25 $ -->
<appendix id="migration">
<title>Migrating from PHP/FI 2 to PHP 3</title>
<section id="migration.about">
<title>About the incompatibilities in 3.0</title>
<simpara>
PHP 3.0 is rewritten from the ground up. It has a proper parser
that is much more robust and consistent than 2.0's. 3.0 is also
significantly faster, and uses less memory. However, some of
these improvements have not been possible without compatibility
changes, both in syntax and functionality.
</simpara>
<simpara>
In addition, PHP's developers have tried to clean up both PHP's
syntax and semantics in version 3.0, and this has also caused some
incompatibilities. In the long run, we believe that these changes
are for the better.
</simpara>
<simpara>
This chapter will try to guide you through the incompatibilities
you might run into when going from PHP/FI 2.0 to PHP 3.0 and help
you resolve them. New features are not mentioned here unless
necessary.
</simpara>
<simpara>
A conversion program that can automatically convert your old
PHP/FI 2.0 scripts exists. It can be found in the
<filename class="directory">convertor</filename> subdirectory of the PHP 3.0
distribution. This program only catches the syntax changes though,
so you should read this chapter carefully anyway.
</simpara>
</section>
<section id="migration.old-function">
<title><literal>old_function</literal></title>
<simpara>
The <literal>old_function</literal> statement allows you to
declare a function using a syntax identical to PHP/FI2 (except you
must replace 'function' with 'old_function'.
</simpara>
<simpara>
This is a deprecated feature, and should only be used by the
PHP/FI2->PHP 3 convertor.
</simpara>
<warning>
<para>
Functions declared as <literal>old_function</literal> cannot be
called from PHP's internal code. Among other things, this means
you can't use them in functions such as
<function>usort</function>, <function>array_walk</function>, and
<function>register_shutdown_function</function>. You can get
around this limitation by writing a wrapper function (in normal
PHP 3 form) to call the <literal>old_function</literal>.
</para>
</warning>
</section>
<section id="migration.startendtags">
<title>Start/end tags</title>
<para>
The first thing you probably will notice is that PHP's start and end
tags have changed. The old <literal>&lt;? &gt;</literal> form has been
replaced by three new possible forms:
<example>
<title>Migration: old start/end tags</title>
<programlisting role="php">
<![CDATA[
<? echo "This is PHP/FI 2.0 code.\n"; >
]]>
</programlisting>
</example>
As of version 2.0, PHP/FI also supports this variation:
<example>
<title>Migration: first new start/end tags</title>
<programlisting role="php">
<![CDATA[
<? echo "This is PHP 3.0 code!\n"; ?>
]]>
</programlisting>
</example>
Notice that the end tag now consists of a question mark and a
greater-than character instead of just greater-than. However, if
you plan on using XML on your server, you will get problems with
the first new variant, because PHP may try to execute the XML
markup in XML documents as PHP code. Because of this, the
following variation was introduced:
<example>
<title>Migration: second new start/end tags</title>
<programlisting role="php">
<![CDATA[
<?php echo "This is PHP 3.0 code!\n"; ?>
]]>
</programlisting>
</example>
Some people have had problems with editors that don't understand
the processing instruction tags at all. Microsoft FrontPage is one
such editor, and as a workaround for these, the following variation
was introduced as well:
<example>
<title>Migration: third new start/end tags</title>
<programlisting role="php">
<![CDATA[
<script language="php">
echo "This is PHP 3.0 code!\n";
</script>
]]>
</programlisting>
</example>
</para>
</section>
<section id="migration.if-endif">
<title>if..endif syntax</title>
<para>
The `alternative' way to write if/elseif/else statements, using if();
elseif(); else; endif; cannot be efficiently implemented without
adding a large amount of complexity to the 3.0 parser. Because of
this, the syntax has been changed:
<example>
<title>Migration: old if..endif syntax</title>
<programlisting role="php">
<![CDATA[
if ($foo);
echo "yep\n";
elseif ($bar);
echo "almost\n";
else;
echo "nope\n";
endif;
]]>
</programlisting>
</example>
<example>
<title>Migration: new if..endif syntax</title>
<programlisting role="php">
<![CDATA[
if ($foo):
echo "yep\n";
elseif ($bar):
echo "almost\n";
else:
echo "nope\n";
endif;
]]>
</programlisting>
</example>
Notice that the semicolons have been replaced by colons in all
statements but the one terminating the expression (endif).
</para>
</section>
<section id="migration.while">
<title>while syntax</title>
<para>
Just like with if..endif, the syntax of while..endwhile has changed
as well:
<example>
<title>Migration: old while..endwhile syntax</title>
<programlisting role="php">
<![CDATA[
while ($more_to_come);
...
endwhile;
]]>
</programlisting>
</example>
<example>
<title>Migration: new while..endwhile syntax</title>
<programlisting role="php">
<![CDATA[
while ($more_to_come):
...
endwhile;
]]>
</programlisting>
</example>
</para>
<warning>
<simpara>
If you use the old while..endwhile syntax in PHP 3.0,
you will get a never-ending loop.
</simpara>
</warning>
</section>
<section id="migration.expr">
<title>Expression types</title>
<simpara>
PHP/FI 2.0 used the left side of expressions to determine what type
the result should be. PHP 3.0 takes both sides into account when
determining result types, and this may cause 2.0 scripts to behave
unexpectedly in 3.0.
</simpara>
<para>
Consider this example:
<informalexample>
<programlisting role="php">
<![CDATA[
$a[0]=5;
$a[1]=7;
$key = key($a);
while ("" != $key) {
echo "$keyn";
next($a);
}
]]>
</programlisting>
</informalexample>
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 2.0,
because the left argument's type was string, a string comparison
was made, and indeed <literal>""</literal> does not equal
<literal>"0"</literal>, 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 <literal>atoi("")</literal> which is
<literal>0</literal>, and <literal>variablelist</literal> which is
also <literal>0</literal>, and since <literal>0==0</literal>, the
loop doesn't go through even once.
</para>
<para>
The fix for this is simple. Replace the while statement with:
<informalexample>
<programlisting role="php">
<![CDATA[
while ((string)$key != "") {
]]>
</programlisting>
</informalexample>
</para>
</section>
<section id="migration.errors">
<title>Error messages have changed</title>
<simpara>
PHP 3.0's error messages are usually more accurate than 2.0's were,
but you no longer get to see the code fragment causing the error.
You will be supplied with a file name and a line number for the
error, though.
</simpara>
</section>
<section id="migration.booleval">
<title>Short-circuited boolean evaluation</title>
<simpara>
In PHP 3.0 boolean evaluation is short-circuited. This means that
in an expression like <literal>(1 || test_me())</literal>, the
function <function>test_me</function> would not be executed since
nothing can change the result of the expression after the
<literal>1</literal>.
</simpara>
<simpara>
This is a minor compatibility issue, but may cause unexpected
side-effects.
</simpara>
</section>
<section id="migration.truefalse">
<title>Function &true;/&false; return values</title>
<simpara>
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 <literal>$fp = fopen("/your/file") or
fail("darn!");</literal>. 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.
</simpara>
<para>
<example>
<title>Migration from 2.0: return values, old code</title>
<programlisting role="php">
<![CDATA[
$fp = fopen($file, "r");
if ($fp == -1);
echo("Could not open $file for reading<br />\n");
endif;
]]>
</programlisting>
</example>
<example>
<title>Migration from 2.0: return values, new code</title>
<programlisting role="php">
<![CDATA[
$fp = @fopen($file, "r") or print("Could not open $file for reading<br />\n");
]]>
</programlisting>
</example>
</para>
</section>
<section id="migration.other">
<title>Other incompatibilities</title>
<itemizedlist>
<listitem><simpara>
The PHP 3.0 Apache module no longer supports Apache versions
prior to 1.2. Apache 1.2 or later is required.
</simpara></listitem>
<listitem><simpara>
<function>echo</function> no longer supports a format string.
Use the <function>printf</function> function instead.
</simpara></listitem>
<listitem><simpara>
In PHP/FI 2.0, an implementation side-effect caused
<literal>$foo[0]</literal> to have the same effect as
<literal>$foo</literal>. This is not true for PHP 3.0.
</simpara></listitem>
<listitem>
<simpara>
Reading arrays with <literal>$array[]</literal> is no longer
supported
</simpara>
<simpara>
That is, you cannot traverse an array by having a loop that does
<literal>$data = $array[]</literal>. Use <function>current</function>
and <function>next</function> instead.
</simpara>
<simpara>
Also, <literal>$array1[] = $array2</literal> does not
append the values of <literal>$array2</literal> to
<literal>$array1</literal>, but appends
<literal>$array2</literal> as the last entry of
<literal>$array1</literal>. See also multidimensional array
support.
</simpara>
</listitem>
<listitem>
<simpara>
<literal>"+"</literal> is no longer overloaded as a
concatenation operator for strings, instead it converts it's
arguments to numbers and performs numeric addition. Use
<literal>"."</literal> instead.
</simpara>
</listitem>
</itemizedlist>
<example>
<title>Migration from 2.0: concatenation for strings</title>
<programlisting role="php">
<![CDATA[
echo "1" + "1";
]]>
</programlisting>
<para>
In PHP 2.0 this would echo 11, in PHP 3.0 it would
echo 2. Instead use:
<programlisting role="php">
<![CDATA[
echo "1"."1";
]]>
</programlisting>
<programlisting role="php">
<![CDATA[
$a = 1;
$b = 1;
echo $a + $b;
]]>
</programlisting>
</para>
<para>
This would echo 2 in both PHP 2.0 and 3.0.
<programlisting role="php">
<![CDATA[
$a = 1;
$b = 1;
echo $a.$b;
]]>
</programlisting>
This will echo 11 in PHP 3.0.
</para>
</example>
</section>
</appendix>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->