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 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
|
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 1.13 $ -->
<appendix id="migration4">
<title>PHP 3からPHP 4への移行</title>
<section id='migration4.changes'>
<title>PHP 4での変更点</title>
<para>
PHP 4とこれに組み込まれたZendエンジンは、PHPの性能と機能を大
幅に向上させますが、既存のコードへの変更は最小限ですむように多くの
考慮がなされています。このため、PHP 3から4への移行は、
PHP/FI 2.0から PHP 3への移行と比べて非常に容易です。既存の PHP
3のコードの多くは無修正で実行可能です。しかし、実用環境でバージョ
ンを切替える際には、バージョン間の若干の差異を知り、使用するコード
について確認を行うことが必要です。以下の記述は、これらの事項につい
ていくつかの示唆を与えるものです。
</para>
</section>
<section id="migration4.php4.with.php3">
<title>PHP 3とPHP 4を同時に実行する</title>
<simpara>
最近のオペレーティングシステムでは、バージョン管理及びスコープ監理
を行う機能が提供されています。この機能により、1つのApacheサーバ上
のモジュールとしてPHP 3とPHP 4を同時に実行することが可能です。
</simpara>
<simpara>
この機能は、以下のプラットフォーム上での動作が確認されています。
</simpara>
<itemizedlist>
<listitem>
<simpara>
最近のbinutils (binutils 2.9.1.0.25 でテスト済み) を備えたLinux
</simpara>
</listitem>
<listitem>
<simpara>
Solaris 2.5以降
</simpara>
</listitem>
<listitem>
<simpara>
FreeBSD (3.2, 4.0 でテスト済み)
</simpara>
</listitem>
</itemizedlist>
<para>
この機能を使用するには、PHP 3および PHP 4でAPXS(--with-apxs)および
必要なリンク拡張(--enable-versioning)を指定します。それ以外の場合、
通常の命令が使用されます。例えば、
<informalexample>
<programlisting role="configure">
<![CDATA[
$ ./configure \
--with-apxs=/apache/bin/apxs \
--enable-versioning \
--with-mysql \
--enable-track-vars
]]>
</programlisting>
</informalexample>
</para>
</section>
<section id="migration4.configuration">
<title>設定ファイルの移行</title>
<para>
グローバル設定ファイル<filename>php3.ini</filename>は、名前が
<filename>php.ini</filename>に変更となりました。
</para>
<para>
Apache設定ファイルの場合、変更点はやや多くなっています。PHPモジュー
ルにより認識されるMIME型が変更となりました。
<informalexample>
<programlisting role="apache">
<![CDATA[
application/x-httpd-php3 --> application/x-httpd-php
application/x-httpd-php3-source --> application/x-httpd-php-source
]]>
</programlisting>
</informalexample>
</para>
<para>
以下の構文を使用することにより、(サーバに組み込まれているバージョ
ンに基づき)両方のバージョンで動作する設定ファイルを作成することが
可能です。
<informalexample>
<programlisting role="apache">
<![CDATA[
AddType application/x-httpd-php3 .php3
AddType application/x-httpd-php3-source .php3s
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
]]>
</programlisting>
</informalexample>
</para>
<simpara>
加えて、Apache用のPHPディレクティブが変更となっています。
</simpara>
<para>
PHP 4以降、PHPに関連するApacheディレクティブは以下の4種類のみと
なっています。
<informalexample>
<programlisting role="apache">
<![CDATA[
php_value [PHPディレクティブ名] [値]
php_flag [PHPディレクティブ名] [On|Off]
php_admin_value [PHPディレクティブ名] [値]
php_admin_flag [PHPディレクティブ名] [On|Off]
]]>
</programlisting>
</informalexample>
</para>
<simpara>
Adminの値とそれ以外の値には次の2つの違いがあります。
</simpara>
<itemizedlist>
<listitem>
<simpara>
Admin の値(またはフラグ)は、サーバ全体のApache設定ファイル(すな
わちhttpd.conf)でのみ設定可能です。
</simpara>
</listitem>
<listitem>
<simpara>
通常の値(またはフラグ)はセーフモードのようなある種のPHPディレク
ティブを制御できません(セーフモードの設定を.htaccessで上書きで
きるとしたら、セーフモードの目的は達成されなくなります)。逆に
Admin値では全てのPHPディレクティブの値を修整可能です。
</simpara>
</listitem>
</itemizedlist>
<simpara>
移行の過程をより容易にするために、PHP 4にはApache設定命令と.
htaccessファイルをPHP 3とPHP 4の両方で動作するように変換するス
クリプトがバンドルされています。これらのスクリプトは、MIME型の行を
変換しません。これらは自分で変更を行う必要があります。
</simpara>
<para>
Apache設定ファイルを変換するために、(scripts/apache/ディレクトリに
ある)apconf-conv.sh スクリプトを実行して下さい。 例えば、
<informalexample>
<programlisting role="shell">
<![CDATA[
~/php4/scripts/apache:# ./apconf-conv.sh /usr/local/apache/conf/httpd.conf
]]>
</programlisting>
</informalexample>
</para>
<simpara>
元の設定ファイルは、httpd.conf.origに保存されます。
</simpara>
<para>
.htaccess ファイルを変換するには、(同じくscripts/apache/ディレクト
リにある)aphtaccess-conv.sh スクリプトを実行して下さい。
<informalexample>
<programlisting role="shell">
<![CDATA[
~/php4/scripts/apache:# find / -name .htaccess -exec ./aphtaccess-conv.sh {} \;
]]>
</programlisting>
</informalexample>
</para>
<simpara>
同様に古い.htaccessファイルには.origが付加されて保存されます。
</simpara>
<simpara>
この変換スクリプトは、awkがインストールされていることを必要とします。
</simpara>
</section>
<section id='migration4.parser'>
<title>パーサの動作</title>
<para>
パーサと実行は、二つの完全に分割されたステップになりました。ファイ
ル中のコードの実行は、ファイル全体と必要なものが全て完全にパースさ
れるまで行われません。
</para>
<para>
この分割により PHP 4では requireやincludeで読み込まれるファイルが
構文的に完全であることが新たに必要となっています。PHP 4では、制御
構造の異なる制御部をファイル境界をまたいで配置することはできません。
このため、<literal>for</literal> ループまたは
<literal>while</literal>ループ、<literal>if</literal> 命令または
<literal>switch</literal>ブロックをあるファイルで開始し、
<literal>else</literal>、<literal>endif</literal>,
<literal>case</literal>、<literal>break</literal> 命令を別のファイ
ルに置くことはできません。
</para>
<para>
ループまたは他の制御構造の中で追加のコードを読み込むことは、PHP 4
では、全く問題ありません。制御用のキーワードや対応する波括弧
<literal>{...}</literal> だけは、同じコンパイル単位(ファイルまたは
<function>eval</function>された文字列)の中に置く必要があります。
</para>
<para>
しかし、配布されているコードではこうした記法は非常に悪いスタイルで
あるとみなされているようなので、この制約の影響は大きくないはずです。
</para>
<para>
使用ができなくなった他の機能としては、PHP 3ではほとんど使用され
ていませんが、requireで読みこまれたファイルから値を返すというもの
があります。includeで読み込まれたファイルから値を返すことは PHP
4でも可能です。
</para>
</section>
<section id='migration4.error-reporting'>
<title>エラー出力</title>
<section id='migration4.error-reporting.config'>
<title>設定変更</title>
<para>
PHP 3では、エラー出力レベルは異なったエラーレベルを意味する数
を合計した単純な数値で表されていました。よく使用されるのは、全て
のエラーと警告を出力する15と好ましくない形式や事項を通知するメッ
セージ以外の全てを出力する7です。
</para>
<para>
PHP 4では、より多くの異なったエラーおよび警告レベルを設定して
おり、設定ファイルにおいて意図する動作を設定するために定数シンボ
ルを使用することが可能になっています。
</para>
<para>
エラー出力レベルは、出力したくないエラーメッセージの警告レベルを
定数シンボル <literal>E_ALL</literal> と排他的論理和をとることに
より明示的に取り除くことにより指定することも可能になっています。
解りにくいでしょうか? では、ここで定数シンボル
<literal>E_NOTICE</literal> に分類される簡単な警告以外のエラー出
力を行うように設定したい場合を考えます。この場合、
<filename>php.ini</filename>において次のような指定を行います。
<literal>error_reporting = E_ALL & ~ ( E_NOTICE )</literal>
ここでさらに警告の出力を行わないようにしたい場合は、次のように括
弧の中でバイナリまたは演算子'|'を使用して適当な定数を追加します。
<literal>error_reporting= E_ALL & ~ ( E_NOTICE | E_WARNING
)</literal>
</para>
<warning>
<para>
従来の値7および15を使用してエラー出力を設定する方法は、パースエ
ラーを含む新たに追加されたエラークラスのいくつかが使用できなくな
るため、非常に悪い方法です。この場合、スクリプトが動作しない場合
でもエラーメッセージをどこにも表示しないため、非常に奇妙な動作と
なることがあります。
</para>
<para>
これにより、過去において、原因を追求が困難なスクリプトエンジンの
問題と報告された多くの再現不可能なバグレポートが、実際には、
requireで読み込まれたファイルにいくつかの '}' が足りず、エラー出
力の設定を誤っていたためにパーサがエラーを出力できなかったという
ことがあります。
</para>
<para>
このため、スクリプトが何も出力せずに終了する場合、エラー出力設定
をまず確認するべきです。現在のZend エンジンは十分に完成されてお
り、この種の奇妙な動作を発生しません。
</para>
</warning>
</section>
<section id='migration4.error-reporting.additions'>
<title>追加された警告メッセージ</title>
<para>
既存のPHP 3コードの多くは、このコードのように非常に悪いスタイル
の言語構造を使用しており、意図された通りに動作している場合でも、
他の部分を変更すると動作しなくなることがあります。PHP 4は、PHP
3が出力しないような場面でも多くの通知メッセージを出力します。
E_NOTICEメッセージをオフにすれば簡単に修正できますが、通常は問題
のあるコードを修正する方が良いでしょう。
</para>
<para>
通知メッセージが出力される場面で最も多いのが、引用符で括られてい
ない文字列定数を配列の添字として使用している場合です。その名前の
キーワードまたは定数が存在しない場合、PHP 3と4は共にこれら
を文字列として解釈し直します。しかし、そのコードのどこか他の場所
でその名前の定数が定義されている場合、このスクリプトは意図した通
りに動作しない可能性があります。これは、侵入者が文字列定数を再定
義して使用されるスクリプトが侵入者が有さないアクセス権を侵入者に
与えるようにする場合には、セキュリティのリスクとなることさえあり
ます。そこで、PHP 4では、例えば、
<literal>$HTTP_SERVER_VARS[REQUEST_METHOD]</literal> のように引用
符で括られていない文字列定数を使用した場合に警告を発生するように
なっています。これを
<literal>$HTTP_SERVER_VARS['REQUEST_METHOD']</literal> に変更する
ことにより、パーサは正常に動作し、コードのスタイルとセキュリティ
は大幅に改善されます。
</para>
<para>
その他、PHP 4では初期化されていない変数または配列要素を使用し
ていることを知らせるようになっています。
</para>
</section>
</section>
<section id='migration4.initializers'>
<title>イニシャライザ</title>
<para>
静的変数とクラスメンバのイニシャライザは、PHP 3では有効な式なら
ばなんでも指定可能でしたが、PHP 4ではスカラー値のみが指定可能で
す。これは、前記のようにパースと実行が分割されており、パーサがイニ
シャライザを処理する際にはまだコードは実行されていないためです。
</para>
<para>
クラスの場合、メンバ変数を初期化する際にはコンストラクタを使用する
べきです。静的変数の場合、単純なスカラー値以外のものに意味があるこ
とはまれです。
</para>
</section>
<section id='migration4.empty'>
<title><literal>empty("0")</literal></title>
<para>
恐らく最も動作上の問題のある変更は、<function>empty</function>の動
作に関するものでしょう。文字 '0' (ゼロ)のみを含む文字列は、PHP 3
とは異なり空文字列とみなされるようになりました。
</para>
<para>
数値の入力が要求された場合でも全てのinputフィールドは文字列を返し、
PHPは自動的に型変換を行う機能を有しているため、この動作の変更は、
Webアプリケーションにおいて有意義なものです。しかし、一方、コード
の正常動作を阻害する可能性があり、動作の内容を知らない場合には、
原因を追求しがたい動作の不備を生じる可能性があります。
</para>
</section>
<section id='migration4.missing'>
<title>廃止された関数</title>
<para>
PHP 4は多くの新しい機能と拡張を導入していますが、同時にいくつか
のバージョン3の関数は廃止されています。コア関数のいくつかは、
Zendエンジンを使用する4で導入されたパーサと実行モジュールの分割
という新たな形態では動作しないため、廃止されています。他の関数や拡
張機能全体もより新しい関数や拡張が同じタスクをより良くより一般的な
手法で行うため古くなっています。いくつかの関数は単にまだ移植されて
いないだけであり、いくつかの関数や拡張はライセンス上の問題により廃
止されています。
</para>
<section id='migration4.missing.concept'>
<title>コンセプトの変更により廃止された関数</title>
<para>
PHP 4ではパースと実行が分割されており、実行時に(現在、Zendエン
ジンに組み込まれている)パーサの動作を変更することは、パースが実行
前に既に行われているため、もうできません。
<filename>php.ini</filename> ファイルで適当な値を設定することによ
りパーサの動作を変更することが可能です。
</para>
<para>
PHP 3の機能でPHP 4でサポートされていない機能としては、
このマニュアルで記述されている実験的なデバッグインターフェースの
サポートがあります。独立した本格的なデバッガがZendの製品としてリ
リースされています。
</para>
</section>
<section id='migration4.deprecate'>
<title>推奨されない関数と拡張</title>
<para>
Adabas および Solid データベース拡張は、もはや推奨されません。
今後は、unified ODBC 拡張を代わりに使用して下さい。
</para>
</section>
<section id='migration4.unset'>
<title><function>unset</function>のステータスの変更</title>
<para>
<function>unset</function>はまだ使用可能ですが、PHP 4ではリテラ
ルとして実装されるように変更されており、このため、'真の'関数とし
てはもはや数えられていません。
</para>
<para>
これは、<function>unset</function> の動作を変更するものではないの
で、直接的な変更点があるわけではありませんが、
<function>function_exists</function> により "unset" を調べた場合、
<function>echo</function>のような他の低レベル関数と同様に
&false; が返されます。
</para>
<para>
その他のより実際的な変更としては、<function>unset</function> を間
接的にコールすることができなくなったというものがあります。このた
め、<literal>$func="unset"; $func($somevar)</literal> はもう動作
しません。
</para>
</section>
</section>
<section id='migration4.extensions'>
<title>PHP 3拡張機能</title>
<para>
PHP 3用に描かれた拡張モジュールは、PHP 4ではバイナリレベルでも
ソースレベルでも動作しません。元のソースにアクセス可能な場合、
PHP 4にその拡張モジュールを移植することは困難ではありません。
実際の移植の手順についての詳細な説明はこの文章には(まだ)含まれて
いません。
</para>
</section>
<section id='migration4.strings'>
<title>文字列中の変数置換</title>
<para>
PHP 4では文字列中の新しい変数置換の機構が追加されています。文字
列中の多次元配列からオブジェクトのメンバ変数と要素にアクセスが可能
となっています。
</para>
<para>
これを行うには、開き括弧の直後にドル記号が付くように変数を波括弧で
括る必要があります。
<literal>{$...}</literal>
</para>
<para>
オブジェクトのメンバ変数の値を文字列に埋め込むには、
<literal>"text {$obj->member} text"</literal> とします。一方、PHP
3 では、<literal>"text ".$obj->member." text"</literal> のよ
うにする必要がありました。
</para>
<para>
これによりコードの可読性が高まりますが、PHP 3用に描かれた既存の
スクリプトは動作しなくなる可能性があります。しかし、コード中の
<literal>{$</literal> という文字の組み合わせを調べることにより容易
にこの種の問題の確認が可能で、任意の検索/置換ツールにより
<literal>\{$</literal> に置換することにより対処可能です。
</para>
</section>
<section id='migration4.cookies'>
<title>クッキー</title>
<para>
PHP 3は、コード中の<function>setcookie</function>のコールとは逆
の順番でクッキーを設定するという好ましくない動作をしていました。
PHP 4はこの動作を変更し、コードでクッキーを設定したのと同じ順番
で正しくクッキーを設定するヘッダ行を生成します。
</para>
<para>
これによりいくつかの既存のコードが動作しなくなる可能性がありますが、
従来の動作は理解しにくく、将来的な更なる問題を防ぐために変更望まれ
ていました。
</para>
</section>
<section id='migration4.variables'>
<title>グローバル変数の扱い</title>
<para>
PHP 3とPHP 4の初期のバージョンでは、グローバル変数の扱いは「簡単であること」
に重点が置かれていましたが、PHP 4では「安全であること」に焦点が当てられています。
PHP 3では後述の例は問題なく動作しますが、PHP 4では unset($GLOBALS["id"]); とする
必要があります。これはグローバル変数の扱いに関する一つの例にすぎません。
PHP 4では多くの場合に $GLOBALS 変数を使用しなければならなくなりました。
詳細については<link linkend="references.global"><literal>グローバル</literal>
リファレンス</link>の章を参照してください。
</para>
<example>
<title>グローバル変数の移行</title>
<programlisting role="php">
<![CDATA[
<?php
$id = 1;
function test()
{
global $id;
unset($id);
}
test();
echo($id); // PHP 4では1と表示されます
?>
]]>
</programlisting>
</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:
-->
|