2020/11/26にPHP8.0.0がリリースされました。
ということで、UPGRADINGに載っている機能や変更点をだいたい全部見て回ることにします。
Backward Incompatible Changes
後方互換性のない変更。
なお、ここで削除される機能の多くは何年も前から公知されています。
PHPコア
match
is now a reserved keyword.
match
が予約語になりました。
match構文の導入に伴う措置です。
function match(){}
// PHP8.0
Parse error: syntax error, unexpected token "match", expecting "("
// PHP7.4
エラーは起こらない
Assertion failures now throw by default.
assertのデフォルト動作が例外になりました。
assert(false);
// PHP8.0
Fatal error: Uncaught AssertionError: assert(false)
// PHP7.4
Warning: assert(): assert(false) failed
PHP7.4以前と同じ動作に戻すにはini設定assert.exception=0
を設定します。
ちなみにPHP7.0以降、アサート文はコンパイル時に除去されて実行コストが0になるので、気軽に突っ込んでおけます。
便利なのでどんどん使いましょう。
Removed ability to call non-static methods statically.
静的でないメソッドを静的に呼び出すことができなくなりました。
class HOGE{
public function fuga(){}
}
HOGE::fuga();
// PHP8.0
Fatal error: Uncaught Error: Non-static method HOGE::fuga() cannot be called statically
// PHP7.4
Deprecated: Non-static method HOGE::fuga() should not be called statically
これまでは警告は出るものの実行自体はできていました。
今後は致命的エラーになります。
Removed (unset) cast.
(unset)
キャストが削除されました。
$a = 1;
(unset)$a;
// PHP8.0
Fatal error: The (unset) cast is no longer supported
// PHP7.4
Deprecated: The (unset) cast is deprecated
今後は普通にunset($a);
としましょう。
Removed track_errors ini directive.
ini設定track_errors
が削除されました。
これは何かというと$php_errormsgです。
track_errors
が有効になっていると、最後に発生したエラーメッセージが$php_errormsg
に登録されるという謎機能です。
デフォルトはずっとオフで、またPHP7.2でE_DEPRECATEDになったので使っている人もほとんどいないでしょうが、今後はerror_get_lastを使いましょう。
Removed the ability to define case-insensitive constants.
defineの第三引数$case_insensitive
が削除されました。
define('HOGE', 'FUGA', true);
var_dump(HOGE, HoGe);
// PHP8.0
Warning: define(): Argument #3 ($case_insensitive) is ignored
// PHP7.4
FUGA, FUGA // Deprecated: define(): Declaration of case-insensitive constants is deprecated
trueにすると定数が大文字小文字を区別しなくなるという意味のわからない機能です。
PHPは大文字小文字を区別するかしないかはわりかしややこしいのですが、関数/メソッドは区別しない、それ以外は区別する、という認識でだいたい大丈夫です。
実装上は、一律して区別するものだと考えておいたほうが楽でしょう。
Access to undefined constants now always results in an Error exception.
未定義定数にアクセスすると致命的エラーが発生します。
var_dump(HOGE);
// PHP8.0
Fatal error: Uncaught Error: Undefined constant "HOGE"
// PHP7.4
HOGE // Warning: Use of undefined constant HOGE - assumed 'HOGE'
これまではE_WARNINGを出したうえで、定数名と同じ文字列が割り当てられていましたが、この手抜きができなくなります。
Removed ability to specify an autoloader using an __autoload() function.
__autoload関数が削除されました。
function __autoload($class){}
// PHP8.0
Fatal error: __autoload() is no longer supported, use spl_autoload_register() instead
// PHP7.4
Deprecated: __autoload() is deprecated, use spl_autoload_register() instead
削除されたといっても完全に消えたわけではなく、定義することもできないという特別扱いです。
今後はspl_autoload_registerを使いましょう。
Composerのオートロードとか使った方がもっといいですが。
Removed the $errcontext argument for custom error handlers.
set_error_handlerの第1引数$error_handler
の第5引数$errcontext
が削除されました。
set_error_handler(function($errno, $errstr, $errfile, $errline, $errcontext){
echo $errcontext['fuga'];
});
function hoge(){
$fuga = 'piyo';
$y = '1a' + 1;
}
hoge();
// PHP8.0
Fatal error: Uncaught ArgumentCountError: Too few arguments to function {closure}(), 4 passed and exactly 5 expected
// PHP7.4
"piyo"
エラーが発生した個所のローカル変数が配列で入ってくるという謎機能です。
Removed create_function().
PHPの魔関数のひとつcreate_functionが削除されました。
$a = create_function('$a', 'echo $a;');
$a('hoge');
// PHP8.0
Fatal error: Uncaught Error: Call to undefined function create_function
// PHP7.4
"hoge" // Deprecated: Function create_function() is deprecated
かわりに無名関数を使いましょう。
無名関数はPHP5.3から使えるので、古のソースを熟成させながら使い続けてでもいないかぎり、いまどきcreate_functionはそうそう出てこないはずです。
Removed each()
eachが削除されました。
$arr = [1, 2, 3];
while ([$key, $val] = each($arr)) {
var_dump($key, $val);
}
// PHP8.0
Fatal error: Uncaught Error: Call to undefined function each()
// PHP7.4
0,1 1,2 2,3 // Deprecated: The each() function is deprecated
この関数を使う意味は全くないので、普通にforeachを使いましょう。
Removed ability to unbind $this from closures
クロージャ内で$this
のバインドを外すことができなくなりました。
とあるのだけどよくわかりません。
$closure = Closure::bind(null, new stdClass());
// PHP8.0
Fatal error: Uncaught TypeError: Closure::bind(): Argument #1 ($closure) must be of type Closure, null given
// PHP7.4
Warning: Closure::bind() expects parameter 1 to be Closure, null given
これは何の意味があるんだ?
Removed ability to use array_key_exists() with objects
オブジェクトに対してarray_key_existsを使えなくなりました。
array_key_exists(1, (object)[0, 1]);
// PHP8.0
Fatal error: Uncaught TypeError: array_key_exists(): Argument #2 ($array) must be of type array, stdClass given
// PHP7.4
Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated
property_existsを使えってずっと前から言われていたので、今さらこれに引っかかることはないでしょう。
Made the behavior of array_key_exists() regarding the type of the key parameter consistent with isset() and normal array access.
array_key_existsの引数のキー値の挙動が、issetなどと同じになりました。
array_key_exists([], [1]);
// PHP8.0
Fatal error: Uncaught TypeError: Illegal offset type
// PHP7.4
Warning: array_key_exists(): The first argument should be either a string or an integer
isset([], [1]); // こちらは昔からFatal error
これまでは引数のキー値に配列やオブジェクトなど不正な値を突っ込むことができましたが(当然falseなので意味はない)、今後はisset
などと同様のチェックが入ります。
negative_array_index
配列の自動採番キーがマイナスに対応します。
$a = [-10=>1];
$a[] = 2;
// PHP8.0
$a[-9]=>2になる
// PHP7.4
$a[0]=>2になる
これは正直、どうして賛成多数なのかわからない。
The default error_reporting level is now E_ALL.
ini設定error_reportingのデフォルトがE_ALLになります。
これまではE_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATEDでした。
この変更により、適当に書いてるコードは動かなくなります。
echo $a;
// PHP8.0
Warning: Undefined variable $a
// PHP7.4
何も出ない
PHP7.4で何も出ないのは単にデフォルトが非表示になっているだけなので、E_ALLに設定変更すればエラーが出ます。
もちろんerror_reporting
を変更すれば黙殺することもできますが、やめましょう。
display_startup_errors is now enabled by default.
ini設定display_startup_errorsの初期値がオンになりました。
Using "parent" inside a class that has no parent will now result in a fatal compile-time error.
親クラスの無いクラスでparent
を書くとコンパイルエラーになります。
class A{
public function __construct(){
parent::__construct();
}
}
// PHP8.0
Fatal error: Cannot use "parent" when current class scope has no parent
// PHP7.4
Deprecated: Cannot use "parent" when current class scope has no parent
PHP7.4では、呼ばれないかぎりは警告にとどまります。
もちろんnew A()
を実行したら、parentが存在しないため致命的エラーになります。
The @ operator will no longer silence fatal errors
エラー制御演算子@が致命的エラーには効かなくなりました。
@require("notfound.php");
// PHP8.0
Fatal error: Uncaught Error: Failed opening required 'notfound.php'
Process exited with code 255.
// PHP7.4
Process exited with code 255.
もっとも致命的エラーが起きたらスクリプトは強制終了されるので、結果は特に変わりません。
Following the hash comment operator # immediately with an opening bracket is not supported as a comment
#[
はコメントにならなくなりました。
#[ これはコメント
// PHP8.0
Parse error: Unclosed '['
// PHP7.4
エラーは起きない
アトリビュートの実装に伴う変更です。
[
以外の文字はこれまでどおりコメントです。
空白を入れた# [
もコメントになります。
LSP violations will now always generate a fatal error
LSP違反となる継承は常に致命的エラーを発生します。
class C1 {
public function method(array $a) {}
}
class C2 extends C1 {
public function method(int $a) {}
}
// PHP8.0
Fatal error: Declaration of C2::method(int $a) must be compatible with C1::method(array $a)
// PHP7.4
Warning: Declaration of C2::method(int $a) should be compatible with C1::method(array $a)
これまでは場合によってE_FATALだったりE_WARNINGだったりしていたので、これを揃えたものです。
The precedence of the concatenation operator has changed
連結演算子の優先度が変更されます。
$errors_count = 0;
echo 'unknown_upgrade_error_' . $errors_count + 1;
// PHP8.0
unknown_upgrade_error_1
// PHP7.4
1
これまで.
と+
の優先順位が同じで前から順だったため、直感的ではない結果になることがありました。
今後は.
の優先順位が下がります。
Arguments with a default value that resolves to null at runtime will no longer implicitly mark the argument type as nullable
引数のデフォルト値にnullが指定されている場合、引数の型は暗黙的にnull許容型になります。
function test(int $arg = null){}
test(null);
型引数はint
ですが、デフォルト値にnullが指定されているので暗黙的に?int
型となります。
このようにnullを直接渡した場合の挙動はPHP8でも変わりません。
しかし、デフォルト値を定数などで間接的に渡した場合は暗黙のnull許容型が許されなくなります。
const CONST_RESOLVING_TO_NULL = null;
function test(int $arg = CONST_RESOLVING_TO_NULL){}
test(null);
// PHP8.0
Fatal error: Uncaught TypeError: test(): Argument #1 ($arg) must be of type int, null given
// PHP7.4
エラーは出ない
一件ややこしいですが、まあnull許容型の意味を考えれば妥当な変更かなと。
A number of warnings have been converted into Error exceptions
多くのE_NOTICEがE_WARNINGに、多くのE_WARNINGが例外にと、警告レベルが厳しくなります。
$a = new stdClass();
$a->b;
// PHP8.0
Warning: Undefined property: stdClass::$b
// PHP7.4
Notice: Undefined property: stdClass::$b
$a = 1;
$a->b++;
// PHP8.0
Fatal error: Uncaught Error: Attempt to increment/decrement property "b"
// PHP7.4
Warning: Attempt to increment/decrement property 'b' of non-object
横着せずに正しいコードを書くようにしましょう。
Attempting to assign multiple bytes to a string offset will now emit a warning
マルチバイト文字列にオフセットアクセスするとE_WARNINGが出るようになります。
<?php
$str = 'あいうえお';
$str[2] = 'か';
// PHP8.0
Warning: Only the first byte will be assigned to the string offset
// PHP7.4
何も出ない
なんにしろ結果は文字化けするので、このようなコードを書いている時点でおそらくバグでしょう。
Unexpected characters in source files will now result in a ParseError
ヌルバイトなど、ソースコード中に想定外の文字コードが入っているとパースエラーになります。
これまではE_COMPILE_WARNINGでした。
Uncaught exceptions now go through "clean shutdown"
"destructors will be called after an uncaught exception"、すなわちキャッチされない例外が発生してもデストラクタが呼ばれるようになる、と読めるのですが、でも実際は前から呼ばれてるんですよね。
なんのことかよくわかりません。
class HOGE{
public function fuga(){
throw new \Exception();
}
public function __destruct(){
echo 'destruct called.';
}
}
(new HOGE())->fuga();
// PHP8も7.4も
destruct called.
Fatal error: Uncaught Exception
Compile time fatal error "Only variables can be passed by reference" has been delayed until runtime
参照渡し引数に値を渡した際の警告タイミングが変更になりました。
try{
array_pop([1,2,3]);
}catch(\Throwable $e){
echo $e->getMessage();
}
// PHP8.0
array_pop(): Argument #1 ($array) cannot be passed by reference
// PHP7.4
Fatal error: Only variables can be passed by reference
PHP7.4まではコンパイル時にエラーが出ていたので、プログラム側で制御することができませんでした。
PHP8では評価が実行時まで遅延されるので、結果としてcatchで受け取ることができるようになります。
まあソースコードを修正すべき内容なので、catchできても特に意味はなさそうですが。
Some "Only variables should be passed by reference" notices have been converted to "Argument cannot be passed by reference" exception.
一部の参照渡し引数に値を渡した時の挙動がE_NOTICEから例外になりました。
とあるのですが実例を見つけられませんでした。
array_pop([1,2,3]); // Fatal error
array_pop(array_values([1,2,3])); // Notice: Only variables should be passed by reference
PHP7のころから、値を直接渡した場合はFatal errorとなり、別の関数の返り値をそのまま渡すとE_NOTICEになります。
The generated name for anonymous classes has changed
匿名クラスの名前が変更になりました。
var_dump(new class extends stdClass{});
// PHP8.0
object(stdClass@anonymous)
// PHP7.4
object(class@anonymous)
名前に親クラスやインターフェイスの名前が付くようになり、わかりやすくなります。
しかし、これのせいで互換性が失われる実装って想像もつきませんな。
Non-absolute trait method references in trait alias adaptations are now required to be unambiguous
トレイトに同じ名前がある場合、曖昧さを消さなければならなくなりました。
trait T1{
public function foo(){}
}
trait T2{
public function foo(){}
}
class X{
use T1, T2{
foo AS bar;
}
public function foo(){}
}
// PHP8.0
Fatal error: An alias was defined for method foo(), which exists in both T1 and T2
// PHP7.4
何もエラー出ない
X::foo()
はどれを指すのかが曖昧ですが、PHP7.4では暗黙的にT1::foo()
とみなされていました。
PHP8.0では以下のように明示しなければなりません。
class X{
use T1, T2{
T1::foo AS bar;
}
}
The signature of abstract methods defined in traits is now checked against the implementing class method
traitに書いた抽象メソッドを実装したときにシグネチャを正しく解析するようになりました。
trait MyTrait {
abstract public function neededByTrait(): string;
}
class MyClass {
use MyTrait;
public function neededByTrait(): int { return 42; }
}
// PHP8.0
Fatal error: Declaration of MyClass::neededByTrait() must be compatible with MyTrait::neededByTrait()
// PHP7.4
何もエラー出ない
今まで異なるシグネチャで実装できていたのがバグなのではという気がしないでもない。
Disabled functions are now treated exactly like non-existent functions
無効化した関数が存在しない関数と同じ扱いになりました。
具体的には、php.ini
にdisable_functions ="exec"
と設定したときの結果が異なります。
exec('ls');
// PHP8.0
Fatal error: Uncaught Error: Call to undefined function exec()
// PHP7.4
PHP Warning: exec() has been disabled for security reasons
PHP7.4までのdisable_functions
は、『存在はしているけど無効化されている』という扱いでした。
PHP8においては単純に『存在しない』となるので、別の定義を行うことも可能です。
data: stream wrappers are no longer writable
dataストリームラッパーに書き込みできなくなりました。
The arithmetic and bitwise operators will now consistently throw a TypeError
各種演算子が、引数に配列、リソース、オブジェクトが渡された場合にTypeErrorを出すようになりました。
対象の演算子は+
・-
・*
・/
・**
・%
・<<
・>>
・&
・|
・^
・~
・++
・--
です。
new stdClass() + 1;
// PHP8.0
Fatal error: Uncaught TypeError: Unsupported operand types: stdClass + int
// PHP7.4
Notice: Object of class stdClass could not be converted to number
オブジェクトの場合、GMPのように演算子オーバーロードが設定されている一部のクラスはこれまでどおり計算可能です。
Float to string casting will now always behave locale-independently
浮動小数から文字列へのキャストがロケールに依存しなくなりました。
setlocale(LC_ALL, 'fr-FR');
echo (string)3.14;
// PHP8.0
3.14
// PHP7.4
3,14
フランス語は小数点が','なので、これまでは3,14
になっていました。
しかし(float)"3,14"
は解釈できず元に戻せなかったりと、わりと中途半端な機能だったので、ロケールに関わらず常に3.14
にするようになりました。
Removed support for deprecated curly braces for offset access
中括弧による文字列オフセットアクセスが削除されました。
echo '12345'{3};
// PHP8.0
Fatal error: Array and string offset access syntax with curly braces is no longer supported
// PHP7.4
4 Deprecated: Array and string offset access syntax with curly braces is deprecated
何のために存在したのかよくわからない機能です。
Applying the final modifier on a private method will now produce a warning unless that method is the constructor
コンストラクタ以外のprivateメソッドにfinalを書けなくなりました。
class FOO
{
final private function bar(){}
}
// PHP8.0
Warning: Private methods cannot be final as they are never overridden by other classes
// PHP7.4
何も出ない
privateメソッドはオーバーライドされることはないよ、というE_WARNINGが出ます。
警告なので動作自体はするのですが、今後動かなくなる可能性もありますし、使わない方がよいでしょう。
If an object constructor exit()s, the object destructor will no longer be called
コンストラクタでexit()
した場合、デストラクタが呼ばれなくなりました。
class FOO
{
public function __construct()
{
exit();
}
public function __destruct()
{
echo 'destruct called.';
}
}
new FOO();
// PHP8.0
何も出ない
// PHP7.4
destruct called.
元々コンストラクタでthrow
したときはデストラクタが呼ばれていなかったのですが、それと動作を合わせたということらしいです。
Non-strict comparisons between numbers and non-numeric strings now work by casting the number to string and comparing the strings
厳密でない比較演算子の数値比較の挙動が変更になりました。
詳しくはここに書いてあります。
var_dump('foo' == 0);
// PHP8.0
false
// PHP7.4
true
厳密な比較演算子の挙動は変更ありません。
===
を使っている限りは安泰です。
Namespaced names can no longer contain whitespace
名前空間に空白を入れることができなくなりました。
namespace A \ B{}
// PHP8.0
Parse error: syntax error, unexpected token "\"
// PHP7.4
エラー出ない
まあ、今までできていたのがおかしいといえばおかしいのですが。
Nested ternaries now require explicit parentheses
曖昧な三項演算子のネストに括弧が必要になりました。
1 ? 2 : 3 ?: 4;
// PHP8.0
Fatal error: Unparenthesized `a ? b : c ?: d` is not supported
// PHP7.4
Deprecated: Unparenthesized `a ? b : c ?: d` is deprecated
PHPの三項演算子は他の大半の言語と挙動が異なるという問題がありましたが、それを合わせるための布石です。
debug_backtrace() and Exception::getTrace() will no longer provide references to arguments
debug_backtraceおよびException::getTraceが引数の参照を渡さなくなりました。
function foo(&$bar)
{
debug_backtrace()[0]['args'][0] = 2;
}
$x = 1;
foo($x);
echo $x;
// PHP8.0
1
// PHP7.4
2
これまでスタックトレース経由で引数を書き替えるという邪悪な操作ができていたのですが、今後はできなくなります。
Numeric string handling has been altered to be more intuitive and less error-prone
function foo(int $int){}
foo('123abc');
// PHP8.0
Fatal error: Uncaught TypeError: foo(): Argument #1 ($int) must be of type int
// PHP7.4
Notice: A non well formed numeric value encountered
PHP7.4までは数値型文字列の定義が『数値型文字列』と『非正規の数値型文字列』の2種類あってわかりにくかったのですが、今後は単純に『数値型文字列』とそれ以外になります。
Magic Methods will now have their arguments and return types checked if they have them declared
マジックメソッドがシグネチャをチェックするようになりました。
class FOO{
public function __get(array $name):int{
return 1;
}
}
// PHP8.0
PHP Fatal error: FOO::__get(): Parameter #1 ($name) must be of type string when declared
// PHP7.4
エラー出ない
正しい定義に合わせるか、あるいは単にシグネチャを書かないようにすればよいです。
// PHP8.0でもOK
class FOO{
public function __get($name){
return 1;
}
}
call_user_func_array() array keys will now be interpreted as parameter names, instead of being silently ignored
call_user_func_arrayに連想配列を渡したときに、キーが無視されなくなりました。
function foo(...$args){
var_dump($args);
}
call_user_func_array('foo', ['a'=>1, 'b'=>2]);
// PHP8.0
['a'=>1, 'b'=>2]
// PHP7.4
[1, 2]
そもそもcall_user_func_arrayなんか使うなって話だな。
COM
Removed the ability to import case-insensitive constants from type libraries
COMのタイプライブラリ定数の大文字小文字を区別しない機能が削除されました。
com_load_typelibの第二引数は常にtrueとなり、com.autoregister_casesensitiveも常にonとなります。
ということらしいのだけど、そもそもタイプライブラリって何だ。
Curl
CURLOPT_POSTFIELDS no longer accepts objects as arrays
CURLOPT_POSTFIELDSはオブジェクトを受け取らなくなりました。
$c = curl_init();
curl_setopt($c, CURLOPT_POSTFIELDS, (object)['a'=>1]);
// PHP8.0
Fatal error: Uncaught Error: Object of class stdClass could not be converted to string
// PHP7.4
エラー出ない
そもそも最初から文字列か配列しか受け取らないという仕様で、オブジェクトを受け取れていたのはたまたまです。
今後は普通に配列を渡せば問題ありません。
Date
mktime() and gmmktime() now require at least one argument
mktimeとgmmktimeは、最低ひとつの引数が必要になりました。
mktime();
// PHP8.0
Fatal error: Uncaught ArgumentCountError: mktime() expects at least 1 argument, 0 given
// PHP7.4
Deprecated: mktime(): You should be using the time()
単に現在時刻がほしいときはtimeを使え、ということらしいです。
DOM
Remove unimplemented classes from ext/dom that had no behavior and contained test data
定義だけあって実装のなかった、あるいは実験的実装だったDOM関連クラスが削除されました。
new DOMTypeInfo();
// PHP8.0
Fatal error: Uncaught Error: Class "DOMTypeInfo" not found
// PHP7.4
エラー出ない
具体的にはDOMNameList / DomImplementationList / DOMConfiguration / DomError / DomErrorHandler / DOMImplementationSource / DOMLocator / DOMUserDataHandler / DOMTypeInfoが削除されました。
これらはDOMスタンダードからも削除されているため、それと合わせたものとなります。
マニュアルにも元々入ってなかったので影響も極小でしょう。
Enchant
enchant_broker_list_dicts(), enchant_broker_describe() and enchant_dict_suggest() will now return an empty array instead of null
enchant_broker_list_dicts等の関数が、対象がなにもないときにnull
ではなく[]
を返すようになりました。
enchant_broker_init() will now return an EnchantBroker object rather than a resource
enchant_broker_initは、これまでリソースを返していたのがEnchantBrokerオブジェクトを返すようになりました。
他のEnchant関数はこれまでと同じ書き方で透過的に動作します。
enchant_broker_request_dict() and enchant_broker_request_pwl_dict() will now return an EnchantDictionary object rather than a resource
enchant_broker_request_dictとenchant_broker_request_pwl_dictは、これまでリソースを返していたのがEnchantDictionaryオブジェクトを返すようになりました。
ていうかEnchantってPHP7.3で削除されるという話だったんだけどどうなったんだ?
Exif
Removed read_exif_data
read_exif_dataが削除されました。
今後はexif_read_dataを使いましょう。
Filter
The FILTER_FLAG_SCHEME_REQUIRED and FILTER_FLAG_HOST_REQUIRED flags for the FILTER_VALIDATE_URL filter have been removed
検証フィルタFILTER_VALIDATE_URLにおいて、FILTER_FLAG_SCHEME_REQUIRED
とFILTER_FLAG_HOST_REQUIRED
のフラグが削除されました。
実はプロトコルスキームとホストは元から常に必須だったため、実質的に意味のないフラグでした。
The INPUT_REQUEST and INPUT_SESSION source for filter_input() etc have been removed
filter_inputなどのフラグINPUT_REQUESTとINPUT_SESSIONが削除されました。
そもそも実装されていませんでした。
GD
The GD extension now uses a GdImage objects as the underlying data structure for images, rather than resources
GDリソースがGdImageオブジェクトになりました。
$image = imagecreatetruecolor(100, 100);
$text_color = imagecolorallocate($image, 233, 14, 91);
imagestring($image, 1, 5, 5, 'TEXT', $text_color);
imagepng($image);
echo gettype($image);
// PHP8.0
object
// PHP7.4
resource
この変更は透過的です。
上記コードの$image
はPHP7.4ではリソースであるのに対してPHP8.0ではオブジェクトになりますが、どちらでも同じように動作します。
ただしis_resourceなどでチェックを入れている場合は動かなくなります。
The deprecated function image2wbmp() has been removed
image2wbmp関数が削除されました。
PHP7.3以降E_DEPRECATEでした。
The deprecated functions png2wbmp() and jpeg2wbmp() have been removed
同じく非推奨だったpng2wbmpとjpeg2wbmpも削除されました。
The default $mode parameter of imagecropauto() no longer accepts -1.
imagecropautoの第二引数$mode
は-1
を受け付けなくなりました。
$image = imagecreatetruecolor(100, 100);
imagecropauto($image, -1, 0.5);
// PHP8.0
Fatal error: Uncaught ValueError: imagecropauto(): Argument #2 ($mode) must be a valid mode
// PHP7.4
Deprecated: imagecropauto(): Crop mode -1 is deprecated
IMG_CROP_DEFAULTなどの定数を使いましょう。
GMP
gmp_random() has been removed
gmp_randomが削除されました。
この関数はプラットフォームに依存して出力が変わるという問題があったため、PHP7.2でE_DEPRECATEDになりました。
かわりにgmp_random_bitsかgmp_random_rangeを使いましょう。
Iconv
iconv() implementations which do not properly set errno in case of errors are no longer supported
iconvは、エラー時にerrnoプロパティを適切にセットしない実装はサポートしなくなりました。
と書かれているのですが、errnoがなんなのか一切出てこないので何を見て判断すればよいのかわかりません。
IMAP
The unused default_host argument of imap_headerinfo() has been removed
imap_headerinfoの未使用だった第五引数$defaulthost
が削除されました。
The imap_header() function which is an alias of imap_headerinfo() has been removed
imap_headerが削除されました。
imap_headerinfoのエイリアスです。
Intl
The deprecated constant INTL_IDNA_VARIANT_2003 has been removed
定数INTL_IDNA_VARIANT_2003
が削除されました。
これはUnicodeから削除されたためです。
The deprecated Normalizer::NONE constant has been removed
Normalizer::NONEが削除されました。
何もしないという意味のない設定です。
The IntlDateFormatter::RELATIVE_FULL, RELATIVE_LONG, RELATIVE_MEDIUM, and RELATIVE_SHORT constants have been added.
IntlDateFormatterクラスに定数RELATIVE_FULL/RELATIVE_LONG/RELATIVE_MEDIUM/RELATIVE_SHORTが追加されました。
追加は互換性のない変更ではないような気がする。
LDAP
The deprecated function ldap_sort / ldap_control_paged_result / ldap_control_paged_result_response has been removed
関数ldap_sort、ldap_control_paged_result、ldap_control_paged_result_responseが削除されました。
かわりにldap_searchを使いましょう。
The interface of ldap_set_rebind_proc has changed
ldap_set_rebind_procの第二引数$callback
が空白""を受け付けなくなりました。
設定を外したい場合はかわりにnullを使います。
Mbstring
The mbstring.func_overload directive has been removed
マルチバイト関数の関数オーバーロード機能が削除されました。
substrを使うと自動的にmb_substrが呼ばれる、といった機能なのですが、事故の元でしかありません。
機能の削除に伴い、定数MB_OVERLOAD_MAIL、mb_get_infoのfunc_overload
といった関連項目も削除されます。
mb_parse_str() can no longer be used without specifying a result array
mb_parse_strの第二引数$array
が必須になりました。
mb_parse_str('a=b');
echo $a;
// PHP8.0
Fatal error: Uncaught ArgumentCountError: mb_parse_str() expects exactly 2 arguments, 1 given
// PHP7.4
b // Deprecated: mb_parse_str(): Calling mb_parse_str() without the result argument is deprecated
元々は文字列を直接変数に展開するという危険極まりない関数だったのですが、この変更により配列に展開するという妥当な内容になりました。
$array = mb_parse_str('a=b')
とできればもっと良かったのですけどね。
A number of deprecated mbregex aliases have been removed
いくつかのマルチバイト正規表現関数に存在したエイリアスが削除されました。
mbsplit("//u", 'foo');
// PHP8.0
Fatal error: Uncaught Error: Call to undefined function mbsplit
// PHP7.4
Deprecated: Function mbsplit() is deprecated
なぜかmb_eregやmb_regex_encodingなどには、mbereg
やmbregex_encoding
といった_
のないエイリアスが存在しました。
これらはマニュアルにも全く存在しない、謎のエイリアスです。
The 'e' modifier for mb_ereg_replace() has been removed
mb_ereg_replaceにおいてオプションe
が削除されました。
preg_replaceでは7.0で削除されたのに何故かこっちには残っていたのですが、ようやく揃った形です。
今後はmb_ereg_replace_callbackを使う必要があります。
A non-string pattern argument to mb_ereg_replace() will now be interpreted as a string instead of an ASCII codepoint
mb_ereg_replaceにおいて、第一引数$pattern
のASCIIコード変換を行わなくなります。
echo mb_ereg_replace(98, 'x', 'abc98');
// PHP8.0
"abcx"
// PHP7.4
"axc98" // Deprecated: mb_ereg_replace(): Non-string patterns will be interpreted as strings in the future
第一引数に数値を渡した場合、これまでは何故か対応するASCIIコードとして扱われていました。
意味もないうえにわかりにくすぎるので、今後は単純に文字列として扱われます。
The needle argument for mb_strpos(), mb_strrpos(), mb_stripos(), mb_strripos(), mb_strstr(), mb_stristr(), mb_strrchr() and mb_strrichr() can now be empty
mb_strposなどの各関数において、引数$needle
に空白が許可されます。
echo mb_strpos('abcde', '');
// PHP8.0
0
// PHP7.4
false // Warning: mb_strpos(): Empty delimiter
""はあらゆる文字列にマッチするため、だいたい1文字目になります。
The $is_hex parameter, which was not used internally, has been removed from mb_decode_numericentity()
mb_decode_numericentityにおいて、使われていなかった引数$is_hex
が削除されました。
The legacy behavior of passing the encoding as the third argument instead of an offset for the mb_strrpos() function has been removed
mb_strrposの、引数$encoding
は第四引数ですが、これを第三引数に書いても動く機能が削除されました。
mb_strrpos('b', 'abc', 'UTF-8');
// PHP8.0
Fatal error: Uncaught TypeError: mb_strrpos(): Argument #3 ($offset) must be of type int, string given
// PHP7.4
Deprecated: mb_strrpos(): Passing the encoding as third parameter is deprecated
引数の位置が変更されたのはPHP5.2です。
今まで残ってたことにびっくりですね。
The ISO_8859-* character encoding aliases have been replaced by ISO8859-* aliases
サポートされる文字エンコーディングのうち、ISO-8859-x
のエイリアスが変更されました。
mb_detect_order(['ISO-8859-1', 'ISO_8859-2']);
var_dump(mb_detect_order());
// PHP8.0
Fatal error: Uncaught ValueError: mb_detect_order(): Argument #1 ($encoding) contains invalid encoding
// PHP7.4
['ISO-8859-1', 'ISO-8859-2']
これまでISO_8859-x
という形のエイリアスが存在したのですが、PHP8.0では使えなくなりました。
かわりにISO8859-x
というエイリアスが使えるようになりますが、これはPHP7.4では対応していません。
iconvと形を揃えるためだそうですが、いきなり完全に差し替える必要に陥ります。
とはいえ、最初からエイリアスではなくISO-8859-x
の正しい形を使っていれば特に問題ありません。
mb_ereg() and mb_eregi() will now return boolean true on a successful match
mb_eregとmb_eregiが、マッチしたらtrueを返すようになりました。
echo mb_ereg('bbb', 'abbbc', $regs);
// PHP8.0
true
// PHP7.4
3
これまでは第三引数$regs
の有無によって返り値の値も型も変わるという非常に使いにくいものでした。
この変更によって、マッチしたらtrue、しなかったらfalseとわかりやすい形になります。
OCI8
The OCI-Lob class is now called OCILob, and the OCI-Collection class is now called OCICollection
OCI-LobクラスがOCILob
に、OCI-CollectionクラスがOCICollectionに変更されました。
Several alias functions have been marked as deprecated
幾つかの関数のエイリアスが非推奨になりました。
oci_internal_debug() and its alias ociinternaldebug() have been removed
oci_internal_debugが削除されました。
ODBC
odbc_connect() no longer reuses persistent connections
odbc_connectが持続的接続を利用しなくなりました。
よくわかりませんが、odbc_pconnectのほうに同じ dsn、user、 password の組み合わせ (odbc_connect() および odbc_pconnect() による)接続の場合は、 持続的な接続を再利用する
とか書いてあるので、おそらく一度odbc_pconnect
したあとにodbc_connect
したら持続的接続になってしまっていたのではないかと思われます。
The unused flags parameter of odbc_exec() has been removed
odbc_execの第三引数$flags
は未使用だったため削除されました。
OpenSSL
openssl_x509_read() and openssl_csr_sign() will now return an OpenSSLCertificate object rather than a resource
openssl_x509_readとopenssl_csr_signは、これまでリソースを返していたのをOpenSSLCertificateオブジェクトを返すようになりました。
The openssl_x509_free() function is deprecated
openssl_x509_freeはE_DEPRECATEDとなり、何もしなくなりました。
↑の変更で対象がリソースからオブジェクトになったので、わざわざ関数で開放しなくても自動的に解放されるからです。
openssl_csr_new() will now return an OpenSSLCertificateSigningRequest object rather than a resource
openssl_csr_newもリソースではなくOpenSSLCertificateSigningRequestオブジェクトを返すようになりました。
openssl_pkey_new() will now return an OpenSSLAsymmetricKey object rather than a resource
openssl_pkey_newもOpenSSLAsymmetricKeyオブジェクトを以下略
The openssl_pkey_free() function is deprecated
openssl_pkey_freeはE_DEPRECATEDとなり、何もしなくなりました。
openssl_seal() and openssl_open() now require $method to be passed
openssl_sealとopenssl_openの引数$method
が必須になりました。
デフォルト値が'RC4'
で、これはセキュアではないためです。
PCRE
When passing invalid escape sequences they are no longer interpreted as literals
無効なエスケープシーエンスが文字列リテラルと解釈されなくなりました。
preg_match('/\i/', 'h\ij', $matches);
var_dump($matches);
// PHP8.0
null // Warning: preg_match(): Compilation failed: unrecognized character
// PHP7.4
[0=>"i"]
正規表現パターンに存在しない文字列\i
は、これまでは単なる文字列と解釈されていましたが、今後は不正なパターンとみなされてエラーが出るようになります。
\i
という文字列で検索したい場合は、正しく\\\\i
と記述しましょう。
PDO
The default error handling mode has been changed from "silent" to "exceptions"
PDOのエラーモードPDO::ATTR_ERRMODE
のデフォルト値がPDO::ERRMODE_EXCEPTION
になりました。
これまではPDO::ERRMODE_SILENT
でした。
The signatures of some PDO methods have changed
幾つかのメソッドにおいてシグネチャが変更されました。
例としてPDOStatement::setFetchModeは、PDOStatement::setFetchMode(int $mode, ...$params)
になります。
PDO_ODBC
The php.ini directive pdo_odbc.db2_instance_name has been removed
pdo_odbc.db2_instance_nameディレクティブが削除されました。
これを設定すると環境変数DB2INSTANCEに値が入るだけというよくわからないディレクティブなので、まあ削除されても妥当でしょう。
pgsql
The deprecated pg_connect() syntax using multiple parameters instead of a connection string is no longer supported
pg_connectにおいて、DSNを使わない形の古い構文が削除されました。
pg_connect("host", "port", "options", "tty", "dbname");
// PHP8.0
Fatal error: Uncaught ArgumentCountError: pg_connect() expects at most 2 arguments, 5 given
// PHP7.4
エラー出ない
mysqliもPDOも既にDSN形式以外は対応していないので、こちらもいつまでも残しておく必要はないでしょう。
The deprecated pg_lo_import() and pg_lo_export() signature that passes the connection as the last argument is no longer supported
pg_lo_importおよびpg_lo_exportは、実は第三引数にリソースを渡しても動いていたらしいのですが、それが削除されました。
そんな構文ドキュメントにもユーザノートにも全く書かれていないのですが、PHP7.4のソースにはたしかにそれっぽいものが書いてあって、PHP8.0ではそれがなくなっていました。
これ使ってる人とかいるんだろうか。
pg_fetch_all() will now return an empty array instead of false for result sets with zero rows
pg_fetch_allは、取得行数が0だった場合はfalseを返していたのですが、[]
を返すようになりました。
失敗ではなく結果が無いということなので、こちらが妥当でしょう。
Phar
Metadata associated with a phar will no longer be automatically unserialized
これまではPharファイルを読み込もうとした時点で自動的にメタデータが展開されていたのですが、自動的には呼ばれなくなりました。
セキュリティ上の理由です。
Reflection
The method signatures have been changed
幾つかの関数のシグネチャが変更されました。
// PHP7.4
ReflectionClass::newInstance($args)
ReflectionFunction::invoke($args)
ReflectionMethod::invoke($object, $args)
// PHP8.0
ReflectionClass::newInstance(...$args)
ReflectionFunction::invoke(...$args)
ReflectionMethod::invoke($object, ...$args)
The ReflectionType::__toString() method will now return a complete debug representation of the type, and is no longer deprecated
ReflectionType::__toStringは非推奨でなくなりました。
function hoge(?int $a){}
echo (new ReflectionFunction('hoge'))->getParameters()[0]->getType();
// PHP8.0
?int
// PHP7.4
int
また、これまで正確に取ってこれなかったnullableなども取ってこれるようになっています。
Reflection export() methods have been removed
Reflection::exportは削除されました。
ReflectionFunction::export('strpos');
// PHP8.0
Fatal error: Uncaught Error: Call to undefined method ReflectionFunction::export()
// PHP7.4
Function [ <internal:standard> function strpos ]
ざっくり概要確認するには便利だったんですけどね。
The following methods can now return information about default values of parameters of internal functions
ReflectionParameter::isDefaultValueAvailable、getDefaultValue、isDefaultValueConstant、getDefaultValueConstantNameが内部関数にも使えるようになりました。
(new ReflectionFunction('strpos'))->getParameters()[2]->getDefaultValue();
// PHP8.0
0
// PHP7.4
Fatal error: Uncaught ReflectionException: Cannot determine default value for internal functions
内部関数に対して使う意義はあんまり感じられませんが。
ReflectionMethod::isConstructor() and ReflectionMethod::isDestructor() now also return true
ReflectionMethod::isConstructorおよびisDestructorは、インターフェイスにもtrueを返すようになりました。
これまではインターフェイスには非対応でした。
interface HOGE{
public function __construct();
}
(new ReflectionMethod('HOGE', '__construct'))->isConstructor();
// PHP8.0
true
// PHP7.4
false
ちなみにtraitには昔からtrueを返します。
ReflectionType::isBuiltin() method has been moved to ReflectionNamedType
ReflectionType::isBuiltinはReflectionNamedTypeクラスに移動しました。
なぜならReflectionUnionTypeにはビルトインの型はないからです。
Sockets
The deprecated AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES flags for socket_addrinfo_lookup() have been removed
socket_addrinfo_lookup関数の第三引数に渡せるフラグAI_IDN_ALLOW_UNASSIGNED/AI_IDN_USE_STD3_ASCII_RULESが削除されました。
glibcで削除されたので追随したということのようです。
socket_create(), socket_create_listen(), etc will now return a Socket object rather than a resource
以下の各関数が、リソースではなくオブジェクトを返すようになりました。
socket_create / socket_create_listen / socket_accept / socket_import_stream / socket_addrinfo_connect / socket_addrinfo_bind / socket_wsaprotocol_info_import
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($socket, IPPROTO_IP, IP_MULTICAST_LOOP, 0);
var_dump($socket);
// PHP8.0
object(Socket)#1 (0) {}
// PHP7.4
resource of type (Socket)
socket_set_optionのようなソケットを引数として受け取る関数は、そのまま透過的に動作します。
ただしis_resource等でチェックしている場合は修正が必要です。
socket_addrinfo_lookup() will now return an array of AddressInfo objects rather than resources
socket_addrinfo_lookupは、リソースの配列ではなく、AddressInfoの配列を返すようになりました。
SPL
SplFileObject::fgetss() has been removed
SplFileObject::fgetssは削除されました。
SplHeap::compare($a, $b) now specifies a method signature
SplHeap::compareに型mixedが設定されました。
extendsする場合は型を指定するか、もしくは何も書かないかが必要です。
SplDoublyLinkedList::push() now returns void instead of true
SplDoublyLinkedList::pushがvoidを返すようになりました。
var_dump((new SplDoublyLinkedList())->push(1));
// PHP8.0
null
// PHP7.4
true
これまではtrueを返していました。
元々マニュアルにもvoidと書かれていて、trueを返すのはバグだったみたいです。
SplDoublyLinkedList::unshift() now returns void instead of true
SplDoublyLinkedList::unshiftがvoidを以下同文。
SplQueue::enqueue() now returns void instead of true
SplQueue::enqueueが以下同文。
spl_autoload_register() will now always throw a TypeError on invalid arguments
spl_autoload_registerは、無効な引数について常にTypeErrorを発するようになりました。
spl_autoload_register('HOGE', false);
// PHP8.0
Fatal error: Uncaught TypeError: spl_autoload_register(): Argument #1 ($callback) must be a valid callback, function "HOGE" not found or invalid function name
// PHP7.4
何も出ない
これに伴い、第二引数$throw
は常に無視されるようになります。
SplFixedArray is now an IteratorAggregate and not an Iterator
SplFixedArrayがIteratorAggregateをimplementsしました。
var_dump(
is_subclass_of('SplFixedArray', 'Iterator'),
is_subclass_of('SplFixedArray', 'IteratorAggregate'),
);
// PHP8.0
false, true
// PHP7.4
true, false
これまではIteratorをimplementsしていました。
また、これに伴ってSplFixedArray::rewindなどIterator由来の実装は削除され、かわりにSplFixedArray::getIterator
が追加されます。
Standard
assert() will no longer evaluate string arguments
assertの引数を文字列表現で渡すことができなくなりました。
assert('$a');
// PHP8.0
true
// PHP7.4
Notice: Undefined variable: a
PHP7.4までは、引数が文字列のときはPHPコードとして解釈されていました。
つまりevalされていたってことです。
PHP8では'$a'
という単なる文字列として扱われます。
parse_str() can no longer be used without specifying a result array
parse_strの第二引数$result
が必須になりました。
上の方にあるmb_parse_strと全く同じ理由です。
fgetss() has been removed
fgetssは削除されました。
The string.strip_tags filter has been removed
文字列フィルタstring.strip_tagsが削除されました。
fgetssなどと同様、何かをするのと同時に文字列をフィルタするのは事故の元なのでやめましょうという方向です。
The needle argument of strpos(), strrpos(), stripos(), strripos(), strstr(), strchr(), strrchr(), and stristr() will now always be interpreted as a string
strposほかの関数で、引数$needle
に空文字列が有効になりました。
echo strpos('abc', '');
// PHP8.0
0
// PHP7.4
Warning: strpos(): Empty needle
空文字はどのような文字列にも該当するので、だいたいは1文字目すなわち0になります。
The length argument for substr(), substr_count(), substr_compare(), and iconv_substr() can now be null
substr、substr_count、substr_compare、iconv_substrの引数$length
にnullを渡した時の挙動が変わりました。
echo substr('abcde', 2, null);
// PHP8.0
"cde"
// PHP7.4
""
これまでは返り値が0やら""やらになっていたのですが、これが未指定の場合と同じ動きになります。
The length argument for array_splice() can now be null
array_spliceの引数$length
にnullを渡した時の挙動が変わりました。
$input = [1, 2, 3, 4];
array_splice($input, 2, null);
var_dump($input);
// PHP8.0
[1, 2]
// PHP7.4
[1, 2, 3, 4]
これまでは何もしませんでしたが、未指定の場合と同じ動きになります。
すなわち、引数$offset
より後ろが全て削除されます。
The args argument of vsprintf(), vfprintf(), and vprintf() must now be an array
vsprintf、vfprintf、vprintfの引数$arg
が配列しか受け付けなくなりました。
echo vsprintf('a%sc', 'b');
// PHP8.0
Fatal error: Uncaught TypeError: vsprintf(): Argument #2 ($values) must be of type array, string given
// PHP7.4
abc
元からマニュアルでは配列のみとなっていたのに、何故か文字列なども受け付けていたという謎のサービスでした。
The 'salt' option of password_hash() is no longer supported
password_hashのオプションsaltが削除されました。
指定する意味はないし固定すると脆弱になるだけなので、元々存在する必要のないオプションです。
The quotemeta() function will now return an empty string if an empty string was passed
quotemetaにから文字列""を渡すと空文字列""を返すようになりました。
これまではfalseでした。
hebrevc() / convert_cyr_string() / money_format() / ezmlm_hash() / restore_include_path() has been removed
以下の関数が削除されました。
hebrevc
convert_cyr_string
money_format
ezmlm_hash
restore_include_path
上位互換が存在する、他の関数と整合性がないなどの理由で、PHP7.4で非推奨となっています。
get_magic_quotes_gpc() and get_magic_quotes_runtime() has been removed
旧時代PHPの黒歴史のひとつ、get_magic_quotes_gpcとget_magic_quotes_runtimeが削除されました。
同時に定数FILTER_SANITIZE_MAGIC_QUOTESも削除されました。
PHPはついに、マジッククオートの軛から完全に解き放たれたのです。
Calling implode() with parameters in a reverse order ($pieces, $glue) is no longer supported
implodeは歴史的理由から引数を逆順でも受け付けていたのですが、これが削除されました。
echo implode(['a', 'b', 'c'], '|');
// PHP8.0
Fatal error: Uncaught TypeError: implode(): Argument #2 ($array) must be of type ?array, string given
// PHP7.4
a|b|c
PHP8.0は、負の遺産の清算が目立ちます。
parse_url() will now distinguish absent and empty queries and fragments
parse_urlの、空のクエリやフラグメントへの返り値が微妙に変わりました。
// 出力のscheme等は省略
var_dump(
parse_url('http://example.com/foo'),
parse_url('http://example.com/foo?'),
parse_url('http://example.com/foo#'),
parse_url('http://example.com/foo?#'),
);
// PHP8.0
[], ["query"=>""], ["fragment"=>""], ["query"=>"", "fragment"=>""]
// PHP7.4
[], [], [], []
空のクエリには空文字列を出力、クエリ自体がない場合は出力自体行わない、と区別できるようになります。
var_dump() and debug_zval_dump() will now print floating-point numbers using serialize_precision rather than precision
var_dumpとdebug_zval_dumpの浮動小数出力が、ini設定precisionではなくserialize_precisionを使うようになりました。
ini_set('precision', 1);ini_set('serialize_precision', 100);
var_dump(1.23456789012345678901234567890123456789012345678901234567890);
// PHP8.0
float(1.2345678901234566904321354741114191710948944091796875)
// PHP7.4
float(1)
100とか指定してもビット数の制限は越えられないみたい。
If the array returned by __sleep() contains non-existing properties, these are now silently ignored
マジックメソッド__sleepに存在しないプロパティを返した場合、無視するようになりました。
class FOO{
private $a = 'a';
public function __sleep()
{
return ['a', 'b'];
}
}
echo serialize(new FOO());
// PHP8.0
O:3:"FOO":1:{s:6:"FOOa";s:1:"a";} // Warning: serialize(): "b" returned as member variable from __sleep() but does not exist
// PHP7.4
O:3:"FOO":2:{s:6:"FOOa";s:1:"a";s:1:"b";N;} // Notice: serialize(): "b" returned as member variable from __sleep() but does not exist
これまでは、値がnullのプロパティがセットされていました。
The default locale on startup is now always "C"
デフォルトのロケールが常に"C"になりました。
これまではLC_ALLは"C"で、LC_CTYPEは環境変数LANGから取ってくる、みたいなことになっていました。
Removed deprecated DES fallback in crypt()
cryptのSALTフォールバックが削除されました。
echo crypt('str', 'あ');
// PHP8.0
*0
// PHP7.4
▒UYLTFzPe08. // Deprecated: crypt(): Supplied salt is not valid for DES
cryptはSALTの形式によって自動的にハッシュ形式を選択するのですが、これまでは未知のSALTが来た場合は自動的にDESにフォールバックしていました。
今後は失敗します。
ただ失敗といっても例外を出したりせず'*0'という文字列を返してくるのでむしろわかりにくいのでは。
Calling crypt() without an explicit salt is no longer supported
cryptの第二引数$salt
が必須になりました。
echo crypt('str');
// PHP8.0
Fatal error: Uncaught ArgumentCountError: crypt() expects exactly 2 arguments, 1 given
// PHP7.4
$1$SsnnMRiS$4clL.zBKekzZvryhRYVUP1 // Notice: crypt(): No salt parameter was specified
こちらは非対応SALTとは異なり、致命的エラーになります。
Sort comparison functions that return true or false will now throw a deprecation warning
ソート関数でtrue/falseを返している場合、非推奨の警告が出るようになりました。
0と等しいか、0より大きいか、0より小さい整数を返す必要があります。
$arr = [2, 1];
usort($arr, fn($a, $b) => $a > $b);
var_dump($arr);
// PHP8.0
[1, 2] // Deprecated: usort(): Returning bool from comparison function is deprecated
// PHP7.4
[1, 2]
Any functions accepting callbacks that are not explicitly specified to accept parameters by reference will now warn
リファレンスを受け取らないコールバック関数の引数にリファレンスを書いた場合、警告が出るようになりました。
array_filter([1,2], function (&$v) {
return true;
});
// PHP8.0
Warning: {closure}(): Argument #1 ($v) must be passed by reference, value given
// PHP7.4
何も出ない
多くの関数では既にこうなっていたものの、array_filterなど一部はそうなってなかったので追加したということのようです。
それに$v
を書き替えても元の値には影響しないので、&
を付ける意味は特にないです。
HTTP stream wrapper as used by functions now advertises HTTP/1.1 rather than HTTP/1.0
stream_context_createなどで作れるHTTPストリームラッパーのデフォルトがHTTP1.1になりました。
これまでどおりHTTP1.0を使いたい場合は、コンテキストオプションで指定する必要があります。
$opts = [
'http'=>[
'protocol_version'=>'1.0',
]
];
$context = stream_context_create($opts);
substr(), mb_substr(), iconv_substr() and grapheme_substr() now consistently clamp out-of-bounds offsets to the string boundary
substr、mb_substr、iconv_substr、grapheme_substrが、範囲外の引数にも文字列を返すようになりました。
var_dump(
substr('abc', 10)
);
// PHP8.0
""
// PHP7.4
false
これまではfalseになっていました。
Populating $http_response_header variable by the HTTP stream wrapper doesn't force rebuilding of symbol table anymore
HTTPストリームラッパーが$http_response_header
を変更してもシンボルテーブルの再構築が行われなくなりました。
ということらしいけど内部のことはよくわかりません。
きっと詳しい人がなんか教えてくれるはず。
Sysvmsg
msg_get_queue() will now return an SysvMessageQueue object rather than a resource
msg_get_queueがリソースではなくSysvMessageQueueインスタンスを返すようになりました。
Sysvsem
sem_get() will now return an SysvSemaphore object rather than a resource
sem_getがリソースではなくSysvSemaphoreインスタンスを返すようになりました。
The $auto_release parameter of sem_get() was changed to accept bool values rather than int
sem_getの第4引数$auto_release
の型がintからboolになりました。
Sysvshm
shm_attach() will now return an SysvSharedMemory object rather than a resource
shm_attachがリソースではなくSysvSharedMemoryインスタンスを返すようになりました。
tidy
The $use_include_path parameter has been removed from tidy_repair_string()
tidy_repair_stringの引数$use_include_path
が削除されました。
元々マニュアルにも載ってなかったんだけど、内部的に使っていたらしいです。
tidy::repairString() and tidy::repairFile() became static methods
tidy::repairStringとtidy::repairFileが静的メソッドになりました。
tidy::repairString('hoge');
// PHP8.0
エラー出ない
// PHP7.4
Fatal error: Uncaught Error: Non-static method tidy::repairString() cannot be called statically
Tokenizer
T_COMMENT tokens will no longer include a trailing newline
T_COMMENTトークンは末尾の改行を含まなくなりました。
$str = '<?php // comment
';
var_dump(
token_get_all($str)[1][1]
);
// PHP8.0
string(10) "// comment"
// PHP7.4
string(11) "// comment
"
Namespaced names are now represented
名前空間はひとまとまりとして解釈されるようになりました。
// 出力は必要部分のみ
$str = '<?php
namespace FOO\BAR;
';
var_dump(
token_get_all($str)
);
// PHP8.0
[ [T_NAME_RELATIVE, 'FOO\BAR'] ]
// PHP7.4
[ [T_STRING, 'FOO'], [T_NS_SEPARATOR, '\'], [T_STRING, 'BAR'] ]
こちらのほうが名前空間としてわかりやすいですね。
XML
xml_parser_create(_ns) will now return an XmlParser object rather than a resource
xml_parser_createがリソースではなくXmlParserオブジェクトを返すようになりました。
$parser = xml_parser_create();
xml_parse($parser, '<xml></xml>', true);
var_dump($parser);
// PHP8.0
object(XmlParser)#1
// PHP7.4
resource(4) of type (xml)
XMLパーサ関数は、これまでと同じ書き方で透過的に動作します。
またxml_parser_freeは実質的に何もしません。
XMLReader
XMLReader::open() and XMLReader::xml() are now static methods
XMLReader::openとXMLReader::XMLは静的メソッドになりました。
XMLWriter
The XMLWriter functions now accept and return, respectively, XMLWriter objects instead of resources
XMLWriter::openUriなどがリソースではなくXMLWriterオブジェクトを返すようになりました。
XMLWriter関数は、これまでと同じ書き方で透過的に動作します。
Zip
ZipArchive::OPSYS_Z_CPM has been removed
定数ZipArchive::OPSYS_Z_CPMが削除されました。
echo ZipArchive::OPSYS_Z_CPM;
// PHP8.0
Fatal error: Uncaught Error: Undefined constant ZipArchive::OPSYS_Z_CPM
// PHP7.4
9
これ、ZipArchive::OPSYS_CPM
の誤字です。
Zlib
gzgetss() has been removed
gzgetssが削除されました。
inflate_init() will now return an InflateContext object rather than a resource
inflate_initがリソースではなくInflateContextオブジェクトを返すようになりました。
inflate_addなどは、これまでと同じ書き方で透過的に動作します。
deflate_init() will now return a DeflateContext object rather than a resource
deflate_initがリソースではなくDeflateContextオブジェクトを返すようになりました。
deflate_addなどは、これまでと同じ書き方で透過的に動作します。
zlib.output_compression is no longer automatically disabled for Content-Type: image/*
ini設定zlib.output_compressionは、これまでは画像に対しては自動的に無効化されていましたが、その自動無効化がなくなりました。
New Features
新機能。
この多くはPHP8.0の新機能で紹介しています。
Core
Added support for union types
UNION型が追加されました。
function hoge(int|string $fuga): bool|stdClass {
if($fuga === 0){return true;}
return new stdClass;
}
関数hogeはint型もしくはstring型を受け取り、bool型もしくはstdClassインスタンスを返します。
Added WeakMap
弱いマップです。
メモリが足りなくなったら自動で削除されます。
Added ValueError class
ValueErrorクラスが追加されました。
echo bcadd('1', '2', -1);
// PHP8.0
Fatal error: Uncaught ValueError: bcadd(): Argument #3 ($scale) must be between 0 and 2147483647
// PHP7.4
3
bcaddの第三引数は小数点以下の桁数なので、マイナス値は不適切です。
このように、型は合っているけど値が範囲外のときに使われる例外となります。
Any number of function parameters may now be replaced by a variadic argument
継承時に、異なる型の値を可変長引数でまとめることができるようになりました。
class A{
public function hoge(int $foo, string $bar, stdClass $baz){}
}
class B extends A{
public function hoge(...$args){}
}
// PHP8.0
エラー出ない
// PHP7.4
Warning: Declaration of B::hoge(...$args) should be compatible with A::hoge
この場合、シグネチャは継承したクラスのものしか確認しません。
すなわち、(new B())->hoge(1, 2, 3)
とか書いてもエラーは出ません。
これはいいのか??????
"static" (as in "late static binding") can now be used as a return type
返り値にstaticを書けるようになります。
class Test {
public function create(): static {
return new static();
}
}
使い道がよくわからないので誰か解説よろ。
It is now possible to fetch the class name of an object using $object::class
インスタンスからクラス名を取得できるようになります。
echo (new stdClass)::class;
// PHP8.0
stdClass
// PHP7.4
Fatal error: Cannot use ::class with dynamic class name
New and instanceof can now be used with arbitrary expressions
Some consistency fixes to variable syntax have been applied
デリファレンス可能範囲が拡大されます。
class Foo{
const BAR = 'Bar';
}
class Bar{
public static $baz = 'QUX';
}
echo Foo::BAR::$baz;
// PHP8.0
QUX
// PHP7.4
Parse error: syntax error, unexpected '::'
これまでは構文エラーになっていたいくつかの構文が許されるようになります。
このRFCややこしくて正直理解が追い付いてません。
Added Stringable interface
Stringableインターフェイスが追加されました。
interface Stringable{
public function __toString(): string;
}
これがあると__toString()可能になるというものですが、これは暗黙的にimplementsされるため、使用する側としては特に気にする必要はありません。
Traits can now define abstract private methods
traitでabstract privateメソッドが作成可能になりました。
trait FOO {
abstract private function bar();
}
// PHP8.0
エラー出ない
// PHP7.4
Fatal error: Abstract function FOO::bar() cannot be declared private
throw
can now be used as an expression
throwが式になりました。
fn() => throw new Exception();
// PHP8.0
エラー出ない
// PHP7.4
Parse error: syntax error, unexpected 'throw'
構文の途中などで気軽に例外を投げられるようになります。
An optional trailing comma is now allowed in parameter lists
関数定義に末尾カンマが許可されました。
function foo($a, $b,){}
// PHP8.0
エラー出ない
// PHP7.4
Parse error: syntax error, unexpected ')'
関数を呼び出す方はPHP7.3から使えていたので、合わせた対応です。
It is now possible to write catch (Exception)
to catch an exception without storing
例外の変数を明示的に受け取らないことができるようになりました。
try{
new PDO();
}catch(\Throwable){
echo "なんかエラー出た";
}
// PHP8.0
なんかエラー出た
// PHP7.4
Parse error: syntax error, unexpected ')'
PDOのエラーメッセージを表示すると脆弱性になる可能性があるので出したくない場合など、例外から来た値を使わずに処理したいという意図を明示できます。
Added support for mixed type
mixed型がサポートされました。
function foo(mixed $arg){}
foo(1);
foo('x');
foo(new stdClass());
// PHP8.0
エラー出ない
// PHP7.4
Uncaught TypeError: Argument 1 passed to foo() must be an instance of mixed, int given
マニュアルでは見慣れた型名ですね。
var_dumpの引数など、あえて多様な型を受け取りたいときに使います。
Added support for Attributes
アトリビュートが追加されました。
#[ExampleAttribute]
function foo(){}
Javaでいうアノテーションです。
これまではPHPDocとかで適当に書いていましたが、これがPHPの構文としてパース可能な形で書けるようになります。
Added support for constructor property promotion
オブジェクト初期化子です。
素直にコンストラクタ引数昇格って言った方がわかりやすい気がしてきた。
class HOGE{
public function __construct(public int $x){}
}
echo (new HOGE(99))->x;
// PHP8.0
99
// PHP7.4
Parse error: syntax error, unexpected 'public'
コンストラクタ引数に可視性を書くと、自動的に同名のプロパティを作って値を突っ込んでくれます。
定型文をたくさん書く必要があって面倒だった初期化が楽になります。
コンストラクタ以外には使えません。
Added support for match
expression
match式が導入されました。
echo match("1"){
1 => '1だ',
true => 'trueだ',
"1" => '"1"だ',
default => 'どれでもない',
};
// PHP8.0
"1"だ
// PHP7.4
Parse error: syntax error, unexpected '=>'
厳密な比較、フォールスルーしない、返り値を持つ式である、とswitch文の問題の多くを解消した構文です。
Private methods declared on a parent class no longer enforce any inheritance rules
privateメソッドが子クラスに影響しないようになりました。
class A{
private final function foo(int $arg){}
}
class B extends A{
private function foo(string $agg){}
}
// PHP8.0
Warning: Private methods cannot be final
// PHP7.4
Fatal error: Cannot override final method A::foo()
privateメソッドにfinalって書くと継承時に何故かFatal Errorになっていたのですが、これがオーバーライドチェックされないようになります。
かわりにprivateは上書きされないからfinalしなくていいというE_WARNINGが出るようになりました。
Added support for nullsafe operator
ヌル安全オペレータが追加されました。
echo null?->foo();
// PHP8.0
NULL
// PHP7.4
Parse error: syntax error, unexpected '->'
ヌル安全オペレータ?->
は、nullに対してプロパティやメソッドを取り出そうとすると、そこで処理が止まります。
なおnullでなければ止まらないので、(new stdClass)?->foo()
とか書くとfoo()
が無いってエラーになります。
Added support for named arguments
名前付き引数がサポートされました。
echo htmlspecialchars(encoding:'UTF-8', string:'>');
// PHP8.0
>
// PHP7.4
Parse error: syntax error, unexpected ':'
引数の多い関数で最後の引数だけ呼んだり、引数の順番を入れ替えたりできます。
また呼び出し側に引数名を書くため、どの引数が何を表しているのか理解しやすくなります。
Date
Added DateTime::createFromInterface() and DateTimeImmutable::createFromInterface()
DateTime::createFromInterface、DateTimeImmutable::createFromInterfaceが追加されました。
echo (DateTime::createFromInterface(new DateTimeImmutable()))->format('Y-m-d');
// PHP8.0
2020-12-01
// PHP7.4
Fatal error: Uncaught Error: Call to undefined method DateTime::createFromInterface
名前からするとDateTime::createFromImmutableのように、DateTimeXXXからDateTimeを作るメソッドだと思われます。
現状ではDateTimeとDateTimeImmutableしかないうえにDateTimeInterfaceをユーザがimplementsすることはできないので意味はありませんが、将来種類が増えたときに役立ちそうです。
Added the DateTime format specifier "p"
DateTimeのフォーマットにp
が追加されました。
P
と同じですが、+00:00
のときだけZ
が返ります。よくわからない。
Dom
Introduce DOMParentNode and DOMChildNode
DOMParentNode、DOMChildNodeが追加されました。
普段SimpleXMLしか使わないからよくわからない。
Enchant
enchant_dict_add / enchant_dict_is_added
enchant_dict_add、enchant_dict_is_addedが追加されました。
Enchantを実用で使ってる人っているんだろうか。
FPM
Added a new option pm.status_listen
設定pm.status_listenが追加されました。
異なるエンドポイントのステータスを確認できるとかなんとか。
Hash
HashContext objects can now be serialized
HashContextがシリアライズ可能になりました。
echo serialize(hash_init('md5'));
// PHP8.0
O:11:"HashContext":5…
// PHP7.4
Fatal error: Uncaught Exception: Serialization of 'HashContext' is not allowed
リクエストを超えてハッシュ作成を継続したいとかあるのか?
Opcache
If the opcache.record_warnings ini setting is enabled, opcache will record compile-time warnings
ini設定opcache.record_warningsを有効にした場合、コンパイル時に発生した警告をして次のアクセス時にも発生させます。
OpenSSL
Added Cryptographic Message Syntax (CMS)
Cryptographic Message Syntaxがサポートされました。
Standard
printf() and friends now support the %h and %H format specifiers
printfおよび類似関数が、指定子%h
・%H
をサポートしました。
%g
・%G
と同じですが、ロケールに関わらず小数点が.
になります。
setlocale(LC_ALL, 'fr');
echo sprintf('%g - %h', 1.2, 3.4);
// PHP8.0
1,2 -
// PHP7.4
1,2 - 3.4
上の方にもあったフランス語問題の対応です。
printf() and friends now support using "*" as width or precision
printfおよび類似関数が、量指定子*
をサポートしました。
printf("%.*f", 10, 1.2);
// PHP8.0
1.2000000000
// PHP7.4
f
精度を外側から渡すことができます。
これまでも文字列結合などで実現は可能でしたが、簡単に書けるようになります。
proc_open() now supports pseudo-terminal (PTY) descriptors
proc_openが疑似ターミナルをサポートしました。
$proc = proc_open('dir', [['pty'], ['pty'], ['pty']], $pipes);
// PHP8.0
Warning: proc_open(): PTY (pseudoterminal) not supported on this system
// PHP7.4
Warning: proc_open(): pty pseudo terminal not supported on this system
なんにしろWindowsではサポートされてなかった。
proc_open() now supports socket pair descriptors
proc_openがソケットをサポートしました。
$proc = proc_open('dir', [['socket'], ['socket'], ['socket']], $pipes);
// PHP8.0
エラー出ない
// PHP7.4
Warning: proc_open(): socket is not a valid descriptor spec/mode
こちらはWindowsでも使えます。
Sorting functions are now stable
ソート関数が安定ソートになりました。
$array = [
'a' => 1,
'b' => 1,
];
asort($array);
これまではソート後にaとbの位置がどうなっているか保証がなかったのですが、今後はaとbの順番が保たれます。
array_diff(), array_intersect() and their variations can now be used with a single array as argument
array_diffなどを引数ひとつで使えるようになりました。
array_diff([1, 2]);
// PHP8.0
エラー出ない
// PHP7.4
Warning: array_diff(): at least 2 parameters are required, 1 given
単独だと意味はないですが、array_intersect(...$arrays)
のように展開して渡したいときに役立ちます。
The $flag parameter of ob_implicit_flush() was changed to accept bool values
ob_implicit_flushの引数$flag
がbool型になりました。
Zip
Extension updated to version 1.19.1
zipエクステンションのバージョンが1.19.1になりました。
と言われてもこれがlibzipのことかすらよくわからないのですが。
New ZipArchive::lastId property
ZipArchiveにlastIdプロパティが追加されました。
最後に追加したファイルのインデックスです。
Error can be checked after an archive is closed
ZipArchiveを閉じた後でも、ZipArchive::statusなどでステータスを確認可能になりました。
The remove_path option of ZipArchive::addGlob() and ::addPattern() is now treated as arbitrary string prefix
ZipArchive::addGlobおよびZipArchive::addPatternのオプションremove_path
は、アーカイブを追加する際に削除される接頭辞になりました。
以前はディレクトリ名でしたが、add_path
と整合が取れていなかったので変更されました。
Optional compression / encryption features are listed in phpinfo
圧縮/暗号化オプションがphpinfoに表示されるようになりました。
Changes in SAPI modules
SAPIモジュールへの変更
Apache
The PHP module has been renamed
Apache PHPモジュールの名前がphp7_module
からphp_module
に変更されました。
今後メジャーバージョンアップのたびにLoadModule php8_module
とか書き替えずに済むようになります。
Deprecated Functionality
非推奨になる機能。
ここで『できなくなった』と書いてあるのは非推奨と読み替えてください。
Core
Declaring a required parameter after an optional one is deprecated
省略可能引数の後で必須引数を記述することができなくなりました。
function hoge($foo = 'foo', $bar){}
// PHP8.0
Deprecated: Required parameter $bar follows optional parameter $foo
// PHP7.4
エラー出ない
今まで許可されていたことにびっくりですね。
Calling get_defined_functions() with $exclude_disabled explicitly set to false is deprecated
get_defined_functionsの引数$exclude_disabled
にfalse指定ができなくなりました。
互換性のない変更点において、無効化された関数は存在しないものにされました。
そのため、このフラグには意味がなくなりました。
Enchant
enchant_broker_set_dict_path and enchant_broker_get_dict_path not available
libenchant-2では、enchant_broker_set_dict_pathとenchant_broker_get_dict_pathが使えなくなりました。
enchant_dict_add_to_personal, use enchant_dict_add instead
enchant_dict_add_to_personalが非推奨になりました。
かわりにenchant_dict_addを使います。
enchant_dict_is_in_session, use enchant_dict_is_added instead
enchant_dict_is_in_sessionが非推奨になりました。
かわりにenchant_dict_is_addedを使います。
enchant_broker_free and enchant_broker_free_dict, unset the object instead
enchant_broker_freeとenchant_broker_free_dictが非推奨になりました。
かわりにunsetを使います。
ENCHANT_MYSPELL and ENCHANT_ISPELL constants
定数が非推奨になりました。
LibXML
libxml_disable_entity_loader() has been deprecated
libxml_disable_entity_loaderが非推奨になりました。
XXE脆弱性対応のためです。
PGSQL / PDO PGSQL
The constant PG_VERSION_STR has now the same value as PG_VERSION, and thus is deprecated
定数PG_VERSION_STRは中身がPG_VERSIONと同じになり、さらに非推奨になりました。
PG_VERSION_STRもPG_VERSIONもPostgresの項目にないんだけど何処で定義されてるんだろう。
Function aliases in the pgsql extension have been deprecated
Postgres関数の古い呼び名のエイリアスが非推奨になりました。
たとえばpg_lo_openにはpg_loopenというエイリアスが存在し、PHP7.4までは警告なく使用可能でした。
Zip
Using empty file as ZipArchive is deprecated
空のファイルをZipArchiveとして扱うことができなくなりました。
libzip 1.6.0で非対応になったためです。
The procedural API of Zip is deprecated
手続き型のzip関数は非推奨になりました。
zip_open('tmp');
// PHP8.0
Deprecated: Function zip_open() is deprecated
// PHP7.4
エラー出ない
ZipArchiveを使いましょう。
Reflection
ReflectionFunction::isDisabled() is deprecated
ReflectionFunction::isDisabledが非推奨になりました。
無効化された関数は存在しないものにされたためです。
ReflectionParameter::getClass(), ReflectionParameter::isArray(), and ReflectionParameter::isCallable() are deprecated
ReflectionParameter::getClass、ReflectionParameter::isArray、ReflectionParameter::isCallableが非推奨になりました。
かわりにReflectionParameter::getTypeとReflectionTypeを使いましょう。
Changed Functions
仕様が変更になる関数。
Reflection
ReflectionClass::getConstants and ReflectionClass::getReflectionConstants results can be now filtered
https://www.php.net/manual/ja/reflectionclass.getconstantsとReflectionClass::getReflectionConstantsに引数$filter
が追加されました。
またフィルタ用の定数ReflectionClassConstant::[IS_PUBLIC|IS_PROTECTED|IS_PRIVATE]
が追加されました。
class FOO{
public const A = 'A';
protected const B = 'B';
private const C = 'C';
}
$c = (new ReflectionClass('FOO'))->getReflectionConstants(filter:ReflectionClassConstant::IS_PRIVATE);
// privateの定数Cだけ出てくる
引数未指定のときはこれまでどおり全て出てきます。
Zip
ZipArchive::addGlob and ZipArchive::addPattern methods accept more values in the "options"
ZipArchive::addGlobとZipArchive::addPatternの引数$options
に対象が追加されました。
- flags
- comp_method
- comp_flags
- env_method
- enc_password
ZipArchive::addEmptyDir, ZipArchive::addFile and aZipArchive::addFromString methods have a new "flags" argument
ZipArchive::addEmptyDir、ZipArchive::addFile、ZipArchive::addFromStringに引数$flags
が追加されました。
ZipArchive::extractTo now restore file modification time
ZipArchive::extractToがmtimeを復元するようになりました。
これまでは解凍した時刻になっていました。
New Functions
新しい関数。
Core
Added get_resource_id($resource) function
関数get_resource_idが追加されました。
echo get_resource_id(tmpfile()); // 4 環境によって変わる
リソースのリソースIDを取得できます。
(int)$resource
と同じですが、関数的に記述することができます。
ldap_count_references
関数ldap_count_referencesが追加されました。
よくわかりませんが、おそらくWindowsAPIなどと同じものでしょう。
他のLDAP関数もほぼ共通ですし。
OpenSSL
Added openssl_cms_encrypt() / openssl_cms_decrypt() / openssl_cms_read() / openssl_cms_sign() / openssl_cms_verify()
CMS関連の関数が追加されました。
Cryptographic Message Syntaxサポートに伴い導入されたものです。
openssl_cms_encrypt('input.txt', 'output.txt', file_get_contents('key.pem'), []);
使い方はopenssl_pkcs7_XXXXXと相似です。
PCRE
Added preg_last_error_msg
preg_last_error_msgが追加されました。
preg_match('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
echo preg_last_error_msg(); // Backtrack limit exhausted
正規表現で最後に発生したエラーメッセージを返します。
意味的にはpreg_last_errorと同じですが、こちらはintでわかりにくいため、メッセージとして出力するようにしたものです。
SQLite3
Add SQLite3::setAuthorizer() and respective class constants
SQLite3::setAuthorizerが追加されました。
SQLを実行するたびに呼ばれるコールバックを設定することができます。
Standard
str_contains / str_starts_with / str_ends_with
str_contains、str_starts_with、str_ends_withが追加されました。
str_contains('森久保乃々', '森久保'); // true
str_starts_with('望月聖', '望月'); // true
str_ends_with('イヴ・サンタクロース', 'サンタクロース'); // true
それぞれ○○が含まれる、○○で始まる/終わる、の文字列検索を楽にする関数です。
Added fdiv() function
fdivが追加されました。
echo fdiv(1, 0); // INF
IEEE 754に準拠した割り算です。
Added get_debug_type() function
get_debug_typeが追加されました。
echo get_debug_type(1), get_debug_type(new DateTime()); // int, DateTime
プリミティブ型の型名を返すgettypeと、オブジェクトのクラス名を返すget_classの悪魔合体です。
Zip
ZipArchive::setMtimeName and ZipArchive::setMtimeIndex
ZipArchive::setMtimeNameとZipArchive::setMtimeIndexが追加されました。
mtimeを操作できます。
ZipArchive::setProgressCallback / ZipArchive::setCancelCallback
ZipArchive::setProgressCallbackとZipArchive::setCancelCallbackが追加されました。
ってUPGRADINGには書いてあるんだけど、試してみるとCall to undefinedって言われるしregisterProgressCallbackとregisterCancelCallbackが存在するのでおそらく間違い。
ZipArchive::replaceFile
ZipArchive::replaceFileが追加されました。
中身のファイルの一部を置き換えるみたいだけど、そんなややこしいことをPHPで行うことはあるのだろうか。
ZipArchive::isCompressionMethodSupported / ZipArchive::isEncryptionMethodSupported
ZipArchive::isCompressionMethodSupportedとZipArchive::isEncryptionMethodSupportedが追加されました。
名前のとおり、圧縮方式および暗号化方式をサポートしているか確認できます。
New Classes and Interfaces
新しいクラス、インターフェイス。
Tokenizer
PhpToken
PhpTokenクラスが追加されました。
echo PhpToken::tokenize('<?php echo; ?>')[0]->text; // <?php
既存のTokenizerをオブジェクト的に扱えるようにしたものです。
Removed Extensions and SAPIs
削除されたエクステンション、SAPIなど。
XML-RPC
The xmlrpc extension has been unbundled and moved to PECL
XML-RPCがPHPコアから削除され、PECL行きになりました。
内部で使っているxmlrpc-epiが開発放棄されているためです。
Other Changes to Extensions
そのほかの変更点。
CURL
The CURL extension now requires at least libcurl 7.29.0
Curlエクステンションがlibcurlの7.29.0以上を必要とするようになりました。
curl_init() will now return a CurlHandle object rather than a resource
curl_initはリソースではなくCurlHandleオブジェクトを返すようになりました。
var_dump(
curl_init()
);
// PHP8.0
object(CurlHandle)#1
// PHP7.4
resource(4) of type (curl)
他のCurl関数はこれまでと同じ書き方で透過的に動作します。
curl_closeは実質的に何もしなくなりました。
curl_multi_init() will now return a CurlMultiHandle object rather than a resource
curl_multi_initはリソースではなくCurlMultiHandleオブジェクトを返すようになりました。
それ以外はcurl_initとほぼ同じです。
curl_share_init() will now return a CurlShareHandle object rather than a resource
curl_share_initはリソースではなくCurlShareHandleオブジェクトを返すようになりました。
それ以外はcurl_initとほぼ同じです。
The deprecated parameter $version
of curl_version() has been removed
非推奨だったcurl_versionの第一引数$version
が削除されました。
マニュアルからは既に抹消されています。
Date
DatePeriod now implements IteratorAggregate
DatePeriodがIteratorAggregateをimplementsするようになりました。
(new ReflectionClass('DatePeriod'))->getInterfaceNames(); // [IteratorAggregate, Traversable]
以前はTraversableでした。
DOM
DOMNamedNodeMap / DOMNodeList now implements IteratorAggregate
DOMNamedNodeMapおよびDOMNodeListがIteratorAggregateをimplementsするようになりました。
これらも以前はTraversableでした。
Intl
IntlBreakIterator / ResourceBundle now implements IteratorAggregate
IntlBreakIteratorおよびResourceBundleがIteratorAggregateをimplementsするようになりました。
以前はTraversableでした。
Enchant
The enchant extension now uses libenchant-2 by default when available
Enchantエクステンションが使用しているlibenchantのバージョンがlibenchant-2になりました。
1系は非推奨となり、将来的に削除されます。
GD
The $num_points parameter of imagepolygon(), imageopenpolygon() and imagefilledpolygon() is now optional
imagepolygon、imageopenpolygon、imagefilledpolygonの引数$num_points
が省略可能になりました。
省略した場合、$points / 2
とみなされます。
imagepolygon( $im=imagecreatetruecolor(100, 100), [1,2,3,4,5,6], imagecolorallocate($im, 255,255,255))
第四引数$color
は省略不可のため、省略する場合は第三引数に$color
を入れる、すなわち引数の数によって第三引数の意味が変わるという非常にわかりにくいことになります。
負債を増やしてどうする。
imagepolygon( $im=imagecreatetruecolor(100, 100), [1,2,3,4,5,6], null, imagecolorallocate($im, 255,255,255));
// Fatal error: Uncaught ValueError: imagepolygon(): Argument #3 ($num_points_or_color) must be greater than or equal to 3
imagepolygon( $im=imagecreatetruecolor(100, 100), points:[1,2,3,4,5,6], color:imagecolorallocate($im, 255,255,255))
// Fatal error: Uncaught ArgumentCountError: imagepolygon(): Argument #3 ($num_points_or_color) not passed
nullにしたり名前付き引数で飛ばしたりといったこともできません。
これはもっとどうにかしたほうがよかったのでは。
The function imagegetinterpolation() to get the current interpolation method has been added
imagegetinterpolationが追加されました。
$im=imagecreatetruecolor(100, 100);
imagesetinterpolation($im, IMG_GENERALIZED_CUBIC);
echo imagegetinterpolation($im); // 11
現在設定されている補間方法を取得します。
JSON
The JSON extension cannot be disabled anymore
JSONエクステンションを無効にすることができなくなりました。
マニュアルには全く載っていないのですが、実はこれまでコンパイルオプション--disable-json
で無効化することが可能でした。
MBString
The Unicode data tables have been updated to version 13.0.0
Unicodeデータベースが13.0.0にバージョンアップされました。
PDO
PDOStatement now implements IteratorAggregate
PDOStatementがIteratorAggregateをimplementsするようになりました。
以前はTraversableでした。
LibXML
The minimum required libxml version is now 2.9.0
要求するlibxmlがバージョン2.9.0以上になりました。
以前は2.6.0以上でした。
MySQLi / PDO MySQL
When mysqlnd is not used the minimum supported libmysqlclient version is now 5.5
要求するlibmysqlclientのバージョンが5.5以上になりました。
libmysqlclientではなくmysqlndを使う場合は不要です。
ところでマニュアルには『mysqlndを勧める』って書いてあるんだけど、変更履歴では『libmysqlclientが推奨だしデフォルトもこっち』って書いてあるんですよね。
どっちが正解なんだ。
mysqli_result now implements IteratorAggregate
mysqli_resultがIteratorAggregateをimplementsするようになりました。
以前はTraversableでした。
PGSQL / PDO PGSQL
The PGSQL and PDO PGSQL extensions now require at least libpq 9.1
要求するlibpqのバージョンが9.1以上になりました。
Readline
Calling readline_completion_function() before the interactive prompt starts will now override the default interactive prompt completion function
readline_completion_functionは、対話型シェルが起動していないときにも動くようになりました。
以前は、既に対話型シェルが起動していないと動きませんでした。
SimpleXML
SimpleXMLElement now implements RecursiveIterator and absorbed the functionality of SimpleXMLIterator
SimpleXMLElementがRecursiveIteratorをimplementsするようになりました。
以前はTraversableでした。
さらにSimpleXMLIteratorの機能を吸収しました。
SimpleXMLIteratorは実質的にSimpleXMLElementと同じになりました。
Shmop
shmop_open() will now return a Shmop object rather than a resource
shmop_openはリソースではなくShmopオブジェクトを返すようになりました。
他の共有メモリ関数はこれまでと同じ書き方で透過的に動作します。
shmop_closeは実質的に何もしなくなります。
New Global Constants
新たなグローバル定数。
Filter
FILTER_VALIDATE_BOOL has been added as an alias for FILTER_VALIDATE_BOOLEAN
検証フィルタFILTER_VALIDATE_BOOLが追加されました。
var_dump(FILTER_VALIDATE_BOOL, FILTER_VALIDATE_BOOLEAN); // 258, 258
これはFILTER_VALIDATE_BOOLEANのエイリアスです。
真偽型の表記はbool
に揃えられつつあるので、他のboolean
もいずれbool
に変更されるでしょう。
Changes to INI File Handling
iniファイルの変更。
zend.exception_string_param_max_len
ini設定zend.exception_string_param_max_len
が追加されました。
スタックトレースに表示される引数の文字数を制御します。
try {
substr('12345678901234567890');
} catch(Throwable $e) {
echo $e->getTraceAsString();
}
// zend.exception_string_param_max_len=15のとき
#0 C:\xampp\htdocs\test.php(10): substr('123456789012345...')
// zend.exception_string_param_max_len=1のとき
#0 C:\xampp\htdocs\test.php(6): substr('1...')
開発時のデバッグなどに重宝するでしょう。
デフォルトは15で、範囲は0から1000000です。
ini_setで変更できたのでPHP_INI_ALLのようです。
com.dotnet_version
dotnetを使う際の.netフレームワークのバージョンを指定できるようです。
Windows Support
Standard
Program execution functions using the shell now consistently execute %comspec% /s /c "$commandline"
,
execなどのシェルコマンド実行関数が、一貫して%comspec% /s /c "$commandline"
という形で実行されるようになりました。
ということらしいですがよくわかりません。
GD
php_gd2.dll has been renamed to php_gd.dll
GDエクステンションのファイル名がphp_gd2.dll
からphp_gd.dll
に変更されました。
php-test-pack
The test runner has been renamed from run-test.php to run-tests.php
テストパッケージのテストランナーファイル名がrun-test.php
からrun-tests.php
に変更されました。
Other Changes
その他の変更点
EBCDIC targets are no longer supported
文字コードEBCDICがサポート対象外になりました。
果たして使っていた人はいるのだろうか?
Performance Improvements
パフォーマンスについて。
A Just-In-Time (JIT) compiler has been added to the opcache extension
JITがサポートされました。
function getFibonacci(int $i){
return $i < 2 ? $i : getFibonacci($i-1) + getFibonacci($i-2);
}
$a = microtime(true);
echo getFibonacci(38);
$b = microtime(true);
echo $b - $a;
| PHP8デフォルト | opcache有効 | JIT有効 |
|---|---|---|---|
| 6.931639 | 5.833915 | 1.698887 |
| 7.443145 | 5.536612 | 2.009317 |
| 6.610769 | 5.619338 | 1.662739 |
| 6.794568 | 5.654112 | 1.739347 |
| 7.286194 | 5.774223 | 1.788053 |
CPUバウンドな処理はとんでもない速さになります。
ただPHPの主な用途はディスクやデータベースへのIOで、それらにはJITの恩恵はほぼないので、実際のWebアプリケーションはここまで極端に速くはなりません。
公式LPではざっくり1割から3割減というところですね。
感想
変更点多すぎ!!!!
PHP8たいしたことないんじゃねえのとか言ってた奴土下座な。
互換性のない変更の多くは、古くからのアバウトな仕様を排除し、厳密な書き方を推奨する方向に向けるものです。
implodeの引数が逆順でも書けるなんてのはその最たるものですね。
そのぶん昔からの熟成されたソースを使っているところは移行が大変になると思いますが、PHPは互換を切ってでも進化し続ける方向を選んだということなので、まあがんばってもらいましょう。
それにPHP7以降の近代風な書き方をしている限りでは、変更が必要なところはほとんどありません。
そして新機能については、流行りの書式やら文法などを貪欲に取り入れていて、このあたりはさすがPHPってところです。
節操がないとも言えますが、その節操のなさこそがPHPたる所以と言えましょう。
アロー関数や型宣言、アトリビュートあたりはまだ機能が半端なので、次のメジャーバージョンかあるいはマイナーバージョンでさらに進化しそうですね。
さらにJITが入ったことで、Webアプリケーションだけに囚われない、実用的な計算ライブラリでもPHPが輝く時代がやってくるかもしれません。
まあC++やGoあたりとはさすがに比べものにはならないですが、他のスクリプト言語に比べればだいぶいい線行っているのではないでしょうか。