PHPのバージョンを5.4にしたときのClass ‘Debugger’ not found inについて

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
日本語で言うとこの「朝飯前だぜ」って感じかなぁ

この記事を三行にまとめると

PHPのバージョンを上げたら変なエラーが出た
でも解決した
It's a piece of cake!!
もうね、全く原因が分からんかったんですよ。

何がって、サーバーのPHPのバージョンを5.3から5.4に上げたときの話よ。

さくらインターネットのレンタルサーバーを使っているとね、PHPのバージョンをいくつか選択できるんですよ。デフォルトはたぶん、5.3なのかな。

でも一応、5.4も選ぶことができるんで、今回ちょっと、わけあって5.4に上げてみようかなーと思いまして。まあ、実際に上げてみたんです。

そしたらあーた、動かないじゃないのよ。ウェブサイトが。Fatal Errorが出て、うんともすんとも言わない。

どんなFatal Errorかって? そりゃ記事のタイトルにも出ているあいつよ。

Class ‘Debugger’ not found in 〜

言ってることは何となく分かる。Debuggerとかいうクラスがないよってことだよね。

まあ、たいしたエラーじゃねえ。Debuggerとかいうクラスを読み込めば問題は解決すんじゃん、楽勝じゃんって話よね。

と・こ・ろ・が。

これが案外そーでもなかった。いや、最終的にはそんなに難しい話じゃなかったんだけど、それが分かるまでに思った以上に労力を割いてしまったのよ。

何が時間かかったって、同じようなエラーに悩まされてる人は結構いたんだけど、検索しても出てくるのが英語のサイトばっかで、しかも僕はそんなに英語が堪能じゃないから、それでちょっと苦労しちゃったのよね。

なので、僕と同じように上記のエラーに悩まされて、なおかつ僕と同じように英語が苦手な人のために、ちょっと今日はそのときの話をさせてもらおうじゃないの。NIHONGOでね。

いや〜、過去に何度思ったか知らないけど、やっぱり英語はできるようになっといた方が良いね。僕みたいに「Hello」「Thank you」「It’s a piece of cake」くらいしか知らないと、損すること多いわ。

あ、そうだ。cakeで思い出したけど、今回はCakePHP2系で開発してる際に起こった話です。だからこっから先も、Cakeで開発してるって前提で話を進めますよ。Cakeじゃなくても、同じような状況を作れば、同じようなエラーが出るとは思うんですけど。



まずは素直に

英語のサイトうんぬんの前に、とりあえず試してはみたんですよ。Debuggerとかいうクラスを読み込むってやつ。

僕の場合、ビューのヘルパーのところで、例のエラーが出てたんで、そこで最初に読み込んでみることにした。

CakePHP2系の場合、Debuggerっていうクラスは、コアファイルの「Utility」っていうディレクトリの中にDebugger.phpっていうファイルがあって、そこに存在する。

だから、ヘルパーの先頭にこんな記述をすれば解決する……はずだった。

App::uses('Debugger', 'Utility');
class SampleHelper extends AppHelper {

}

しかし、全く解決する気配がねえ。「くくく……俺はしぶといぜ」と言わんばかりに、Fatal Errorが消えやしねえ。戸愚呂兄もビックリだな。

もうこうなると原因が分からんやん? エラーメッセージのお導きのままにDebuggerっていうクラスを読み込んだのに、解決できないんだから。

ってことで、英語だらけのバグ修正大会にエントリーすることになるわけです。



多くの人が言ってたことは

「public」とか「protected」とかの、えーと、あれは何て言うのかな……メンバ変数の宣言って言うの? あれがないのはダメだよって言ってるんですよ。

Cake2.0のコアファイルを見ると、変数の場合だけじゃなくて、関数のfunction()の前にもpublicとかprotectedとかついてるんです。こんな風に。

pubiic function __construct() {

}

CakePHP1.3の場合はこういうのはついてない。

あかつきのお宿の場合もそうなんですが、元々は1.3で作ってたのを2.0にアップグレードしたもんですから、自分で作った関数の方は、みんなpublicとかの宣言がついてなかったんです。

で、どこぞの外人さんが言うには、それつけないとダメよと。

ってことは、これつければ直るのかなと思いまして、僕もつけてみました。そりゃもう、手当たり次第につけてみた。ストーカーが好きな女性の後を延々と尾行するくらい、しつこくつけてみた。



でも、直らなーい。ナオラナイヨ、シャッチョーサーン。

どうやら、宣言するだけでは直らないものだったようです。

こうして、英語だらけのバグ修正大会はポロリすることもなく、幕を閉じました。まあ強いていえば、エラーが解決できないことに涙がポロリしたのかな?



