Nucleus(JP)フォーラム

NucleusCMS日本語版ユーザーのためのサポートフォーラムです。疑問が生じたらまずは記事検索をご利用ください。

ログインしていません。

#1 2016-08-08 22:33:51

ppyochan
メンバー
登録日: 2008-01-18
投稿: 30
ウェブサイト

PHP7.0.9での不具合報告

先日PHP7.0.9がリリースされたので、7.0.8からアップデートしたら
アイテム編集画面の「追加プラグインオプション」の部分でいくつかのプラグインの動作がおかしくなりました。

自分が実際に確認したのは、「Custom URL」の部分が表示されなくなり、
アイテムを保存するとカスタムパスが元の「item_xx」に戻ってしまうという症状です。

他のプラグインでもイベントが呼び出されないという症状が出たようです。

アップデートする際は注意が必要かもしれません。

コアの開発にも影響する部分かもしれませんのでご報告まで。

オフライン

#2 2016-08-09 20:30:21

ピヨピヨbird
メンバー
登録日: 2015-04-05
投稿: 78

Re: PHP7.0.9での不具合報告

ppyochan さんの発言:

先日PHP7.0.9がリリースされたので、7.0.8からアップデートしたら
アイテム編集画面の「追加プラグインオプション」の部分でいくつかのプラグインの動作がおかしくなりました。

問題の起きそうなところは
・sqlのキャッシュ
・コアのオプション関数
・プラグイン側の event_関数
の順ですね

Version 7.0.9 Core:    Fixed bug #72508 (strange references after recursive function call and "switch" statement).
とあるので 、reference をいじったようなので MANAGER::notify 関数が破壊された可能性も若干あります

オフライン

#3 2016-08-10 12:36:06

ピヨピヨbird
メンバー
登録日: 2015-04-05
投稿: 78

Re: PHP7.0.9での不具合報告

「まとめ」
以前フォーラム(2012年8月)でmekyoが指摘していましたnotify関数内のcall_user_func関数の誤使用が原因でした。

フォーラムid=6141 (2012-08-24)で指摘しているように
MANAGER.phpのfunction notify関数の

if (isset($this->plugins[$listener]) && method_exists($this->plugins[$listener], 'event_' . $eventName))
 call_user_func(array($this->plugins[$listener], 'event_' . $eventName), $data);

から ↓

$event_funcname = 'event_' . $eventName;
if (isset($this->plugins[$listener]) && method_exists($this->plugins[$listener], $event_funcname))
  $this->plugins[$listener]->$event_funcname($data);

に変更すると直ります。

急ぐ場合は、手動で上記の内容を修正することで対応してください。

「概要」

php 7.0.9 + 英語版 or 日本語版 Nucleus + NP_CustomURL
+ ini_set('display_errors','0'); で警告を消しても
同様の現象を確認しました。
追加プラグインオプションの Custom Pathが表示されなくなりました

php 7.0.9にするとプラグインで
expected to be a reference, value given in /nucleus/libs/MANAGER.php
と表示されます。
下記に記載のスレッドの通りに notify関数を修正すると直りました。

(2012年8月) call_user_func_arrayの挙動

誤実装を指摘していますが
以前のメイン開発チームにいた人が記述を理解できずに、報告者をバカ扱いし、修正すべきコードを変更をせずに、そのまま放置されていたため
今回 php7.0.9で不具合を起こしたようです。

7.0.9でコアに修正が入り、本来の動作?になっため動作しなくなったと思われます。

phpのcall_user_funcの説明書にも

注意:
call_user_func() のパラメータは 参照渡しではないことに注意しましょう。

と記述されています

参照渡しにしたい場合は、call_user_func_arrayを使わないといけないのです。

このコードで

call_user_func_array(array($this->plugins[$listener], 'event_' . $eventName), array(&$data));

修正すると正常動作にできるのですが、
phpとそのソースであるC言語について上級程度の知識がないと理解が難しいので
Nucleusは、オープンソースであり、素人,プロいろいろなレベルの人がいることもふまえ, notify関数での
call_user_func系の関数を使うのをやめ
以前フォーラムで指摘されているように誰でもわかるコードで
素直に

$event_funcname = 'event_' . $eventName;
if (isset($this->plugins[$listener]) && method_exists($this->plugins[$listener], $event_funcname))
  $this->plugins[$listener]->$event_funcname($data);

としたほうが簡潔で、だれでも理解でき、誤動作もなく いいと思います
変数に関数名をいれて$つけると関数として動作する文法が廃止されるまでは、
期待通りの動作をこれからもするはずです。

Nucleus - プラグイン API ヘルプより

パラメータ
event_EventName メソッドはひとつだけ $data パラメータを持ち、
それはイベントごとに内容が異なります。これは連想配列です。
この連想配列に渡されたオブジェクトや配列は参照形式で渡されるため、
これらに加えた変更は記憶されます。

引数は1個しかないので、->$変数($data) の 記述で問題ないと思います。

編集者 ピヨピヨbird (2016-08-10 15:16:29)

オフライン

#4 2016-08-10 13:42:18

ピヨピヨbird
メンバー
登録日: 2015-04-05
投稿: 78

Re: PHP7.0.9での不具合報告

英語版と日本語版のmasterと開発ブランチ両方にプルリクエストしましたので、しばらくお待ちください。

オフライン

#5 2016-08-10 15:13:14

ppyochan
メンバー
登録日: 2008-01-18
投稿: 30
ウェブサイト

Re: PHP7.0.9での不具合報告

検証と修正ありがとうございました。
以前より問題視されていた部分が今回のアップデートで浮き彫りになった感じですね。
マイナーアップデートで不具合が出たので少しびっくりしました。
この件はこれで安心です。

オフライン

Board footer