1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

自己責任でPHP7のcount()関数を改造してエラー抑制する

Last updated at Posted at 2020-03-14

Parameter must be an array or an object that implements Countable

古いPHPのプログラムをPHP7.2以降で動かして、上記エラーの山に呆然となった人も多いことでしょう。
私もそうです。

プログラムをgrepしてみたら、数100か所でcount()関数が使われていました。
それらに全部countableな値が渡されているのかチェックするのは苦痛でしたし、書き換えの事を考えると吐きそうです。

新しい関数を作ったとしても、count()関数を使っている箇所全てを書き直さないといけません。

一括置換をかけたいのですが、困ったことに
select count(*) from…
とか恐ろしい記述があったりします。

php.ini等で、warning抑制という荒業もありますが、
私はその環境で関発出来る自信がありません。

try~catchで捕捉しようかとも思いましたが、
既存のファイル構造上めんどくさそうでした。

てか、なんで互換モードとかないんだろう…。

ネットで検索しても、「これだ!!」という解決策は見つかりませんでした。

というわけで・・・

自己責任でPHP本体を改造します!!

これは

  • PHPのバージョンは、7.4.3
  • 同じサーバで他のWEBサイトが動いてないこと
  • PHPがソースコードからのコンパイルでインストールされていること
  • トラブルが起きても他人のせいにしないこと

が、前提条件となっています。

条件を満たせない場合は、
素直に「is_countable」で検索してください。

エラーを出さないこともできるのですが、今回は
E_WARNINGE_NOTICE に変える改造をします。
別にE_DEPRECATEDでもいいと思います。
php.ini等でエラー出力を制御できればいいです。

対象ファイルは、

  • Zend/zend_vm_def.h(書き換え1か所)
  • Zend/zend_vm_execute.h(書き換え3か所)
  • ext/standard/array.c(書き換え3か所)

の3ファイルです。

Zend/zend_vm_def.h, Zend/zend_vm_execute.h の書き換え箇所は、

zend_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count");

これを、

zend_error(E_NOTICE, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count");

に書き換えます。(E_WARNING → E_NOTICE)
多分コメントアウトしてしまえば、NOTICEすら発生しません。(試してない)

ext/standard/array.c は、

php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");

これを、

php_error_docref(NULL, E_NOTICE, "Parameter must be an array or an object that implements Countable");

に書き換えます。(E_WARNING → E_NOTICE)

あとは念のため、make clean して再インストールします。
怖いのでmake test はしません。

make clean
./configure {オプション自由}
make
make install

あとは、

<?php print count(NULL); ?>

などして、WARNINGが発生しないことを確認してください。
(php.ini の設定などで、メッセージの出力等は異なります。)

count(null); // 0
count(1); // 1
count('abc'); // 1
count(new stdclass); // 1
count([1,2]); // 2

WARNING無しでPHP5と同じ結果が出るようになりました。(NOTICEは発生してる)

当然ですが、公式では非推奨です。

多分、これやるとPHPコミュニティにすっげぇ怒られます。

バージョンアップをするときは、毎回同じ改造が必要です。

くどいようですが、本当に、
自己責任
でやりましょう。

というわけで、patch簡単に作れるんですが、
作らないでおきます。

他、undefinedが出るような関数##

自分で定義して互換動作させてます。
mysql関数とか、ereg()関数とか。
いろいろ問題ありそうだけど…。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?