オーバーライドしてただけ

実はここに来るまで、他のページを見てみるっていう作業をすっかり忘れてたんですよ。トップページを表示しようとしたらFatal Errorが出ちゃってたんで、たぶん全ページがこうなんだろうなって思い込んじゃってて。

でもふと「どこか無事なページはないのか。生存者がいるなら返事してくれ。一緒にハポンに帰るって約束したじゃねえか。国に残して来た奥さんと娘はどうすんだよ。なあ、おい……」って思い立って、他のページのURLを叩いて確かめてみたんですよ。

そしたら、いたんですよ、生存者が。

ただし、Fatal Errorは出てなかったものの、全くのノーエラーってわけではなくてですね……こんなエラーが出てました。

Declaration of UtilHelper::addClass() should be compatible with Helper::addClass($options = Array, $class = NULL, $key = ‘class’)

ここのUtilHelperっていうのは、僕が作ったヘルパーのクラス名でして、一般的な名前ではないです。

んーと、どういうエラーかってーと、UtilHelperの中にある「addClass」っていう関数は、継承元であるHelperっていうクラスの中にすでに存在してるぜ。だからオーバーライドしてるわけだが、なーんかその書き方がおかしいんでねーの? っていうエラーです。

コアファイルの中にあるHelper.phpの中には、昔からaddClassっていう関数があったんですね。調べてみたら1.3の方にもあったわ。そうとは知らず、僕はこの関数を知らず知らずのうちにオーバーライドしちゃってたみたいです。ヘルパーという波にライドオンしちゃってたみたいです。

なので、このUtilHelperの中のaddClassっていう関数を別の名前に変えたら、エラーは消えました。Fatal Errorの方も消えました。

まったく……人騒がせなFatal Errorですよ、ホンマに。何でこれが原因でDebuggerっていうクラスがない的なエラーになってたか。それは未だによく分かりません。



あれあれ? ちょっと待てよ?

まあ、原因は分かったし、その解決方法も分かった。それはいい。

でも、関数をオーバーライドすることに何で問題があるのか? っていう話なのですよ。

だってオーバーライドって、普通にやることあるやん。やることあるし、やってもエラーとか出ないやん。



調べてみたところ、オーバーライドする関数の引数に問題があると、上記のエラーが出るらしいんですよ。Fatal Errorの方じゃなくて、Declaration〜とかいうエラーの方ね。

今までエラーが出てなかったってことは、たぶんバージョンが5.4以降の仕様とかそんな感じのような気がするんですけど、オーバーライドする側の関数とされる側の関数の引数が違っていると、ダメらしいんですよ。

class Sample extends ParentSample {
  //オーバーライドした関数
  public function test() {

  }
}

class ParentSample {
  //継承元の関数
  public function test($option) {

  }
}

例えばこんなんですね。継承元の関数で引数が指定されているのに、オーバーライドする関数で引数がなかったりすると、エラーになります。

引数の数がずれててもダメみたい。引数の数が合ってても、デフォルト値のあるなしが違っててもNGだそうで。デフォルト値そのものが違う分には大丈夫らしいんですけどね。

//引数の数が違うパターン
class Sample extends ParentSample {
  //オーバーライドした関数
  public function test($option) {

  }
}

class ParentSample {
  //継承元の関数
  public function test($option1, $option2) {

  }
}

//デフォルト値のあるなしが違うパターン
class Sample extends ParentSample {
  //オーバーライドした関数
  public function test($option1, $option2) {

  }
}

class ParentSample {
  //継承元の関数
  public function test($option1 = array(), $option2 = true) {

  }
}

//デフォルト値が違うパターン(エラーにならない)
class Sample extends ParentSample {
  //オーバーライドした関数
  public function test($option1 = array(), $option2 = false) {

  }
}

class ParentSample {
  //継承元の関数
  public function test($option1 = array(), $option2 = true) {

  }
}

ちょびっとルールが厳しくなったのかな。






ってな感じで、分かってみれば何のことはないエラーだったっていうお話ですね。

むしろ、この解決方法が分かってから改めて英語のサイトを見てみたら、ちゃんとオーバーライドがどうのこうのとか、Declarationがどうのこうのとか、結構書いてあったわ。はずかし〜///

英語ができない奴はこれだから……ねえ?

まあ何にしてもあれよ。もし僕と同じようなエラーが出たとしても、慌てるこたぁねぇって話よ。

すぐに取り除けるエラーだから。ちょちょっとオーバーライドしてるっぽい関数を修正するだけオーケーさ。

It’s a piece of cake!!
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください