• ベストアンサー

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

  • 【ASP.NET MVC】モデルの作り方

    ASP.NET MVCでのモデルについて、皆様はどのように作成しておられますか? ASP.NET MVCで何本かWebシステムを構築して、いまだに試行錯誤です。 サンプル例を見ても、実際とはかけ離れた簡単な内容で、あまり参考になりません。 自分が見たいくつかのサイトではこのように書いてありました。 ドメインモデル データベースと1:1で存在する入出力用のモデル。EntityFrameworkで定義する。 拡張ドメインモデル ドメインモデルにプロパティを追加したり、複数のモデルを使いやすくまとめたモデル。 ビューモデル 画面表示するためのモデル。 フォームモデル フォーム入力値を受信するためのモデル。 理屈はわかるのですが、このように4種類もモデルを定義するものなのでしょうか? モデル間のデータのやりとりも大変ですし、定義だけで作業量が半端ない感じです。 継承などをうまく使って省力化する方法とかありますか? 皆さまの方法論をお聞きしたくお願い申し上げます。 ASP.NET MVCに限らず、CakePHPなどの例でも歓迎です。

  • PHP MVCパターンでのデータの受け渡し

    PHPでのMVCパターン?についての質問です。 http://www.stackasterisk.jp/tech/php/phpMvc01_01.jsp こちらを参考に作っているのですが、パート間でのデータの受け渡し方がわかりません。 Modelで取得したデータや処理したデータを、1つのオブジェクト管理し受け渡しています。そのオブジェクトの中に、オブジェクト(VO群?)、またその中にオブジェクトを入れたりしていくと、Viewへ渡す時に、どうやって値を取り出せばいいのかわかりません。オブジェクトの入れ子が少なければ、1つ1つゲッターで取り出していくのも手間ではありませんが、入れ子が多いと…。foreachではpublic以外は取得できないようなので困っています。 このような場合は、どのようにすべきなのでしょうか。 また、このような方法は、普通使われる方法なのでしょうか。 よろしくお願いします。

    • 締切済み
    • PHP
  • MVCモデルでのサーブレットのやること

    Javaを習い始めた者です。 MVCモデルでのサーブレットのやるべきことが、いまいちつかめないので質問させていただきます。 私が思っているサーブレットのすることは、 (1)送られてきたた情報をgetParameter()する。 (2)JavaBeanを生成したり、getAttribute()する。 (3)getParameter()したものをJavaBeanにsetする。 (4)JavaBean内のメソッドを実行する。 (5)JavaBeanをsetAttribute()する。 (6)別のJSPなどにfoward()する。 です。 (基本的に計算や比較などの処理は、サーブレット上では行わず、JavaBean内のメソッドで行う) この考え方は間違っていますか? あと例えば、ログイン認証のプログラムを作るとき、上の考え方だと、getParameter()したIdとPasswordをJavaBeanにsetして、JavaBean内のメソッドで、setしたIdを元にDBからPasswordをgetしてきます。そしてこのPasswordと、setしたPasswordを比較することになると思います。 でも、私的にはJavaBean内のメソッドで、引数にgetParameter()したIdを与えて、DBからgetしたPasswordを戻り値にします。そしてサーブレット上で、このPasswordとgetParameter()したPasswordを比較しようと思いました。 でもこれだと、サーブレット上でPasswordを比較するという処理を行っているのでMVCモデルに反しているのでしょうか? わかりにくい説明で申し訳ないのですが、教えてください。 お願いします。

    • ベストアンサー
    • Java
  • RailsのMVCモデルに関しての基本的な質問

    お世話になります、Railsに関して一通り入門書を読んだのですが、MVCモデルに関してご教示頂きたいのですが、現状LinusサーバにRubyGemがインストールされているので、WEBのトップページにも活用しようと考えているのですが、基本的な質問で恐縮なのですが、そもそも、MVCモデルは外部からのイベント(通常はユーザ入力)を受け取り、モデルとやり取りし、適切なビューをユーザに表示するというのが基本的な動作かと思いますが、その外部からのイベントがない静的なWEBページを作成する場合は、特にコントローラを作成する必要はないと考えて良いのでしょうか。 現状、spinelzと部分テンプレートのWEBページ作成を検討しています。データベース等はもちろん使用しません。

  • ASP.NET MVCでObjectをjsに渡す

    いつも勉強させてもらっております。 ASP.NET MVC3で、ビューに渡すモデルを用意するのですが、最近javascriptをよく使うので、一発で展開できるようにできないかと思っています。 現在は、いったん起動後、jQueryで、Ajax JSONで取得しています。こちらだとすぐjavascriptのオブジェクトが取得できるので。 javascriptで一発展開というのは例えば、 public class HogeClass {  public string moge { get; set; }  public List<string> fugas { get; set; } } があって、ビューモデルとして public ActionResult HogeAction(){  var hogeObj = new HogeClass();  return View("hoge", hogeObj); } のようにビューへ渡して、 ビューの"hoge.cshtml"内部で、 <script type="text/javascript">  var hogeObj = <%=Model %>; // こんなので通るわけないですよね </script> とかできたらいいなあ、という話です。 いちいち起動のたびにAjaxで読み直すのは速度のこともあるし、気になります。 これまでは全部サーバでやってたのでこんなこと考えなかったんですが、皆さんはどうされてます?

  • 【ASP.NET MVC】HTMLヘルパーについて

    VisualStudio2010 ASP.NET MVC4.0で開発しています。 検索条件を入力欄から入力し絞り込みさせ、結果を表示する照会画面を作成しています。 ある理由から「入力欄の値をPostで受け取りController内でその値を書き換えさせ、 Viewに戻り、書き換わった状態で入力欄を表示させたい」という事をしたいのですが、 ラムダ式で行うと書き換えが無効になり入力値のままになってしまいます。 @Html.TextBoxFor(model => model.Crdate,) 以下で表現するとキチンとController内の書き換えが有効になって表示されます。 @Html.TextBox("Crdate", Model.Crdate) 解析してみたところTextBoxForの第一引数HtmlHelperの htmlHelper.ViewData.ModelState.Valuesが入力状態を持っていて それがある場合に優先されているのかな?という憶測が立っています。 (初期表示の時点のhtmlHelper(htmlHelper.ViewData.ModelStateにKeyがない状態)をセッションに保存させPost後、画面で表示する際にセッションから上書きしてやるとちゃんと値が変わったため) バリデーションチェックの関係上出来ればラムダ式のHelperForの形でやりたいのですが、 方法がありますでしょうか? よろしくお願いいたします。

  • MVCモデルのJSPの使い方

    こんにちは。二回目の質問をさせていただきます。 今MVCモデルとJDBCで、社員データをDBにいれる簡単なプログラムを作ろうとしているのですが、初期の段階で躓きました。 サーブレットにてBeanをSessionに関連付けているのですが、いざJSPにてBeanを使おうとするとエラーが出るのです。 JSPのコードは冒頭部分にきちんと下記のものを記述し、 (Beanクラス名はFileBeanです。サーブレットできちんとSessionで関連付けています) <jsp:useBean id="bean" class="FileBean" scope="session" /> JSPの中で、Beanのメソッドを使うようにしているのですが下記のようなエラーが出てしまいます。 org.apache.jasper.JasperException: JSPのクラスをコンパイルできません注: sun.tools.javac.Main は推奨されません。 JSPファイル: /Nyuryoku.jsp の中の行: 3でエラーが発生しました 生成されたサーブレットのエラーです: C:\Apache Tomcat 4.0\work\localhost\SyainData\Nyuryoku$jsp.java:65: クラス org.apache.jsp.FileBean が見つかりません。 FileBean bean = null; ^ 因みに参考書のもので試してみたところ、JSPにおいてBeanを使おうとすると空のHTMLが吐き出され、ブラウザには真っ白な画面が表示されます。JSPのBeanの部分を削除すると、ブラウザには普通にHTMLの部分が表示されるのです。 以上二つのことから、JSPでのBeanの使い方がおかしい、というのはわかったのですが、自分でどう解決して良いのかわかりません。特に参考書のコードはちゃんと市販されているものなので、問題ないと思うのですが… 最後になりましたが、私の環境は Tomcat4.0 で OSはMEになります。 皆様お忙しいとは思いますが、ご教示の程宜しくお願い致します<(_ _)>

    • ベストアンサー
    • Java
  • WEBアプリのMVCについて質問です。

    一般的なフレームワークを用いたMVCについて質問です。 例えばM、これはモデルですね。 普通DBヘの接続はモデルでおこないクエリの発行もモデルで行いますね。 その後、クエリ実行後の結果をコントローラー側に返すと思います。 このとき、普段わたしはモデル上ではDB空の目的のデータをいっさい処理せずそのまま コントローラに返します。 返り値として、何かしらの一覧データを取得するものとします。例えば [ {name : "タロウ" , age : "20","town_id" : 10,"city_id" : 49, "prefecture_id" : 23}, {name : "花子" , age : "20","town_id" : 10,"city_id" : 49, "prefecture_id" : 23}, {name : "邦夫" , age : "20","town_id" : 10,"city_id" : 49, "prefecture_id" : 23} ] といった感じで特定の組み合わせのハッシュを多次元配列(リスト)的にラップしたものがかえりますよね。 そして、上記データをコントーラー側が受け取り、さぁいざビューへと受け渡す際に、どの程度コントローラでデータの 加工を行うものかが気になっています。 たとえば上記データでは「県市町」のデータがユニークなIDとして保持しています。このままでは「タロウ」が どの住所なのかがわかりません。どこかで「県市町」のデータリストを受け取りループで一致する住所を取得する 必要があります。 それをコントローラあるいはビュー・・・・どちらで行うのがMVCとして正しいのでしょうか?多少のループなら ビュー側で行うのもありかとおもいますが、はやりビューがループであふれかえるのは作業しにくいですよね。 MVCの基本だとは思いますが、rubyやPHPなど、フレームワークごとの細かい思想はあるでしょうが 一般的なMVCとしてみるとどうでしょうか? ちなみに、モデル内でjoin などつかって県市町のテーブルをくっつけるのはここでは考えないものとしてください。 個人的にはビュー内では大きなループ一度ですませたいものですが ・・・。

  • 【ASP.NET MVC】フォームヘルパーの是非

    いつも大変にお世話になっています。 今回も例によってASP.NET MVCの質問です。 ASP.NET MVCでは、Htmlヘルパーを使用してビューを記述するのが常識かと思います。 例) @Html.Textbox("name", Model.name) 今回、デザイナが加わる仕事で、完成後にデザイナ側でフォーム訂正が必要になることが予想されます。 またその際、デザイナから「できるだけ独自仕様(Lazorのこと?)のテンプレートを使用しないように」とのお達しがあったため、苦慮しております。 質問です。 Htmlフォームヘルパーを使わずに、純粋なHTML記述を行った場合、どのような支障が考えられますか? 要件: @Html.Textbox("name", Model.name) と書かずに。 <input type="text" id="name" name="name" /> と(HTML展開後の文法で)書く場合の違いを知りたい です。同じ動作をするのでしょうか?また、違いの程度は? です。なにとぞよろしくお願いします。

  • JavaBeans,JSP, Servlet(MVC)のみを使った開発って本当に業務で行われているの?

    こんにちは、私がWeb技術を勉強するときによく使う本として、Sun教科書Web Component Developer(試験310-080の対策本なのですが、おそらく現在売っているものより1バージョン古いです)という本があります。 この本には,webのMVCアーキテクチャは以下のように 設計されると記載されています。 サーブレット:Controller(システム処理の制御) JSP :View (画面) JavaBeans :Model (ビジネスロジック) しかし、実際の業務でビジネスロジックがJavaBeansのみで行われているシステムはあるのでしょうか?JavaBeansの定義としては、getXXXやsetXXXアクセス、またコンストラクタが引数をもたずpublicなどと ありますが、これを無視した普通のJavaクラスもビジネスロジックに使われているのではないでしょうか? EJB, Strutsを使わない開発環境でという条件付で、どなたか業務経験のある方、この疑問に答えていただけないでしょうか?