PHPでOOP
PHPを使ってプログラミングするとき、 プロシージャ指向(手続き型、構造化プログラミング)でもできますが、 オブジェクト指向を使った場合の恩恵を享受するために、 PHPでオブジェクト指向プログラミングの勉強をしてみましょう。 <目的> PHP5でオブジェクト指向プログラミングを行なうための知識を習得する。 (PHP4のOOPもOK、このスレが1000に行く前にPHP6が出たらPHP6のOOPもOK) <方向性> ・このスレは、プログラミング初心者、PHP初心者の勉強の場として利用することを前提にします。 ・PHPのOOPの話題に限定します。 (Ruby、Python、Javaなど他言語のOOPについては、その言語のスレッドでお願いします。) ・PHPのOOP学習に役立つ本、WEBサイトの紹介をお願いします。 <その他> ・略記は、「OO」=「オブジェクト指向」、「OOP」=「オブジェクト指向プログラミング」でお願いします。 ・質問をする人はなるべくトリップを付けましょう。 ・荒らし、煽り、叩き、気違いは無視・無干渉でお願いします。 このスレで、今日から貴方もOOP!!!\(^o^)/ >>147 読み込んでも八割がた無駄なので使わない MVCのCってどうやって書けばいいのかわからんぜ。 その概念中でコントローラーが理解出来ないってやつ初めてみた とりあえずView上で必要な操作を徹底的にControllerに切り離すが良い。 そしてModelからデータを引き出して必要があれば書き込み更新してやりなさい。 ユーザークラスで新規登録処理をして、そのときにユーザークラスの中で プロフィールクラスのオブジェクトを作ってプロフィールの登録もする これってしいて言えば何パターン? 模範解答は無いけれど、以下の相互変換を行うクラス(ChStr)をみんなで 作ってみるという案はどうかな? そして、これが出来たら、ログファイルに保存などの機能をつけ、 wikiみたいに編集が出来る機能を追加していくという感じに。 <編集> ------------------------------------------------------------- = 2ch '''2ch'''とは、総合掲示板のことである。 link:[http://www.2ch.net ] ------------------------------------------------------------- <出力> ------------------------------------------------------------- <b><font size="+1">2ch</font></b><br> <b>2ch</b>とは、総合掲示板のことである。<br> link:<a href="http://www.2ch.net ">http://www.2ch.net< ;/a><br> ------------------------------------------------------------- >>157 OOPの勉強というよりも、どちらかというと正規表現の勉強になるでしょうか? wikiのパーサーつくるなら、既存のwikiスクリプトや、PEARのText_Wikiが参考になるかもしれませんね。 http://www.phppro.jp/news/172 PEAR::Text_Wiki 1.2.0RC1 リリース 2006年10月11日 http://labs.cybozu.co.jp/blog/tsuruoka/anubis/blog_show/18 Text_PukiWikiリリース >>158 C++のOOPの勉強として、文字列を簡単に扱うことが出来るクラスを 自作してみるという演習があったので、それをPHPでもやってみようかなと 思ったものです。 Cでは、文字列を結合したり、splitしたりするのが結構大変なので、 この演習が役に立ったなと思っていたのです。 PHPの場合は、関数を使えばそれで終わってしまうので、もう少し ひねりを入れたものを考えて見ました。 正規表現を練習するというよりも、正規表現とhtmlの相互変換をする クラスがあると、プログラムをする際、便利だなという事が実感 出来るのでは?という意味合いです。 (例)正規表現を格納し、html出力する過程。 $text に textarea タグの文字列を格納する。 $str = new ChStr($text); echo "<html><body>"; $str->Write_html(); echo "</body></html>"; ほら、このクラスがあるとレイアウトを変えたりが、やり易い上に 再利用性が高いでしょ?みたいな。 OOPの参考になる解説がありました。 PHPのclass、オブジェクト指向プログラミングに関する質問です。 http://q.hatena.ne.jp/1187962431 ↑ 2番の回答者の解説が分かりやすいと思いました。 6番の回答者のサンプルコードも参考になりましたが、これは「インターフェース」の利用方法ではありませんね。>< インターフェイス http://www.phppro.jp/phpmanual/php/language.oop5.interfaces.html あるクラスが実装する必要があるメソッドの種類を、これらのメソッドの実体を定義することなく、指定するコードを作成できるようになります。 インターフェイスはキーワードinterfaceにより定義され、通常のクラスと同様に定義することができますが、メソッドの実装は全く定義されません。 >>159 なるほど!(・∀・) 文字列を扱う処理は、いろんなところで出番がありそうですね! wikiの文法(表記方法)が使える掲示板とか作れそう^^ ChStr クラス の設計はこんな感じかな。 メンバ private $m_str; // 正規表現文字列を格納する。 コンストラクタ ChStr($str) // 正規表現の文字列を受け取る。 private メソッド ch_to_html() // 正規表現をhtmlに変換する。 public メソッド Write_html() // 格納している文字をhtmlで出力する。 Write_text() // 格納している文字を正規表現で出力する。 --------------------------------------------------- 本当は、ログファイルへの保存や読み取りなどを機能として 考え、そのあたりまで含めたクラスの設計をした方が いいんだろうけれど、まずは簡潔にする方向でいきます。 で、後々拡張の方向で。 PHPのインターフェースは、Javaとかのインターフェースとはちょっと違っているみたいですねー。>< (…使ったことないので実感がありませんが^^) PHPでは実装済みのinterfaceを多重に実装できない http://blog.xole.net/article.php?id=589 http://blog.xole.net/article.php?id=597 >>162 こんなかんじのプログラムと似ているかもしれませんねー。 60行で作るPHP用テンプレートエンジン http://anond.hatelabo.jp/20071030034313 >テンプレートの中身を置換する >function convert_string($s) ↑置き換えるパターンに応じて、別々のメソッドを用意したら便利でしょうか? = 文字サイズ変更、''' 強調、link: リンクとかの記法の置換を担当するprivateメソッド OOPの参考になる解説がありました。 関数、オブジェクト、クロージャ http://d.hatena.ne.jp/brazil/20060131/1138692196 >オブジェクトは、データに処理がくっついたものです。 >array.map()のように、後に後に処理を追加していく書き方は、順にコードを追えるため読みやすく、また書きやすいです。 クロージャっていう仕組みは、PHPにはないですね?>< 大は小を兼ねる…クロージャの代わりにオブジェクトが使えればとりあえずOKかな?(・∀・) >>161 >wikiの文法(表記方法)が使える掲示板とか作れそう^^ PEARのText_Wiki使えばよくね? >>164 > 置き換えるパターンに応じて、別々のメソッドを用意したら便利でしょうか? 本来ならば、そうなるでしょうね。それらはすべてprivateで作っておいて、 外部には、一つのインターフェースのみ(この例の場合はWrite_html()がそれに該当) 公開となるでしょう。 記号ごとに別々にメソッドを定義しておけば、記号とhtmlの関係が変わる時は、 どのメソッドを触ればよいかが分かるし、それを変更したことで、 他のメソッドには影響は無かったりします。 (これが構造化プログラムの場合は、目的のソースと目的ではないソースを 見極めるところから始まります。) ------------------------------------------------------------------------- この ChStr に汎用性を持たせる場合は、Write_html()というよりも、 Get_html()とし、html文字列を return する事になるでしょう。 そうすると、別なプログラムで、「出力結果をファイルに保存する」という 使い方も出来ます。しかし、今回は初回なので、Write_html()とし、 メソッド内部で echo 使うことにします。 >>166 学ぶために具体的に物を作るのと、実用性を考えて物を作るのは 別だと思う。なので、今回はこれでいいと考えている。 現に、初心者向けの書籍に載っているソースの実用性はゼロだ。 とりあえず、全体構成の確認のために書いてみた。 ch_to_html()は、追記の必要性がある。 [chstr.php] <?php class ChStr { // メンバ var $m_str_reg; // 正規表現文字列を格納する。 var $m_str_html; // html文字列を格納する。 // コンストラクタ // 正規表現の文字列を受け取る。 function ChStr($regstr) { $this->m_str_reg = $regstr; $this->ch_to_html(); } // private メソッド // 正規表現をhtmlに変換する。 function ch_to_html() { // 改行を<BR>に変更する。 // nl2br($this->m_str_reg) 使った方がいいかも $this->m_str_html = ereg_replace("\n","<BR>",$this->m_str_reg); } // public メソッド // 格納している文字をhtmlで出力する。 function Write_html() { echo $this->m_str_html; } // 格納している文字を正規表現で出力する。 function Write_text() { echo $this->m_str_reg; } } ?> [index.html] 最初に開くファイル。 <html><body> <form method="POST" action="./text.php"><textarea name="reg_text" cols=40 rows=4> あああああ いいいいい ううううう </textarea><br> <input type=submit value=" 送 信 "></form> </body></html> [text.php] <html><body> <?php include("./chstr.php"); $in_text = $_POST["reg_text"]; $chst = new ChStr($in_text); $chst->Write_html(); ?> </body></html> >>166 確かにそうなんですが、「勉強のため」という目的もあるので、自分で作ってみるというのもありでしょうか?^^ でも、答えが分かっている問題を解くのは楽ですね。>Text_wiki 車輪の再発明 - Wikipedia http://ja.wikipedia.org/wiki/%E8%BB%8A%E8%BC%AA%E3%81%AE%E5%86%8D%E7%99%BA%E6%98%8E 車輪の再発明とは、「広く受け入れられ確立した技術や解決法を無視して、同様のものを再び一から作ってしまう事」を意味する ある技術の意味を理解させるために、意図的に車輪の再発明を行わせる場合がある wikiとか文字列を処理する仕組みは、「パーサー」とか「構文解析」っていうみたいですね(´∀`) 構文解析 - Wikipedia http://ja.wikipedia.org/wiki/%E6%A7%8B%E6%96%87%E8%A7%A3%E6%9E%90%E5%99%A8 今までにいろんな仕組みが考えられてきたみたい。 …本格的にやると奥が深そうだけど、一度仕組みを勉強しておいたら、いろいろ使えそうな予感!(・∀・) ↓wikiの仕組みを自分で作っている方は結構いるみたいですねー。 PHP用の汎用WikiParser作り中 http://tdiary.ishinao.net/20050323.html RandomNote/PHPについて http://tbox.jpn.org/wiki/rnh/index.php?AboutPage.txt 今後の課題と予定 ・ch_to_html() の中身を書く。 ・[text.php] の機能を充実(テキストファイルに保存するなど)させ、wikiを作る。 ・上記とは別に、 ChStr クラスを使い、BBSを作る。 ・ChStr クラスに clear()、SetStr() 等のメソッドをつけ加え、汎用性を持たせる。 http://tbox.jpn.org/wiki/rnh/index.php?AboutPage.txt RandomNoteのMain.phpは参考になるでしょうか? preg_match preg_replace array_push array_pop などの関数を使って、文字列の切り貼りをしてるんですねー。 OOPってより単にクラスの使い方書いてるように見えるのはまあいいとして メソッドの中でstringをreturnせずにecho使うのは>>167 で書いてるように汎用性って面もあるけど 処理と表示の分離って意味合いもあるからちゃんとstringで返したほうがいいよ >>175 > OOPってより単にクラスの使い方書いてるように見えるのはまあいいとして OOPについて説明するとなると、具体的なソースコードとは離れた方が 良くなったりしますからね。 (クラスの使い方書いているように見えるとしても、)PHPでclassを 組む場合のメリットみたいな位置づけで学んでいこうと思っています。 > 処理と表示の分離って意味合いもあるからちゃんとstringで返したほうがいいよ 確かに汎用性以外にそういう目的もありますね。 次のものでstringで返すように書き換えます。 htmlのformのコードもクラス化するのが本当の流れんだろうけれどな。 いきなりそれをやると分かりにくくなるかな・・・ ChStrクラスのサンプルソースを投稿してた者ですが、 今までnobodyさんで書いてたけど、分かりにくくなるかと思ったので 酉入れるようにしてみます。 >>5 に書いてあるように、オブジェクト指向は「変数を保持できる事」が メリットだと思うのですが、これがWebアプリだとどうも実感が無かったりします。 リッチクライアントだと、マウスのクリックに合わせて、メソッドが呼び出され、 そのアプリケーションが終了するまでの間、各種オブジェクトの中の変数に 状態が保持されるという構造なので、そのメリットが感じられるのですが、 Webアプリでは、POSTする度にオブジェクトの変数の状態はリセット されてしまうので、クラスを書いたとしても、結局はグローバル変数から 各種オブジェクトの変数に代入するみたいなコードを書かなくては ならなくなってしまうので、このメリットがあるのかと思ってしまうのです。 これは、勉強不足だからなのでしょうか。。。 >>160 他の人の話のほうがよっぽど核心を突いてるよ >>160 のはてなのリンクの4番目の話、2chの別の板でも 読んだことがあるけれど、この話本当なの? 具体的に何処でどういう商売をしての話なんだろうか。 アプリケーションを売る話?それとも開発環境用のソフトを売る話? ピュアな意味でオブジェクトを操作したいなら ボタンのクリックに関する全ての画面遷移に関してserializeとunserializeを管理する必要があるだろ <?php require_once("hiroyuki.class.php"); $hiroyuki = unserialize($_SESSION["hiroyuki"] >>178 ユーティリティクラスの再実装みたいな事を熱心にやっても あまり意味が無いと思いますよ。 まさにあなたの言う「いちいち書くのがめんどくさい」のを回避する為に OOPがあるんだと思います・・・ OOPの勉強なら、簡単なWEBフレームワークを自作するのが一番良いよ。 知識の無い段階でいきなりPHPでOOPって無理だと思いますよ。 背伸びせず、まずjavaやC#を学習する方が近道かもしれないよ。 .NET 以降の VisualBasic ってどうなの? MVCモデルにそって、ユーザの入力データと、CSVファイルのデータを 読み込んで表示させるというものを作ってみました。 ファイル:全部で5つ。index.phpを実行する。 cfcontrol.php cfview.php index.php cfmodel.php csv.txt [csv] aaa,bbb,ccc [index.php] <?php include("./cfcontrol.php"); $form_str = $_POST["form"]; $in_str = $_POST["key"]; $form = new CFControl($form_str, $in_str); ?> [cfcontrol.php] <?php include("./cfview.php"); include("./cfmodel.php"); class CFControl{ function CFControl($form_str, $in_str){ if( ($form_str == "")or($form_str == "in") ){ $form = new CFView("index.php","in",""); $form->Write_HTML(); }elseif($form_str == "out"){ $da = new CFModel(); $dat = $da->ReadDat($in_str); $form = new CFView("index.php","out", $dat); $form->Write_HTML(); } } } ?> [cfmodel.php] <?php class CFModel{ var $m_csv_file; // コンストラクタ function CFModel(){ // 読み込むCSVファイルを指定 $this->m_csv_file = "csv.txt"; } // データを取り出す。 function ReadDat($str){ $INFILE = fopen($this->m_csv_file,"r"); $line = fgets($INFILE, 1024); fclose($INFILE); $line = $line . ", " . $str; return $line; } } ?> [cfview.php](1/2) <?php class CFView{ var $m_file; // POSTするファイル名 var $m_type; // 表示するフォームの種類。in か out var $m_line; // 表示するデータ // コンストラクタ function CFView($file, $type, $line){ $this->m_file = $file; $this->m_type = $type; $this->m_line = $line; } // private function in_html(){ echo "<html><body>"; echo '<form method="POST" action="' . $this->m_file . '">'; echo '<input type="hidden" name="form" value="out">'; echo '<input type="text" name="key"><input type="submit" value="送信">'; echo "</form></body></html>"; } [cfview.php](2/2) // private function out_html(){ echo "<html><body>"; echo '<form method="POST" action="' . $this->m_file . '">'; echo '<input type="hidden" name="form" value="in">'; echo "$this->m_line<br>"; echo '<input type="submit" value="戻る"></form></body></html>'; } // public function Write_HTML(){ if($this->m_type == "in"){ $this->in_html(); }elseif($this->m_type == "out"){ $this->out_html(); } } } ?> とりあえず、MVCに分けて枠組みを作ってみたけれど、 これをより抽象化させていって、「継承して使ってください」という 方向にするのか、それとも最初はクラスの数を増やさないように しながら簡単なアプリケーションを作る方向にするべきか。 どっちの方向に持っていったほうがいいのか迷うな。。。 ま、そんなことを考える暇があったら手を動かしてみろという 話なのかもしれないが。。 >>190 自分で考えるのも良いが、君が今やっていることを やってしまっているのが、フレームワークだ。 まず既存のフレームワークがどうなっているのか参考しろ。 俺も初心者だからこれが最善とは言い切れないけど newするときに全部引数で渡すってのはナシじゃね? 分かりやすいところだけ書き出すと [index.php] $form = new CFControll(); [cfcontrol.php] コンストラクタ() { $form_str = $_POST['form']; $in_str = $_POST['key']; if(inだったら){ $view = new CFView(); $view->m_type = 'in'; $view->Write_HTML(); } } [cfview.php] メンバ変数 var $m_file = 'index.php'; var $m_type = false; var $m_line = null; フレームワーク使ってみろっていうのは賛成 疎結合にとかDRYにっていうのがだんだんわかってきた 理解したところで戻ってきて〜の方が結果的に早そう 俺はまだ勉強中だからそこまで行ってないけど >>192 > $view = new CFView(); > $view->m_type = 'in'; これみたいに、直接メンバにアクセスするのは構造的に良くないと聞いたことが あるよ。「データをやり取りするのは、インターフェースを通じて」という原則を 守るべきだと。 そうしなければ、CFViewクラスを改変する人は、そのクラスを使っている人の コードを考慮して、メンバの値や変数名を自由に変える事が出来なくなるから。 なので、私は、コンストラクタで値を渡しても良いし、コンストラクタで値を渡して いなければ、値を渡すためのインターフェースを使って渡すようにする仕様が 適当かなと思っている。 汚染されちゃうけどコンストラクタで全部の値渡すよりはましじゃないかなあ あとコンパイルするときに全部チェックしてくれる言語とそうじゃない言語ってのもある phpなんだしゆるーくやればいいじゃん なんていうと怒られるかw 今調べて知ったのだが、オーバーロードは PHP ではできないらしい。 だったら、コンストラクタで値を渡すよりも、インターフェースで値を 設定するような仕組みになるだろうね。 コンストラクタだと、一度値を設定したら、そのオブジェクトが破棄される まで、再度設定が出来なくなるから。 メンバ変数へのアクセスはsetter/getterを使う。これは議論の余地なし。 それを用意した上でコンストラクタに引数を渡すなら渡せば良い。 複雑で多くの設定をしなきゃならない時以外、 newした直後に使える状態になっている方が使いやすい。 > $view = new CFView(); > $view->m_type = 'in'; これをセットで書かなきゃならないなら、 > $view = new CFView('in'); と書きたい。 私は>>197 さんの意見に同意だ。 「このモジュールを使う場合、このように書いてくださいね。」 というコードは、なるべく少ない方がいいからね。 なので、とりあえず設定の値はコンストラクタにいれるという 設計で書いてみた。 とりあえず、フレームワークを使ってみろという話が出ているが、 具体的にどのフレームワークを使って、どんなプログラムを書いて みたらいいのか迷うなぁ。 とりあえずはこのあたりに載ってるものの、「和モノ」あたりからかな。 http://pc11.2ch.net/test/read.cgi/php/1197383840/3 フレームワーク自体の自作の話もいくつかあるみたいだ。 ttp://codezine.jp/a/article.aspx?aid=104 viewに渡すデータはセッタで渡したくならない? あとinなのかoutなのか分岐させるとしたらそれはコントローラ側の仕事なんじゃないかなと思うんだけど違うかな >>200 > viewに渡すデータはセッタで渡したくならない? 表示させるデータはセッタがいいだろうね。 > あとinなのかoutなのか分岐させるとしたらそれはコントローラ側の > 仕事なんじゃないかなと思うんだけど違うかな >>185 のソースがそれにあたるものだと思ってたけど。 if( ($form_str == "")or($form_str == "in") ){ 省略 }elseif($form_str == "out"){ 省略 } コントローラは、POSTしてきた値を見て、必要なModelやViewを 選択し、実行する役割なので、それを実現したつもり。 厳密にMVCを分けることは出来ない場合もあるということだけど、 CFControlクラスで、CFViewを使って表示する内容までもを 指定していする処理を書いていたのは間違いかな? 検索結果の表示や、データの更新の場合は、 Control→Model→View だけど、 ボタンを押した時の画面の展開のみの場合は、 Contol→View という流れとなり、Viewオブジェクトを 生成するクラスが異なるという処理でいいのかな? 「とりあえずはフレームワークを使ってみろ」という返事がきそうだけど、 各クラスの役割は以下のような感じでいいかな? Control ・POSTでデータを受け取り、その値に不正なものが無いかをチェック。 ・変なところからのアクセスではないかをチェック。 ・$_POST["Form"]の値をみて、それに必要な画面と処理を判断する。 Model ・SQLを発行し、データを受け取る。 ・データをViewクラスに渡す。 View ・フォームを表示する。(フォームごとにクラスを分けたほうがいいのかは迷うな) ・データを1件受け取り、tableタグでレイアウトを調整し、表示する。 自分なりに調べて見つけたPHPのサンプルを使った解説ページも 読むとwebアプリについて学べるのではないかと思っている。 やることが多くなったけれど、とりあえずは以下の3本だてで 勉強してみることになるのかな。 MVCに分けて、簡単なアプリを自作する。 (ログイン、メニュー、検索条件指定、検索結果、データ編集などの画面があるもの) 和モノフレームワークを使って学ぶ。 簡単なアプリを自作する。 http://pc11.2ch.net/test/read.cgi/php/1197383840/3 サンプルで理解! フォームデータの受け渡し ttp://www.atmarkit.co.jp/flinux/rensai/mysql5_03/mysql5_03a.html ちいたんのソース見てみたけれど、 class CObject ってあって、必ずそれが継承されて作られてるよね。 これの都合って何なんだろう。(メリットは何?) javaも.NETもこういう基本クラスがあるよね。 >>208 サンクス。 でも、オーバーロードが出来ない場合は逆に足かせになる可能性もあるね。 例えば、継承されているクラスが沢山ある状況でObjectクラスに メソッドを追加する場合とか。 喋るのはコントローラとモデル コントローラとビュー 基本的にはね 少ない数のクラスを書いたり読んだりする程度であれば、すぐに分かるのだが、 フレームワークレベルのクラス構造となると、その構成が全く分からなくなって 来るんだよなぁ。何かコツのようなものはあるのかな? 処理の内容を追いかけると、次々に別のクラスに処理を渡す構造になっていて、 最後はあっけない、みたいな感じだ。 フレームワークを作る場合のクラスの設計手法を身につけるなどしないと いけないのかも。 メンバに定義はしていないけれど、メソッドではその変数をエラーが 出ないように処理が書かれているっていう書き方は多いようだ。 そうしておけば、そのフレームワークを使う人は、クラスを継承して メンバに値を代入するだけで良い。 このサイト、説明は分かるのだが、具体的に作っているコードは MVCのうちどれにあたるのかがいまいちです。 ttp://www.stackasterisk.jp/tech/php/phpMvc01_01.jsp Result.php は、Viewにあたるものという解釈でいいんですよね? PHPでMVC関連のサイトを紹介で貼っておきます。 特集:第3回 PHPを思うままに操れるようになる「MVC」と「Smarty」 (1/4) ttp://www.itmedia.co.jp/enterprise/0402/19/epn01.html PHPでね、イベントドリブンなWEBフレームワークとか自作してみるといいかも。 例えば、サブミットボタンの処理ハンドラがオーバーライドで記述可能で そこでフォーム値をモデルに渡して処理させるみたいなやつ・・ 「POST」や「GET」とかローレベルの概念は全て隠蔽されてて フレームワークにイベント発生時のロジックだけ記述して終わりみたいなの・・・ そしてPHPであれこれ試行錯誤したあと、ASP.NETとか参考にするとね PHPでOOPするバカらしさに気付くかもしれない・・・OTL ASP.NET は、ちょっとだけやってみたことあるけど、概念的に違和感が あって、やらなくなったな。 ある程度Webアプリを学んだ事のある人には便利なんだろうけれど、 初めて学ぶ人には、ドキュメントが少なすぎだし、いきなりイベントドリブンで やるのはどうかと思った。 で、まずは、Webアプリの基礎をやるという意味合いでPerlをやってみた。 で、今はPHPをやっている。PHPそのものがOOPに完全な対応をしていない ので、これで大規模なアプリを組むことも無いかなと思っている。 対応したとしても、それからノウハウが出てくるので、さらに数年先になる。 でも、学ぶ時は、既存のモジュールを使って早くやるのよりも、モジュール なしの状態で、モジュールを作ってみる方がいいので、とりあえず今は PHPでOOPです。 >>217 多分、その違和感のある概念がOOPの本質だと思うよ。 そしてその概念は、洗礼された実装に触れることでしか 身につかないとも思うんだ。 初心者こそイベントドリブンを真っ先に学習したほうがいいよ。 最終的に、理解し易く安全な実装方法に結びつくと思うからね。 PHPでOOPで実装ってケースはありだとは思うけど、 概念は別で学習した方が効率的だと思うんだ。 OOPに取り付かれているとか良くわからんw 普通にプログラミングしていると使うだろ? switchに取り付かれているとかそういうレベルに聞こえるんだが。 MVCモデルでプログラミングする場合、Model から View へ処理を渡す経緯は、 どっちが正しいのかな? ・Control クラスのメソッド内で、Model クラスと View クラスのインスタンスを生成する。 Control クラスが、Model からデータを受け取り、View クラスへデータを渡し、 描画指示を出す。 ・Model クラスのメソッド内で、View クラスのインスタンスを生成する。 Model クラスが、Viewクラスへデータを渡し、描画指示を出す。 Control クラスは、View クラスを一切操作しない。 それとも、こういうところまでは理論的には定めていないので、 ケースバイケースであり、どちらがよいというものは無いということかな? PHPでイベントドリブンですか?(・∀・) …こんなのありました。^^ PHP イベントドリブン に一致する日本語のページ 約 10,600 件 ●PRADO http://www.pradoframework.com/wiki/index.php/Ja:What_is_PRADO >PRADO はコンポーネントベースかつイベントドリブンなウェブアプリケーションを開発するためのPHP5フレームワークです。 ●S2Prado.PHP5 http://labs.s2php5.jp/s2prado.php5 http://blog.xole.net/article.php?id=553 >S2Baseの方は待望のPRADO対応。 ●Piece Framework http://trac.piece-framework.com/piece-unity/wiki/ja/Start >Piece_Unityは、Visual BasicやDelphiのようなイベントドリブンなフレームワークです。 ●Delphi for PHP http://www.codegear.com/jp/products/delphi/php http://orz.qzlab.com/yamagw/index.php?Delphi%20for%20PHP%A4%CE%BB%C8%A4%A4%CA%FD >イベントドリブンなロジックの実装が容易に実現する。 ●Pharon http://pharon.lolipop.jp/ >最大の特徴は、wizard によりイベントドリブン型のスケルトンを自動作成することです。 インターネット越しにイベント処理をさせるのが、WEBプログラミングの特徴ですね。 イベントドリブンは、PHPよりもむしろFlash/Flexとかで使われる仕組みなのでしょうか? レガシーの中心でのOOP http://kaede.to/ ~canada/doc/2005/07/06/ >Webプログラミングにおいて、ブラウザとのやり取りがレガシー(古典的)なデータ交換に過ぎず、これがWebプログラミングを難しくしている >Webは1ページごとに毎回セッションが起動し、ドキュメントを表示するとすぐ終了する。 >オブジェクト指向プログラミングにおける利点の1つであるイベントドリブンなプログラミングは不可能だ。 >何しろ1セッションに1イベントしか発生しないのだから。 >と同時にセッション状態を保存する必要も出てくる。 http://www.adobe.com/jp/devnet/flex/articles/framework_beta_print.html >インタラクティブ性に優れたイベントドリブンなインタフェイス http://www.atmarkit.co.jp/fwcr/rensai/flex203/01.html >イベント処理によってアプリケーションを構築する手法はイベント駆動型(イベントドリブン)と呼ばれます。 http://www.azul.systems-noel.jp/item_9.html >Flex2はイベントドリブンなので、ビューに起こったイベントをコントローラのリスナでキャッチするように意識すれば、MVCの分離はきれいにできるようになっています。 >なんかほんとにJavaのSwingを使ってるような気分になりますね。 http://bitmap.dyndns.org/blog/archives/001215.html >イベントドリブンモデルには、主に以下の 4 つのオブジェクトが登場する。 >>220 >・Control クラスのメソッド内で、Model クラスと View クラスのインスタンスを生成する。 こっちの方が、Controlにまとまっている分だけスッキリしており、分かりやすいコードになるんじゃないでしょうか? >>224 レスありがとうございます。 1番目の方にすると、Modelクラスから取得したデータを Viewクラスに渡すことになるので、その分余計にメモリや CPUを消費してしまうのでは、と心配になって聞いてみましたが、 考えてみると、コードの見易さなどを優先するのがOOPですので、 そちらの方がいいですね。 でも、フレームワークのソースなどを見ていると、 各クラスが、メンバに、別のクラスへのリファレンスを持ってたり するので、もっと理論に従った組み方があるのかも、と思っています。 >>184 ファイル:全部で8つ。index.phpを実行する。 抽象クラスと具象クラスに実装を分けてみました。 csv.txt(※前回と同じ) index.php cfcontrol.php アブストラクトとして実装 cfview.php cfmodel.php コンクリートとして実装 data_model.php index_view.php output_view.php [config.php] <?php // 実際の処理を行うスクリプトをインクルード include("./index_view.php"); include("./output_view.php"); include("./data_model.php"); // 最初に呼ばれるビューのプレフィックス設定 define ('INDEX_VIEW_PREFIX', "Index"); // モデルクラスのプレフィックス設定 define ('MODEL_PREFIX', "Data"); ?> [index.php] <?php include("./cfcontrol.php"); $view_key = $_POST["view_key"]; $data = $_POST["data"]; $app = new CFControl($view_key, $data); $app->Execute(); ?> [cfmodel.php] <?php class CFModel { var $file_name; // 読み込むファイル名 function CFModel() {}// コンストラクタ function Execute($param) // パブリックメソッド { return $this->_OnExecute($param); } function _OnExecute($param) // 仮想メソッド { trigger_error('オーバーライドしてね。', E_USER_ERROR); } } ?> [cfview.php] <?php class CFView { var $file_name; // POSTするファイル名 function CFView() {} // コンストラクタ function Execute($param) // パブリックメソッド { return $this->_OnExecute($param); } function _OnExecute($param) // 仮想メソッド { trigger_error('オーバーライドしてね。', E_USER_ERROR); } } ?> [cfcontrol.php] <?php include("./cfview.php"); include("./cfmodel.php"); include("./config.php"); class CFControl { var $_view_key; // 呼び出すビューのプレフィックス var $_data; // モデルに渡すデータ function CFControl($view_key, $data) // コンストラクタ { $this->_view_key = $view_key; $this->_data = $data; } function Execute() // パブリックメソッド { // モデルオブジェクト動的生成 $model_class_name = MODEL_PREFIX . 'Model'; $model = new $model_class_name(); $param = $model->Execute($this->_data); // ビューオブジェクト動的生成 $view_key = $this->_view_key; if ($view_key == "") $view_key = INDEX_VIEW_PREFIX; $view_class_name = $view_key . 'View'; $form = new $view_class_name(); $form->Execute($param); } } ?> [data_model.php] <?php class DataModel extends CFModel { function DataModel() // コンストラクタで取得先のファイル設定 { $this->file_name = 'csv.txt'; } function _OnExecute($param) // オーバーライドメソッド { $INFILE = fopen($this->file_name,"r"); $data = fgets($INFILE, 1024); fclose($INFILE); $data = $data . ", " . $param; return $data; } } ?> [index_view.php] <?php class IndexView extends CFView { function IndexView() // コンストラクタでPOST先のファイル設定 { $this->file_name = 'index.php'; } function _OnExecute($param) // オーバーライドメソッド { echo "<html><body>"; echo '<form method="POST" action="' . $this->file_name . '">'; echo '<input type="hidden" name="view_key" value="Output">'; echo '<input type="text" name="data"><input type="submit" value="送信">'; echo "</form></body></html>"; } } ?> [output_view.php] <?php class OutputView extends CFView { function OutputView() // コンストラクタでPOST先のファイル設定 { $this->file_name = 'index.php'; } function _OnExecute($param) // オーバーライドメソッド { echo "<html><body>"; echo '<form method="POST" action="' . $this->file_name . '">'; echo '<input type="hidden" name="form" value="Index">'; echo "$param<br>"; echo '<input type="submit" value="戻る"></form></body></html>'; } } ?> >>226-232 サンプルソースありがとうございます。 抽象クラスの書き方に慣れてますね。私はこのあたりを しっかりとやってなかったのでちょっと苦手です。 ま、しっかりと勉強していきたいと思います。(^^; ソースを読んでいて、1点気になったので質問をしたいのですが、 class CFView と class CFModel において、以下のように パブリックメソッドと仮想メソッドを作り、パブリックメソッドから 仮想メソッドを実行する形式にソースを書いた理由は何でしょうか? 出来ましたら、この設計にした意図を教えていただきたいと思います。 function Execute($param) // パブリックメソッド { return $this->_OnExecute($param); } function _OnExecute($param) // 仮想メソッド { trigger_error('オーバーライドしてね。', E_USER_ERROR); } >>218 レスありがとうございます。 イベントドリブンそのものは、VBでWindowsアプリを組んでやったことがあるので すぐに入れたのですが、Webアプリを作る際、イベントドリブンでしかやった事が 無いというのは致命的だと思ったので、PerlやPHPでやってみています。 (ASP.NETは、便利ではあるが、IISを使えとか、.NET Frameworkを使えとか 非常に限定される。) 構造化プログラミングで、あまり命名規則を考えずにプログラムをしていると、 グローバル変数や関数が多くなった時、その把握が出来なくなったりする わけなのですが、そういう苦労する体験をした後、OOPを習うと、その便利な部分が 見えてくるわけです。OOPは経験による結論的な理論だな、と理解できるわけです。 その理解のために、とりあえず、苦労をする方法(PHP で 0 から OOP)で やってみているのです。 今は、このように考えています。 >>233 PHP4では全てパブリックだけど例えばC#では以下の実装になるんだ public object Execute(object parpam) protected virtual object _OnExecute(object parpam) CFControlから_OnExecuteメソッドを隠蔽する意図なんだよ。 _OnExecuteはCFViewやCFModelのサブクラスにだけ見えれば十分なんだ。 >>235 暖かいですねぇ。 >>236 なるほど。ありがとう。 ソースを読んでいて気になった点がありますので、質問させていただきます。 includeの構成についてです。まず、各ファイルに書かれているincludeの部分をまとめます。 [index.php] include("./cfcontrol.php"); [cfcontrol.php] include("./cfview.php"); include("./cfmodel.php"); include("./config.php"); [config.php] // 実際の処理を行うスクリプトをインクルード include("./index_view.php"); include("./output_view.php"); include("./data_model.php"); これは、MVCフレームワークは、以下の3つのファイルであり、 [cfcontrol.php][cfmodel.php][cfview.php] それを拡張する形で、残りの6つのファイルを付け加えた形 なので、このようなincludeの構成ということでよろしいのでしょうか。 includeをばらばらとさせるよりも、以下のように整理したほうが となんとなく思ったりもしたのです。 [index.php] include("./config.php"); [config.php] include("./cfcontrol.php"); include("./cfview.php"); include("./cfmodel.php"); include("./index_view.php"); include("./output_view.php"); include("./data_model.php"); MVC?な俺にはここが一番わかりやすかった 実例コードが載ってるのがいい PHPでMVC第1回:前編 ttp://www.stackasterisk.jp/tech/php/phpMvc01_01.jsp ソースコードをちょっとだけ改変したものを作ってみた。 メモとかを残していく都合もあると思ったから、HP解説してみた。 ttp://www.geocities.jp/narutobakijp2/ 本当は、>>1 さんがソースの管理とかもしてくれたりしたら、うれしいw >>243 CFViewクラスに具体的な実装をしちゃダメなんだよ。 そもそもHTMLのフォーム処理とかは、あとでPEARとか使えばいい。 サブクラスをうまく呼び出す仕組みだけを実装していくんだ。 >>244 > サブクラスをうまく呼び出す仕組みだけを実装していくんだ。 kwsk >>246 構造化プログラミングはルーチンを呼ぶ方向で実装すると思うけど OOPではルーチンに呼ばれる方向で実装して行く感じだよ。 大枠の骨組みだけを抽象クラスで作成して、処理は具象クラスで行うんだ。 インターフェイスさえ同じならあとで個別にパーツを交換出来たりするからね。 だったら基底クラスのメソッドなんて数個で十分じゃないかと思うんだ。 やたら複雑でよくばりな機能のクラスなんて、再利用の価値がないからね。 read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる