1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
|
<?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><? ></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
-->
|