下位互換性のない変更点

多くの既存の PHP 4 のコードは変更無しで動作するはずですが、 以下の下位互換性がない変更点について注意する必要があります。

  • 新たな予約キーワードがいくつか あります。
  • strrpos()strripos() は、 needle として文字列全体を使用するようになりました。
  • 文字列オフセットの不正な使用は、E_WARNING ではなく E_ERROR を発生します。不正な使用の例は、次のようなものです。 $str = 'abc'; unset($str[0]);
  • array_merge() は、配列のみを指定できるよう 変更されました。配列以外の変数を指定した場合は、各パラメータ毎に E_WARNING が発生します。あなたのコードで 突然 E_WARNING が発生し始める可能性が あるため注意してください。
  • サーバー変数 PATH_TRANSLATED は、Apache2 SAPI では暗黙のうちに設定されません。 この動作は、Apache により設定されていない場合に SCRIPT_FILENAME と同じ値に 設定する PHP 4 と異なります。 この変更は、» CGI/1.1 の規約に従うためのものです。 詳細については、 » bug #23610 を参照してください。 また、マニュアルの $_SERVER['PATH_TRANSLATED'] についての記述も参照してください。 この問題は、PHP のバージョン >= 4.3.2 でも影響を及ぼします。
  • 定数 T_ML_CONSTANT は、 Tokenizerエクステンションで 定義されなくなりました。error_reporting にE_ALL を指定した場合、PHPは通知(notice)を生成します。 T_ML_CONSTANTは、全く使用されていませんが、 PHP 4 では定義されていました。PHP 4とPHP 5の両方において、 // と /* */ は、共に T_COMMENT 定数と 解釈されます。 しかし、PHP5からPHPにより解釈されるようになった PHPDoc形式のコメント /** */ は、T_DOC_COMMENT と認識されます。
  • variables_order に "S"が含まれる場合に、$_SERVERargc および argv と共に設定されます。 $_SERVERを作成しないような特別な設定を行った場合、 当然、argc および argv は 設定されません。 この変更は、CLI 版において variables_order の 設定によらず常に argc および argv を作成するために行われました。 これにより、CLI 版では、常にグローバル変数 $argc および $argv が設定されるようになりました。
  • プロパティを持たないオブジェクトはもはや"空"とはみなされません。
  • クラスを使用する前に宣言する必要がある場合もあります。 これは、PHP 5 の新機能 (たとえば interfaces など) を使用する場合にのみ生じます。 その他の場合の動作は従来と同じです。
  • get_class(), get_parent_class() および get_class_methods() は、 ケース依存(大文字小文字を区別)で 宣言時に使用されたクラス/メソッドの名前を返すようになっています これにより、以前の動作(クラス名は小文字で返される)に依存している古いスクリプト では問題を発生する可能性があります。 解決策としては、全てのスクリプトでこれらの関数を検索し、 strtolower()を使用するというものが考えられます。 このケース依存性に関する変更は、 自動的に定義される定数 __CLASS__, __METHOD__, および __FUNCTION__にも適用されます。 これらの値は、宣言時と同様に(ケース依存で)返されます。
  • ip2long() は、 無効なIPアドレスが関数の引数として渡された場合、 -1ではなく、FALSE を返すようになりました。
  • 読み込まれるファイルの中で関数が宣言されている場合、それが return の前もしくは後のどちらにあるかにかかわらず、 メインファイルの中でその関数を使用可能です。 このファイルが二度読み込まれると、関数が既に宣言済みであるため、 PHP 5 は致命的なエラーを発生します。一方、PHP 4 ではエラーを発生しません。 ファイルが読み込み済であるかどうかを調べて 読みこまれたファ入ルの内容を条件分岐でかえすのではなく、 include_once を使用することを推奨します。
  • Windows上で、 include_oncerequire_once は、まず、読みこまれるファイルのパスを正規化します。 これにより、A.php と a.php を読みこむ場合でもファイルは一度だけ読みこまれます。
  • 関数に配列を値渡ししたときに、 関数の中で配列の内部ポインタが移動してもそれをリセットしなくなりました。 PHP 4 では、関数に配列を渡したときに、関数内での配列の内部ポインタがリセットされていました。 一方 PHP 5 では、配列を関数に渡すと、 関数内での配列の内部ポインタの位置は配列が関数に渡されたときのままとなります。

例1 strrpos()strripos() は、 needleとして文字列全体を使用する

<?php
var_dump
(strrpos('ABCDEF','DEF')); //int(3)

var_dump(strrpos('ABCDEF','DAF')); //bool(false)
?>

例2 プロパティを持たないオブジェクトはもはや"空"とはみなされない

<?php
class test { }
$t = new test();

var_dump(empty($t)); // echo bool(false)

if ($t) {
    
// 実行される
}
?>

以下の例はPHP 4では有効でしたが、PHP 5では致命的なエラーを 発生します。

例3 クラスは使用前に宣言する必要がある

<?php
$test 
= new fubar();
$test->barfu();

class 
fubar {
    function 
barfu() {
        echo 
'fubar';
    }
}
?>

add a note add a note

User Contributed Notes 13 notes

up
6
john.g
20 years ago
PATH_TRANSLATED is handy when using Apache's ModRewrite engine, as it gives you the name and path of the resulting file rather than the one that was requested by the user. Since PHP 5.0 and Apache 2 no longer support this variable, I created a workaround by adding an environment variable to my ModRewrite command:

