- ベストアンサー
CakePHPでシングルトンパターンとは?
- CakePHPでシングルトンパターンを使用してインスタンスを使いまわす方法について
- シングルトンパターンを実装するための設定が足りない可能性がある
- Testクラスを呼び出す際にインスタンスが新しく生成されてしまう問題が発生している
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
隠蔽されていることから逆に考えてしまえば、そもそもシングルトンを使う必要がないということですね。シングルトンは内部状態を持ち、テストが書きにくいため、特にフレームワークを導入していて自動テストを理想とするような開発では嫌われる傾向にあります。無理して使う必要はないでしょう。
その他の回答 (6)
- mpro-gram
- ベストアンサー率74% (170/228)
No4回答へのお礼の記載に関して >1度作成したインスタンスは、Apacheを再起動するまでは、作成しないようにすることはCakePHPでは可能なのでしょうか phpでは、無理です。 php の実行自体が 1リクエスト1実行 で完了します(完了時メモリ解放)。メモリー上のオブジェクトのユーザー間共有は無理です。1ユーザーの複数リクエストでさえ、sessionにでも保存しない限り共有できません。 「情報共有」の観点では、保存状態がオブジェクトである必要はないと考える、phpのシングルトンはその目的には使えないし。同じ情報が各リクエストにおいて再生されればいいのですよね。 cakePHPならデータベース利用前提なので、共有したい情報をデータベースから読み込むModelを作って(Modelのコンストラクタで読み込んで、プロパティに保持するなどしておく)、全ControllerにそのModel利用を強制すればよい(AppControllerのuseプロパティにそのModel名を記載しておけばok)。
要は、接続のためのコストを取っ払ってしまいたいということですね。可能です。 【PDO使用時(参考)】 コンストラクタのオプションにて PDO::ATTR_PERSISTENT を True で渡します。 【CakePHP使用時】 情報が少し古いかもしれませんが、以下を参考にしてください。 http://www.phpbook.jp/cakephp/install/index2.html 但し、この接続の使いまわしはC言語で書かれたインタプリタレベルで行われることであり、PHPコードレベルで見れば隠蔽されている話です。よって、getInstanceにより必ず「スクリプト起動ごとに」1回目は新しいものが生成されることになります。これは言語仕様の問題なので気にするところではないでしょう。
ちなみにこれだと全部Trueになってしまいます。 http://pastebin.com/Rz0NVd3a PHPのstaticなメソッドにおける初期化処理は親子別に行われるのに、staticなプロパティが親子間で共有されてしまう点は気持ち悪いと言えるかもしれませんね。他の言語の実装はどうなっているんでしょうかね。
お礼
情報提供ありがとうございます。 確かに気持ち悪いですね。 頂いたソースにログを出力してみたのですが、 public static function getInstance() { if (!static::$instance) { static::$instance = new static; LogError("インスタンス生成"); }else{ LogError("使い回し"); } return static::$instance; } リクエストの度に、インスタンスを新しく作ってしまうのですが、 私のイメージでは、システムを使用しているすべてのユーザで、インスタンスの情報を共有したいのですが、 何か書き方が違いますか? 1度作成したインスタンスは、Apacheを再起動するまでは、作成しないようにすることはCakePHPでは可能なのでしょうか。 Javaなら何度も実装したことがあるのですが、CakePHPでは初めて、かなり悩んでます。
getInstanceのシグネチャはこうですね。staticつけ忘れてました。こうしないとStrictStandardsエラーが発生してしまいます。(エラーを非表示にされているかもしれませんが) public static function getInstance() { ... } 以下のコードで期待した結果になります。 http://pastebin.com/gCqUEzs5
お礼
何度もありがとうございます。 ご教授頂いたソースを適用してみたのですが、すべてtrueで返却されます。
プロパティ使わなくてもstatic変数でいけますよ class Test { private function __construct() { } public function getInstance() { static $self; if (!$self) { $self = new self; } return $self; } } 継承を前提にするなら class Test { final protected function __construct() { } public function getInstance() { static $static; if (!$static) { $static = new static; } return $static; } }
お礼
ご教授ありがとうございます。 頂いたソースを真似して実行してみましたが、うまくいきませんでした。 何か事前設定などはありますでしょうか。
補足
CakePHPですが、2.Xを使用しております。
- kosukejlampnet
- ベストアンサー率44% (126/282)
class Test{ public static $instance = null; private function __construct(){} public function getInstance(){ if(is_null(self::$instance)){ self::$instance = new static(); } return self::$instance; } }
お礼
ご教授ありがとうございます。 ご教授頂いたURLの内容をコピーして、実行してみましたが、 うまく実装出来ないようです。 呼出方などの問題ありますでしょうか。 ※ 補足のところで1つソースが間違っておりました。 public function beforeRender(){ $obj = Singleton::getInstance(); var_dump($obj === Singleton::getInstance()); $obj2 = SingletonChild::getInstance(); var_dump($obj2 === Singleton::getInstance()); var_dump($obj2 === SingletonChild::getInstance()); } が正しいです。 var_dumpの結果が、全てtrueになってしまいます。
補足
参考URLで記載のソースを、Controller/Componentに配置し、AppControllerから呼び出しております。 App::uses('SingletonChild', 'Controller/Component'); App::uses('Singleton', 'Controller/Component'); 呼出方の問題でしょうか。 public function beforeRender(){ $obj = Singleton::getInstance(); var_dump($obj === Singleton::getInstance()); $obj2 = Singleton::getInstance(); var_dump($obj2 === Singleton::getInstance()); var_dump($obj2 === SingletonChild::getInstance()); }
お礼
情報のご提供ありがとうございます。