• ベストアンサー

MVCモデル MV間のデータ共有

先日ここで質問させて頂いたところMVCというモデルを紹介され、いろいろ調べて試しては見たのですが、わからない部分がありましたので質問させて頂きます。 一般的にはMV間でどのようにしてデータを共有するのでしょうか? 以下のような方法を考えては見たのですが、どれもしっくりこなかったので・・・。 ・Modelの実行結果をViewの引数として使う(スマートじゃない気が?) ・$GLOBALSやglobalを使う(これもスマートではないような?) ・セッションを使う(Cookie使えなかったら・・) ・データベースを使う(そこまでする必要が!?) ・singletonなオブジェクトを使う(いまいち理解できていないのですがこれが一番近いような気がしてます) 本来なんらかの書籍を読むべきなのでしょうが、少し気になったので質問させて頂きました。 根本的に考え方が間違っているようであればお勧めの書籍等教えて頂けると助かります。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

MVCパターンなフレームワークのCakePHPですが、 FormHelperという、modelデータからフォームを形成するようなヘルパが用意されており、どうやってmodelを呼び出しているかを眺めてみると、ClassRegistryというクラスを使っているようですね。 k17sさんが最後にあげたsingletonパターンのクラスオブジェクトで、 こちらにmodelだとかクラスをゲッターで保存しておいて、 セッターで呼び出してあげるという手法です。 アクセス手段は、 [クラスを追加する] ClassRegistry::addObject($key, $object); [クラスを呼び出す] ClassRegistry::getObject($key); というもののようですね。 Cakeで実現していることを物凄くザックリ、且つ、PHP5で記述すると以下のようになります。 class MyRegistry{ private static $instance; public $objects = array(); /*================================== 外からnewでインスタンスを作成できないようにprivateにする ==================================*/ private function __construct(){ } /*================================== 通常はコレをpublicにして単一のインスタンスを呼ぶようにするわけですが これもaddObject/getObject以外から呼べないようにする。 ===================================*/ private static function getInstance(){ if(self::$instance === null){ //staticなメンバ変数が空だったら self::$instance = new MyRegistry(); //クラス内部から自分自身をnewしてやる } return self::$instance; //で、それを返す。 } public static function addObject($key, $object){ $self = self::getInstance(); //自分自身のインスタンスを読んできてやり $self->objects[$key] = $object; //メンバ変数に名前とオブジェクトを格納 } public static function getObject($key){ $self = self::getInstance(); //自分自身のインスタンスを読んできてやり return $self->objects[$key]; //登録されている$keyのオブジェクトを呼ぶ } } ?> これは、 <?php //なんかどこぞでモデルが呼ばれた(controllerの中とか) $model = new YourModel(); //レジストリに格納 MyRegistry::addObject('YourModel', $model); //modelを使いたい(Viewの中とか) $model = MyRegistry::getObject('YourModel'); ?> いかがでしょう。

k17s
質問者

お礼

回答ありがとうございます。 ずばり!期待していた答えそのものでした! Singletonなクラスについてあまりよく知らなかったのですが、ソースをつけて頂いたおかげで非常にわかりやすかったです。 もう目から鱗です。久々にソースを見て興奮しております。 是非是非参考にさせて頂きたいと思います。 又、以後調べる際には既存のコードも参考にさせてもらおうと思います。 ありがとうございました。

その他の回答 (3)

回答No.4

下記内容が、しっくり来る内容として、 一応他のものも例示します。 >$GLOBALSやglobalを使う これはPHP的には無いことではないと思います。結構様々なライブラリで見る手法ですね。 $GLOBALS['{ライブラリ名の接頭句}_CONFIG'] = 'hogehoge'; こんな感じで他の値と被らないようになっていたりとか。 MVCで分けた場合、クラス内部以外の場所にコードをベタ書きをすることも無いので、外の変数を使うというのもそんなに問題ないのかもしれないなぁという気もします。 CodeIgniterなんかは、Controllerを格納した変数を外においてあって、専用の関数を使ってアクセスする手法のようでした。 <?php $CTRL = new YourController(); function get_instance(){ global $CTRL; return &$CTRL; } ?> 多分PHP4にも対応する為に考えられた手法なのかもしれません。 記述方法的にはシンプルです。 kichiwaveさんの仰られるとおり、実際はmodelが生成した実行結果を配列などで渡してViewは表示するだけ、というのが最も良いのかなとも思いますが、 モデル外のライブラリやコンポーネントという概念のセッティング及び演算を行うものを呼んできてViewで使用するヘルパ関数/ヘルパクラス(HTMLの出力や文字のエスケープなどをつかさどる奴らですね) にその設定した値及びライブラリのメソッドを適用する、なんていった場合は、先のClassRegistryのようなものなどを利用したくなるかな、っと思います。 後は、趣味/嗜好ですかね。 最後に、今回、回答した内容は、有名フレームワークの実装方法をほぼそのまま紹介した内容でした。 MVCの実装に悩んだら、デザインパターンの書籍などを読むのは当然有用な方法ですが、既に実績のあるフレームワークを眺めてみると、同じMVCパターンでもCIとCakePHPの実装方法が大分違っているので、大いに自作したMVCパターンの助けになると思います。

k17s
質問者

お礼

>$GLOBALS['{ライブラリ名の接頭句}_CONFIG'] = 'hogehoge'; 最初の回答を頂いた後、hogehoge78さんに倣ってEthnaというフレームワークでどういった手法が取られているのか自分なりにソースを読んでみたのですが、同じような実装だったと思います。 >後は、趣味/嗜好ですかね。 現在他言語にも興味がありOOPによるシステム構築が第一歩となるかなと思い、できる限り他言語でも通用するような実装というかパターン的な物を使用したいと考えていたので最初の回答にて質問当初の目標は達成できたのですが、今回のようにPHPでは各バージョンに対応する為にもこういった記述も可能とのこと大変参考になりました。 今回親切に回答して頂き、データ共有の実装以外にも考え方や勉強の仕方等、多くの事を学ばせて頂きました。 本当にありがとうございました!

  • kichiwave
  • ベストアンサー率41% (10/24)
回答No.3

・Modelの実行結果をViewの引数として使う(スマートじゃない気が?) が一番近いのではないかと思いますよ 直接引数として使うというより View用のクラスの変数にセットしてやるという形になると思います Smartyを使うとModelの実行結果や表示させたい項目の連想配列をView用の変数にセットする(アサイン:assign)して使いますよ

k17s
質問者

お礼

回答ありがとうございます。 なるほどSmartyをViewにしてしまい、Model内からViewを使用する感じですね。 私の質問の仕方がわるかったのかもしれません。 少しずつ理解できてきたので質問を修正させて頂きますと 「Modelで得られた値をViewやその他複数のクラス内で共有する方法」 が知りたかったのです。 Modelの結果をすべてSmartyにあててしまうと new someClass($smartyobject);や$someobject->setVariableObject($smartyobject); としたり $GLOBALS['smarty'] = $smartyobject; しないといけなくなるのでは? と思って質問させて頂きました。 説明下手ですみません。 #1にてCakePHPではSingletonクラス、その他にもStatic変数を使用すれば実現できるという事がわかったのでこれにて回答は締切らせて頂きます。 ご回答ありがとうございました。

回答No.2

スミマセン、書いてから少し考え直してみましたら、 PHP5では、メンバ変数にstatic変数が使えるので、がんばってSingletonを引かなくても実現できそうですね・・・ <?php class MyRegistry{ private static $objects; public static addObject($key, $object){ self::$objects[$key] = $object; } public static getObject($key){ return self::$objects[$key]; } } ?> 内部にインスタンスを作る意味、もう少し複雑な処理が絡んでくる場合は何らかの意味も出てくるかもしれませんが、今回のようにいくつかのオブジェクトをただ入れて、出す、だけでしたら、上記のようにstaticなメンバ変数に突っ込んでやればよいですね。

k17s
質問者

お礼

なるほど! たしかに単純な用途であればこれだけのコードで全然使えそうですね。 スタティックな変数というのを実はあまり使った事がなく、先日の回答で初めて「こういう使い方をするんだ!」と理解したばかりでして、今回の回答のように「じゃあこうすればもっとシンプルに・・・」とまでは考えられなかったです。 主題も含め、今回Singletonなクラス及びStaticなメンバ変数について少しは理解でき、大変参考になりました。 本当にありがとうございました。

関連するQ&A