Original:
RewriteRule ^/test/(.*)\.php(.*) /test/prefix_$1.php$2

Adjusted:
RewriteRule ^/test/(.*)\.php(.*) /test/prefix_$1.php$2 [E=TARGET:prefix_$1.php]

I could then find out the resulting file name through the super global $_ENV, for instance:

<?php
echo "The actual filename is ".$_ENV['REDIRECT_TARGET'];
?>

Note: The "REDIRECT_" prefix appears to be allocated automatically by ModRewrite.
up
5
paul at oconnor-web dot net
16 years ago
The __call function will also lowercase the method arguement:

<?php
  
function __call($method, $args) {
     if (
$method == 'Foo') {
       return
true;
     } else {
       return
false
    
}
   }
?>

(= false)
up
3
Anonymous
18 years ago
is_a have been deprecated. You can simply replace all occurences with the new instanceOf operator, although this will break backwards-compatibility with php4.
up
1
Aggelos Orfanakos
17 years ago
As with array_merge(), array_merge_recursive() returns NULL in PHP 5 if a non-array parameter is passed to it.
up
1
nami
17 years ago
addition of the note on 07-Sep-2004 06:40

if you write down your code like this PHP5 will just work fine:

<?php
     $array_1
= array('key1'=>'oranges','key2'=>'apples');
    
$array_2 = array('key3'=>'pears','key4'=>'tomatoes');
    
$array_3 = array();
    
$arr_gemerged = array_merge($array_1,$array_2,$array_3);
     echo
"result:<br>";
    
print_r($arr_gemerged);
     echo
"<br>";
?>

---

so you have to declare array_3 as array() instead of NULL
up
1
cyberhorse
20 years ago
clone() is a php function now.

if you create a subclass, it no longer uses samename methods in superclass as a constructor.
up
0
kemal djakman
17 years ago
The handling of accessing empty property of a class error has also changed:
<?php

class Foo {

    var
$Bar = 'xxx';

    function
F() {
        echo
$this->$Bar;
    }
}

$Obj = new Foo();
$Obj->F();

?>

Notice the $ sign after object dereference opr?  $Bar is empty inside method F.   PHP4 would only generate a warning, PHP5 throws a fatal error
up
0
Amir Laher
17 years ago
Some other things to be aware of:

some extra strictness:
* object members can no longer be accessed using array-member syntax
* function-calls with too many arguments will now cause errors.

Also, from PHP5.2, custom session handlers are affected:
* Best not to use global objects in custom session-handling functions. These would get destructed *before* the session is written (unless session_write_close() is called explicitly).
up
0
Anonymous
20 years ago
Be careful with array_merge in PHP5.1 not only a E_WARNING is thrown, but also the result is an empty array. So if you merge two select queries and the last one is empty you will end up with no array at all.

<?php
        $array_1
= array('key1'=>'oranges','key2'=>'apples');
       
$array_2 = array('key3'=>'pears','key4'=>'tomatoes');
       
$array_3 = null;
       
$arr_gemerged = array_merge($array_1,$array_2,$array_3);
       
print_r($arr_gemerged);
        echo
"<br>";
?>

Result on php4:
Array ( [key1] => oranges [key2] => apples [key3] => pears [key4] => tomatoes )

Result on php5:
Warning: array_merge() [function.array-merge]: Argument #3 is not an array in /removed/by/danbrown/for/manual.php on line 7
up
-1
michael dot darmousseh at gmail dot com
14 years ago
Hack way to fix the array_merge problem so that it works with your existing php4 code

<?php
function array_merge5()
{
   
$args = func_get_args();
    foreach(
$args as $key=>$arg)
       
$args[$key] = (array) $arg;
    return
call_user_func_array("array_merge", $args);
}
?>

just put it somewhere completely accessible to your codebase and change all of your calls to array_merge to array_merge5.
up
-3
Sinured
17 years ago
Not mentioned above: The PHP/FI 2 function style (old_function aka cfunction) is no longer supported as of PHP 5.
up
-2
dward . maidencreek.com
20 years ago
Another change that we've had problems with while trying to use PHP4 code in PHP5 is how $this is carried across static method calls if they are not declared static in PHP5.  The main issue was that debug_backtrace() now shows the first class with -> instead of the second with :: in the backtrace element when the method in the second class was called statically (using ::) from a method in the first class.
up
-4
Steven
16 years ago
Three more that we discovered:

== 1. No longer can re-assign $this ==

The follwoing example works under PHP4 (it outputs "OK"), but produces a fatal error under PHP5:

<?php
 
class a
 
{
    var
$text;
    function
a() { $this->text = 'OK'; }
  }

  class
b
 
{
    var
$text = 'NOT OK';
    function
b() { $this = new a(); }
  }
   
 
$myClass = new b();
  echo
$myClass->text;
?>

== 2. No comments allowed after shorthand echo block ==

The follwoing example works under PHP4, but produces a sytax error under PHP5.

<?=//comment?>

== 3. Constructors return a reference as default ==

The follwoing example works under PHP4, but produces an E_NOTICE notice under PHP5.

<?php
 
class MyClass { function MyClass() { echo('OK'); } }
 
$myObj = null;
 
$myObj &= new MyClass();
?>

Removing the ampersand solves the problem
To Top