質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

6回答

4523閲覧

オブジェクト指向の書き換えについて

newyee

総合スコア213

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

0クリップ

投稿2019/03/13 09:55

現在PHPの学習をしているものです。学習を進めていく内に、簡易な掲示板は作れるようになったのですが、それをオブジェクト指向を用いて書き換えようと思った際に、どの機能をどのようなクラスにまとめれば良いか、などといったことが分からず、どこから手をつけて良いか分からない状態です。オブジェクト指向につきましては、参考書で勉強したり、ネットの記事を見るなどして、調べたりしたのですが、実際に現状自分のコードをどのように、オブジェクト指向に書き換えたらよいのかが分からない為、ご助言頂きたくご質問させていただきました。
以下は、自分の作成した掲示板のコードになります。
下記のコードは、掲示板のコメント投稿画面、及びコメント一覧画面を表示する、「bbs.php」です。

php

1<?php 2include 'includes/login.php'; 3 error_reporting(E_ALL); 4 ini_set("display_errors",1); 5 //1ページに表示されるコメントの数 6 $num = 10; 7 $user = 'root'; 8 $password = ''; 9 $dsn = 'mysql:host=localhost;dbname=online_bbs;charset=utf8'; 10 //ページ数が指定されている時 11 $page = 0; 12 if(isset($_GET['page']) && $_GET['page'] > 0){ 13 $page = intval($_GET['page']) -1; 14 15 } 16 17 try{ 18 $dbh = new PDO($dsn,$user,$password); 19 $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); 20 $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); 21 22 $stmt = $dbh->prepare("SELECT id,name,title,comment,created_at,password FROM post ORDER BY created_at DESC LIMIT 23 :page,:num"); 24 //パラメーターを割り当て 25 $page = $page * $num; 26 27 $stmt->bindValue(':page',$page,PDO::PARAM_INT); 28 $stmt->bindValue(':num',$num,PDO::PARAM_INT); 29 $stmt->execute(); 30 31 }catch(PDOException $e){ 32 echo "エラー: " . $e->getMessage(); 33 } 34 35 36 37?> 38 39 <html> 40 <head> 41 <title>交流サイト:掲示板</title> 42 <meta charset="utf-8"> 43 </head> 44 <body> 45 <h1>掲示板</h1> 46 <form action="write.php" method="post"> 47 <p>名前:<input type="text" name="name" value="<?php echo isset($_COOKIE['name']) ? $_COOKIE['name'] : '' ?>"></p> 48 <p>タイトル:<input type="text" name="title" size="60"></p> 49 <textarea name="comment"></textarea> 50 <p>削除パスワード(数字4桁):<input type="text" name="pass"> 51 <input type="submit" name="submit" value="書き込む"> 52 <input type="hidden" name="token" value="<?php echo password_hash(session_id(),PASSWORD_DEFAULT); ?>"> 53 </form> 54 <hr> 55 <?php 56 while($row = $stmt->fetch()): 57 58 $title = $row['title'] ? $row['title'] : '(無題)'; 59 ?> 60 <p>名前:<?php echo $row['name'] ?></p> 61 <p>タイトル:<?php echo $title ?></p> 62 <p><?php echo nl2br(htmlspecialchars($row['comment'],ENT_QUOTES,'UTF-8'),false) ?></p> 63 <p><?php echo $row['created_at'] ?></p> 64 <form action="delete.php" method="post"> 65 <input type="hidden" name="id" value="<?php echo $row['id']; ?>"> 66 削除パスワード:<input type="password" name="pass"> 67 <input type="submit" value="削除"> 68 <input type="hidden" name="token" value="<?php echo password_hash(session_id(),PASSWORD_DEFAULT); ?>"> 69 </form> 70 <?php 71 endwhile; 72 //ページ数の表示 73 try{ 74 $stmt = $dbh->prepare("SELECT COUNT(*) FROM post"); 75 $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); 76 $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); 77 78 //クエリの実行 79 $stmt->execute(); 80 81 }catch(PDOException $e){ 82 echo "エラー:" . $e->getMessage(); 83 } 84 /** 85 * コメントの件数を取得 86 *fetchColumn関数で 最初のレコードを取り出し、最初の列「id」のデータを取り出す 87 * idは降順に設定されているため、コメントの件数が分かる 88 * */ 89 $comments = $stmt->fetchColumn(); 90 $max_page = ceil($comments / $num); 91 echo '<p>'; 92 for($i = 1; $i <= $max_page; $i++){ 93 echo '<a href="bbs.php?page=' . $i .'">' . $i . 94 '</a>&nbsp;'; 95 } 96 echo '</p>'; 97 ?> 98 99 </body> 100 </html>

下記はコメントを投稿すると、名前やパスワードのバリデーションチェックを行い、データベースへ情報を記録する為の、「write.php」です。

<?php include 'includes/login.php'; error_reporting(E_ALL); ini_set('display_errors', '1'); $err_message = []; if(!empty($_POST)){ $title = filter_input(INPUT_POST,'title',FILTER_SANITIZE_SPECIAL_CHARS); $token = filter_input(INPUT_POST,'token',FILTER_SANITIZE_SPECIAL_CHARS); if(!$name = filter_input(INPUT_POST,'name',FILTER_SANITIZE_SPECIAL_CHARS)){ $err_message[] = '名前が入力されていません'; } if(!$pass = filter_input(INPUT_POST,'pass',FILTER_SANITIZE_SPECIAL_CHARS)){ $err_message[] = 'パスワードが入力されていません'; } if(!$comment = filter_input(INPUT_POST,'comment',FILTER_SANITIZE_SPECIAL_CHARS)){ $err_message[] = 'コメントが入力されていません'; } } if(!preg_match("/^[0-9]{4}$/",$pass)){ $err_message[] = 'パスワードを4文字で入力してください'; } $pass = password_hash($pass,PASSWORD_DEFAULT); if(count($err_message) === 0){ //CSRF対策 if(!password_verify(session_id(),$token)){ header('Location:bbs.php'); exit(); } setcookie('name',$name,time() + 60 * 60 * 24 * 30); //データベースに接続 $dsn = 'mysql:host=localhost;dbname=online_bbs;charset=utf8'; $user = 'root'; $password = ''; try{ $db = new PDO($dsn,$user,$password); $db->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); $stmt = $db->prepare(" INSERT INTO post (name,title,comment,created_at,password) VALUES (:name, :title, :comment, now(), :pass)"); $stmt->bindValue(':name',$name,PDO::PARAM_STR); $stmt->bindValue(':title',$title,PDO::PARAM_STR); $stmt->bindValue(':comment',$comment,PDO::PARAM_STR); $stmt->bindValue(':pass',$pass,PDO::PARAM_STR); $stmt->execute(); }catch(PDOException $e){ die ('エラー:' . $e->getMessage()); } } ?> <html> <head> <meta charset="utf-8"> <title>Page Title</title> </head> <body> <?php echo implode("<br />",$err_message); ?> <h4>投稿に成功しました。</h4> <p><a href="bbs.php">戻る</a> </body> </html>

下記はコメントの削除パスワードを入力すると、データベースから情報を削除する為の、「delete.php」です。

php

1<?php 2 include 'includes/login.php'; 3 error_reporting(E_ALL); 4 ini_set("display_errors",1); 5 6 //エラーメッセージ 7 $err_msg = []; 8 9 if(!empty($_POST)){ 10 11 if(!$pass = filter_input(INPUT_POST,'pass',FILTER_SANITIZE_SPECIAL_CHARS)){ 12 13 $err_msg[] = 'パスワードが入力されていません。'; 14 15 } 16 17 18 $token = filter_input(INPUT_POST,'token',FILTER_SANITIZE_SPECIAL_CHARS); 19 20 //POSTされたIDを取得 21 $id = filter_input(INPUT_POST,'id',FILTER_SANITIZE_SPECIAL_CHARS); 22 $id = intval($id); 23 24 } 25 26 //CRLF対策 27 if(!password_verify(session_id(),$token)){ 28 header('Location:bbs.php'); 29 exit(); 30 }; 31 32 if(count($err_msg) === 0){ 33 34 35 $dsn = 'mysql:host=localhost;dbname=online_bbs;charset=utf8'; 36 $user = 'root'; 37 $password = ''; 38 39 try{ 40 $dbh = new PDO($dsn,$user,$password); 41 $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); 42 $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); 43 $stmt = $dbh->prepare(" 44 SELECT password FROM post where id = :id 45 "); 46 47 $stmt->bindValue(':id',$id,PDO::PARAM_INT); 48 49 $stmt->execute(); 50 51 $db_pass = $stmt->fetch(); 52 53 if(!password_verify($pass,$db_pass['password'])){ 54 55 die('パスワードが違います'); 56 } 57 58 $stmt = $dbh->prepare(" 59 DELETE FROM post WHERE id = :id 60 "); 61 62 $stmt->bindValue(':id',$id,PDO::PARAM_INT); 63 $stmt->execute(); 64 65 }catch(PDOException $e){ 66 67 die( "エラー:" . $e->getMessage()); 68 } 69 70 header('Location: bbs.php'); 71 exit(); 72 73 } 74 75?>

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/03/13 10:51

結局アドバイス通りにしないんですね。それならあまり前向きなコメントしないでもらえますか? 自分の現在地とやるべきことを見誤り過ぎです。 まさか何も前準備もなくこんな丸投げをするとは思わなかった。
newyee

2019/03/13 10:57

いえ...mtsさんにアドバイス頂いた通り、色々調べてみたのですが、具体的にどこの部分をどのようにまとめればよいか...という部分が、質問本文にも記載させて頂いたのですが、検討が付かない状態でして... オブジェクト指向の概念的なものは理解できたのですが、実際にどうすればよいかが分からなかったんですよね...
m.ts10806

2019/03/13 11:15

1段1段あがるべき階段を2段3段どころか200段くらい飛ばしてるし、それが何度言ってもわからないようなら無理です。 簡単に動かして動かなくて試行錯誤してようやく継承なり抽象化なりなんなりが見えてくるまでも数ヶ月かかるはずのものをたった数日で理解できたとか笑わせますね。舐めすぎです。 試してみてください。オブジェクト指向関係ないくてもあってもいいですがteratailにあがってるphpの質問に回答できますか? システムの本質は問題解決です。オブジェクト指向きちんと理解できてる人の質問じゃないですよ。
退会済みユーザー

退会済みユーザー

2019/03/13 11:24

つーか、リプレイスにこだわる理由はなんでしょー? とくにないなら、1から作り直しちゃダメなんですかね?
m.ts10806

2019/03/13 11:29

magendaさん 私は1から作り直せと言ったつもりなんですよ…つか、1から作り直さないとダメだと気づかないとダメですね。
退会済みユーザー

退会済みユーザー

2019/03/13 11:45 編集

To: mts10806 さん https://teratail.com/questions/178928#reply-266190 のコメント見るかぎり、mtsさんは"1から作り直せ"という話をしてるが、newyeeさんはそれを"修正"だと捉えている感じがする 話が食い違ってるのはそこなのかな?しらんけど
m.ts10806

2019/03/13 11:51

magendaさん 考え方の方向性とかご自身の概念は修正してもらいたいですけどね。
退会済みユーザー

退会済みユーザー

2019/03/13 11:58

To: mts10806 さん ともあれ、質問者さんにはぜひがんばっていただきたいですねー あとはまあ、teratailは問題解決の場とはいえ、質問者自身の問題を解決する場所ではないですし、ちょうどよい加減で見切りをつけたほうが有意義だとおもいますんで、ほどほどに・・・
m.ts10806

2019/03/13 12:12

そうですね。 ただ、この内容にまともに答えるのは回答欄じゃ無理なので、 いったん原点に立ち返ってもらうしかないように思います。
newyee

2019/03/13 12:31

mtsさんに言われた掲示板は、参考書にて学習したものを一度自分で作りなおしたものです。 mtsさんがコメントされたアドバイスには次のステップとして、オブジェクト指向を取り入れることとあったので、そのようにしていこうと思っての質問でした。 自分の知識が浅いというのもあるかもしれませんが、自分の中では、クラスを作り関数切り分けをするという部分もオブジェクト指向の一種だと認識していまして、まず関数切り分けするにも、どの部分を関数切り分けして良いか分からない、という所があったので、質問させてもらいました。 オブジェクト指向という言葉を完全に理解していないにも関わらず、安易に使ってしまったという点に関しましては、混乱させてしまった部分はあるかもしれませんが、「考え方の方向性とかご自身の概念は修正してもらいたいですけどね」こういったことを書かれるのは、人としてどうかと思いますけどね。
m.ts10806

2019/03/13 12:57 編集

そこはご自由に思ったら結構かと。自身が如何に人のアドバイスをちゃんと聞き入れてないか気づいてもらえたらそれで良かったのですが、そこにいかないなら仕方ないですね。 ちなみにですが、私があなたの掲示板プログラムを1から、オブジェクト指向きちんとしっかり盛り込んで作ろうとした場合、1週間はかかると見てます(多少大袈裟だけどそれでもまあ1日2日でどうにかできるものではない。フレームワークを1から作るつもりですから)。既に回答がついているようにオブジェクト指向のメリット皆無な簡易掲示板システムですら、しっかり作りこむとあなたが作った程度のものでもそれなりにかかるものです。 それはともかく、何とか1段ずつのぼってもらおうとそれなりに苦心してアドバイスしてきたつもりでしたが、無駄に終わることが分かったので、私はこれで。あとは勝手にしてください。
tamoto

2019/03/14 03:11

回答ではないのでここに書きます。 この質問は、極端なたとえで表現すると、「COBOLでプログラムを書きました!これをrubyに直すとどうなりますか?rubyは調べたので知ってます」みたいなものです。そんなもの「全部書き直してください」としか言えないですし、丸投げ質問でしかないです。まずは調べた内容に則って書いてみて、それでわからなかった部分を質問するのなら良いです。単なる手続き処理とオブジェクト指向は「全く異なる概念の元で書かれるもの」なので、ただ翻訳するということはできないことを「調べた」のであれば理解しているはずですよ。
newyee

2019/03/14 03:53 編集

確かに、オブジェクト指向はすべて理解はできていなかったです。すべて書き直してくださいとの意味で、質問させて貰った訳でなく、どこから手をつけてよいか分からなかった為、ご助言頂ければと思い質問させてもらいました。
guest

回答6

0

既存のコードを無理にオブジェクト指向にするというのはかなり無理がありますね。
掲示板のように小さなものだと、オブジェクト指向のメリットは皆無だし。
まずは、ベタ書きしている処理を関数で切り分けしたらよいかと思います。

投稿2019/03/13 10:44

編集2019/03/13 12:59
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/03/13 11:16

それ私の振りなんですよね… 1段1段あがっていこうねって話をしてたはずですけど、どこをどう間違ったか。phpマニュアルも結局敬遠してる雰囲気ありますし。
退会済みユーザー

退会済みユーザー

2019/03/13 12:59 編集

この掲示板の仕様だと、オブジェクトにすると言っても、「投稿」オブジェクトが無理やりできるだけで、オブジェクト指向の教材にしてはシンプルすぎる。 function を使って、ビジネスロジックとビューを切り分けるところからですね。 これをオブジェクト指向にするのは、上級者でも頭を悩ませるでしょうね。
m.ts10806

2019/03/13 12:53

はい、そこなんですよね。login.phpが何者かはさておき、 まさかべた書きからいきなりクラスに移ろうとするとは思ってませんでした。 私のオペミスもありますが、さすがに質問サイトでできることって少ないですからね。
退会済みユーザー

退会済みユーザー

2019/03/13 12:54

まあ、春休み中の学生さんなんでしょうかね…
退会済みユーザー

退会済みユーザー

2019/03/13 13:05

@newyee さん オブジェクト指向って、まず作りたいものは何か、それを作ることによって何を実現したいのか、という「要求」があって、それを「要件」に落とし込む(つまり設計の)ときに意識すべきことです。 すでにあるコードをグレードアップする段階のことではないのですよ。 すでにあるコードをスマートにする行為はリファクタリングと言います。
guest

0

何かしらのフレームワークを使って、それに則って構築してみる、というのがわかりやすいかなと思います。

PHPでシンプルなフレームワークとしては、CodeIgniterなどがあります。

投稿2019/03/13 11:02

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2019/03/13 13:08

確かに、自分でゼロから作って勉強するより、ある程度は出来合いのものを触るところから始めた方が、いろいろな概念はつかみやすいのかもしれません。
newyee

2019/03/14 02:33

ご回答ありがとうございます。 現状、オブジェクト指向を学習するにはまだ早かったということも、色々な方にご回答いただき分かりましたし、取り敢えず、基礎的なことをやり直し、ある程度身に付きましたら、フレームワークにも挑戦していこうと思います...
guest

0

まだまだ、他人の書いたソースコードを読んで学習するフェーズなんだと思いますよ。
本1冊読んだだけでマスターできますか? 世の中にはもっといっぱい教材がありますよ。
掲示板を作れただけでマスターできたつもりですか? 簡易掲示板をもっと機能充実にするために改良することも学習の一つです。
自分の中からコードが湧き出してこないということは、学習が足りていない証拠です。

コードの読み方、もあると思います。
手を動かさずに黙読するだけでは理解できないこともあります。
写経(本などのソースコードを実際にタイプして動かす)を馬鹿にする人もいますが
タイプミスしたり、あるいは本のミスで間違いだったりして、
動かない場合もあって、それを動くように直せるようになったら一皮むけた自分になります。
(本のミスがないか正誤表などをネットで確認するのも大事なことです。)

最短ルートで習得できるなら苦労しないし、方法がわかったら教えてくださいね。(こっそり。)

投稿2019/03/13 12:41

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/03/13 12:41

説教臭くなってしまって、気分を悪くしたらごめんなさい
newyee

2019/03/14 02:25

いえいえ、ご助言頂きましてありがとうございます。 確かに、学習が足りていない証拠ですよね... 自分でも努力が足りていないとは思いますし、もっといろいろな教材などから、コードを写し、またそれを、書き直す、といったことを身に付くまではやっていこうと思います。 現状の掲示板のコードに関しましては、「オブジェクト指向」の意味を理解できていなかったといのもありますし、取り敢えず、まずは「関数切り出し」を実装できるように学習していこうと思います。
guest

0

別回答に書いたコメントそのまま再掲します。無視されたようなので。
これ聞かなかったら今後どうなろうと知りません。(元々ユーザー同士は他人なので無責任だし知ったこっちゃないわけですけど、アドバイス聞き入れないならそりゃ余計にね)


何が出来るかきちんと知らない内から「まとめる」ことを考えるのは早計ですよ。毎日何かしら考えたとしても「まとめる」ことを考えるまでに数年かかると言っていいです。
私でもそこまで全て把握しきれてるわけではないですし(一応、自分でフレームワークのようなものは作れますが、日々最適化を目指してます)


まともに関数切り出しで共通化もできてないのにロジックもままならないのにオブジェクト指向なんて早計すぎますね。

数年かかるって書いたじゃないですか。
なんで1日くらいで出来る気になれるのか理解に苦しみますね。


ちなみに、
私もinclude、継承地獄から脱却するために
オートローダへの移行をやったときは結局ほぼ全て作り直しました。
名前空間を適切につける必要があったしphpのバージョンも上がってたから
それに合った書き方をしたかったし、実現のためにはディレクトリ構成もかえる必要もありました。
流用したのはほんの一部ですね。

オブジェクト指向からオブジェクト指向に移行するときですら
作り直しなのに、無からオブジェクト指向で作り直しにならないはずがないですね。
今のコードは全部捨てるつもりで、残すのはDBのデータだけとかですよ。

投稿2019/03/13 10:58

編集2019/03/13 11:42
m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

newyee

2019/03/13 11:13

まとめるとお伝えしたことについてなのですが、自分では、オブジェクト指向というものは、クラスなどを作り、まとめることだと認識しており、そのように伝えてしまいました... 自分の中ではクラスを作り関数切り出しを行うことも、オブジェクト指向設計に入るのではないかと思うのですが、そういったことではないのでしょうか? うまく、自分がどの程度理解できているかを、お伝えできなかったことや、適当にまとめるなどといってすみませんでした...
m.ts10806

2019/03/13 11:36 編集

私のコメント全部読み直して出直してください。 質問してる暇があったらHello Worldからやり直してください。 それもechoで出すだけじゃなく、オブジェクト指向をふんだんに使って。 その様子だと継承すら理解してませんよね。意味、効果的な使い方。アクセス修飾子、適切に振り分けられますか?インターフェイス、使い分けできますか? モデル、コントローラ 適切に設置できますか? 名前空間、オートローダはどうですか? など。 これまでifやforなどをやってきたのと同じように基本があり、適材適所の使い方を覚え、ロジックから落とし込む必要がありますよ。 それができてようやく「設計」です。機能をどうまとめたら効果的になるのか、速度やメモリを担保できるようになるのか、を考えられる段階になります。 これでもだいぶ端折ってます。 今、あなたはどうでしょうか? まだ気づきませんか? あなたは人間の成長過程で言うと寝返りも自分の意思では思うようにできないあかちゃんレベルです。 やろうとしていることは、自ら仕事を遂行する行為です(よくて就活で自分に合う職場を探すくらい)。 寝返りもままならない、歩けさえできないのに手を出せると思いますか?マニュアルさえまともに使えないのに。 それだけの段階を省略すればできなくて当然。
newyee

2019/03/13 11:42

継承の意味だったり、インターフェースやモデル、コントローラなどの単語の意味は参考書などで、学習しましたので、知ってはいますが、実際に、自分のコードでそれらを取り入れようとした際に、どのように組み込めばよいのかが分からないです。 恐らくですがmtsさんの指摘されていることをすべて理解できていたら、ここに質問はしないと思います。
m.ts10806

2019/03/13 11:49

知ってるうちに入らないですよそれ。 ifとかforとかどうやって使えるようになりました?というか、今でもちゃんと使えてるって言えますか? 適切に的確に組み込める自信ありますか? 「学習したから知ってる」は、プログラミングの世界では無知と同です。使えないなら知らないと同じ。 使えるようになるにはコードを書いて書いてマニュアル読んでまた書いて失敗して、を繰り返すしかない。 どこまでやりました?たった数日で知った気にならないでください。 あらゆるエンジニアを舐めすぎです。
guest

0

隠蔽

PHP に慣れ親しんだ方はオブジェクト指向を理解しやすいのではないかと思います。

なぜなら PHP はバックエンドで使われることが多く、そこでは「大事なデータをユーザーに直接触らせることなく、抽象化された API によってのみデータを取得・設定できる」ことが求められているからです。

これはオブジェクト指向の「隠蔽」にほかなりません。

つまり、API を公開していること自体がオブジェクト指向と言うことができます。

ポリモーフィズムと継承

オブジェクト志向にはもう一つ(あるいは二つ)重要な概念があります。
それは「ポリモーフィズム」と「継承」です。

ポリモーフィズムは、あるオブジェクトが別のオブジェクトとして振る舞うことで、継承とは、ポリモーフィズムを容易に行うために親オブジェクト(基本オブジェクト)と互換性のある派生オブジェクトを作ることです。

掲示板に当てはめて言うなら、それぞれの環境に合わせて別のコードを書いても、それらが全て同じ API を用いて同じようにアクセスできるならポリモーフィズムと言うことができます。クライアントにとっては、掲示板 A と掲示板 B への同じ記事の書き込みをループで行うことができます。

コードの再利用

さて、ではオブジェクト指向を用いて掲示板を作るにはどうすればいいかということですが、複数の環境にそれぞれ同じ API を実装するときには、それら全てに共通するコードと、環境に合わせて書き換えなければならないコードがあるはずです。それらをごちゃ混ぜに使っていたのでは、保守が大変面倒なことになります。

そこで、共通するコードをそこから切り分ける必要が出てきます。この共通する部分が可能な限り大きく、環境毎のコードが可能な限り小さくなるよう工夫しましょう。

この共通するコードと、そこから呼び出されて環境の差を埋めるコードの切り分けができれば目的は達成します。

結論

現在のコードは、ある一つの環境に特化したものです。

例えば、データベースやユーザー ID やパスワードが固定で、コードに直接埋め込まれています。

また、ユーザーに表示される HTML も固定です。

これを一般化し、ファイルを一つ置き換えるだけでどのような環境でも対応できるようになればオブジェクト指向で作った掲示板と言えるでしょう。

そしてそれを実現するためには、PHP におけるクラスやオブジェクトについて熟知し、それを使いこなして正しく設計することが必要になります。

コード視点で言えば最初から、つまり設計からやり直してください。プログラマー視点で言えば、オブジェクト指向の基礎から勉強して設計してください。

投稿2019/03/14 03:45

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/03/14 04:03 編集

私が作るのであれば、まず root パスワードやデータベースの情報を保持する Settings クラスと、引数に従って HTML や CSS を作成する UI クラスを作ります。 他の関数からこれらの情報が必要になった時には、必ず該当するオブジェクトを作ってそこから取得・設定するようにし、ハードコーディングや多重設定は認めません。 よって、この二つのクラスを取り替えれば環境に合わせて好きな見た目の掲示板が作れるということです。
newyee

2019/03/14 05:38

ご丁寧にありがとうございます。 現状、自分にはご回答頂いた点に関しまして理解できない部分も多々ありますので、もう一度、オブジェクト指向につきまして、きちんと勉強してみたいと思います。 そのうえで、理解できない部分があった場合には、ご回答頂いた点に関しまして、ご質問させて頂くことがあるかもしれないですが、その際はご返信頂けましたら幸いです...
guest

0

ベストアンサー

参考までに。

  • bbs_class.php

php

1<?php 2 3class Bbs 4{ 5 private $dbh; 6 7 private $num; 8 9 protected function __construct($dbh, $num) 10 { 11 $this->dbh = $dbh; 12 $this->num = $num; 13 } 14 15 public static function create($dsn, $user, $password, $num) 16 { 17 $dbh = new PDO($dsn, $user, $password); 18 $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); 19 $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); 20 return new static($dbh, $num); 21 } 22 23 public function comments($page) 24 { 25 $stmt = $this->dbh->prepare("SELECT id,name,title,comment,created_at,password FROM post ORDER BY created_at DESC LIMIT :page,:num"); 26 $page = $page * $this->num; 27 $stmt->bindValue(':page', $page, PDO::PARAM_INT); 28 $stmt->bindValue(':num', $this->num, PDO::PARAM_INT); 29 $stmt->execute(); 30 while ($row = $stmt->fetch()) { 31 yield $row; 32 } 33 } 34 35 public function numberOfPages() 36 { 37 $stmt = $this->dbh->prepare("SELECT COUNT(*) FROM post"); 38 $stmt->execute(); 39 $comments = $stmt->fetchColumn(); 40 return ceil($comments / $this->num); 41 } 42 43 public function write($name, $title, $comment, $pass) 44 { 45 $stmt = $this->dbh->prepare("INSERT INTO post (name,title,comment,created_at,password) VALUES (:name, :title, :comment, now(), :pass)"); 46 $stmt->bindValue(':name',$name,PDO::PARAM_STR); 47 $stmt->bindValue(':title',$title,PDO::PARAM_STR); 48 $stmt->bindValue(':comment',$comment,PDO::PARAM_STR); 49 $stmt->bindValue(':pass',$pass,PDO::PARAM_STR); 50 $stmt->execute(); 51 } 52 53 public function delete($id, $pass) 54 { 55 $stmt = $this->dbh->prepare("SELECT password FROM post where id = :id"); 56 $stmt->bindValue(':id', $id, PDO::PARAM_INT); 57 $stmt->execute(); 58 $db_pass = $stmt->fetch(); 59 if(!password_verify($pass, $db_pass['password'])){ 60 throw new Exception('パスワードが違います'); 61 } 62 $stmt = $this->dbh->prepare("DELETE FROM post WHERE id = :id"); 63 $stmt->bindValue(':id', $id, PDO::PARAM_INT); 64 $stmt->execute(); 65 } 66} 67
  • bbs.php

php

1<?php 2include 'includes/login.php'; 3include 'bbs_class.php'; 4 5error_reporting(E_ALL); 6ini_set("display_errors",1); 7 8$bbs = Bbs::create('mysql:host=localhost;dbname=online_bbs;charset=utf8', 'root', '', 10); 9 10$page = ($_GET['page'] ?? 1) - 1; 11?> 12<html> 13 <head> 14 <title>交流サイト:掲示板</title> 15 <meta charset="utf-8"> 16 </head> 17 <body> 18 <h1>掲示板</h1> 19 <form action="write.php" method="post"> 20 <p>名前:<input type="text" name="name" value="<?php echo isset($_COOKIE['name']) ? $_COOKIE['name'] : '' ?>"></p> 21 <p>タイトル:<input type="text" name="title" size="60"></p> 22 <textarea name="comment"></textarea> 23 <p>削除パスワード(数字4桁):<input type="text" name="pass"></p> 24 <input type="submit" name="submit" value="書き込む"> 25 <input type="hidden" name="token" value="<?php echo password_hash(session_id(),PASSWORD_DEFAULT); ?>"> 26 </form> 27 <hr> 28 <?php foreach ($bbs->comments($page) as $row): ?> 29 <p>名前:<?php echo $row['name'] ?></p> 30 <p>タイトル:<?php echo $row['title'] ? $row['title'] : '(無題)' ?></p> 31 <p><?php echo nl2br(htmlspecialchars($row['comment'],ENT_QUOTES,'UTF-8'),false) ?></p> 32 <p><?php echo $row['created_at'] ?></p> 33 <form action="delete.php" method="post"> 34 <input type="hidden" name="id" value="<?php echo $row['id']; ?>"> 35 削除パスワード:<input type="password" name="pass"> 36 <input type="submit" value="削除"> 37 <input type="hidden" name="token" value="<?php echo password_hash(session_id(),PASSWORD_DEFAULT); ?>"> 38 </form> 39 <?php endforeach; ?> 40 <p> 41 <?php foreach (range(1, $bbs->numberOfPages()) as $page): ?> 42 <a href="bbs.php?page=<?php echo $page ?>"><?php echo $page ?></a>&nbsp; 43 <?php endforeach; ?> 44 </p> 45 </body> 46</html>
  • write.php

php

1<?php 2include 'includes/login.php'; 3include 'bbs_class.php'; 4 5error_reporting(E_ALL); 6ini_set('display_errors', '1'); 7 8$bbs = Bbs::create('mysql:host=localhost;dbname=online_bbs;charset=utf8', 'root', '', 10); 9 10$token = filter_input(INPUT_POST,'token',FILTER_SANITIZE_SPECIAL_CHARS); 11$title = filter_input(INPUT_POST,'title',FILTER_SANITIZE_SPECIAL_CHARS); 12$name = filter_input(INPUT_POST,'name',FILTER_SANITIZE_SPECIAL_CHARS); 13$comment = filter_input(INPUT_POST,'comment',FILTER_SANITIZE_SPECIAL_CHARS); 14$pass = filter_input(INPUT_POST,'pass',FILTER_SANITIZE_SPECIAL_CHARS); 15 16if(!password_verify(session_id(), $token)){ 17 header('Location:bbs.php'); 18 exit(); 19} 20 21$err_message = []; 22 23if (!$name) { 24 $err_message[] = '名前が入力されていません'; 25} 26 27if (!$pass) { 28 $err_message[] = 'パスワードが入力されていません'; 29} elseif (!preg_match("/^[0-9]{4}$/", $pass)){ 30 $err_message[] = 'パスワードを4文字で入力してください'; 31} 32 33if (!$comment) { 34 $err_message[] = 'コメントが入力されていません'; 35} 36 37if(empty($err_message)){ 38 setcookie('name', $name,time() + 60 * 60 * 24 * 30); 39 $pass = password_hash($pass,PASSWORD_DEFAULT); 40 $bbs->write($name, $title, $comment, $pass); 41} 42?> 43<html> 44 <head> 45 <meta charset="utf-8"> 46 <title>Page Title</title> 47 </head> 48 <body> 49 <?php if (empty($err_message)): ?> 50 <h4>投稿に成功しました。</h4> 51 <?php else: ?> 52 <?php echo implode("<br />",$err_message); ?> 53 <?php endif; ?> 54 <p><a href="bbs.php">戻る</a> 55 </body> 56</html>
  • delete.php

php

1<?php 2include 'includes/login.php'; 3include 'bbs_class.php'; 4 5error_reporting(E_ALL); 6ini_set("display_errors",1); 7 8$bbs = Bbs::create('mysql:host=localhost;dbname=online_bbs;charset=utf8', 'root', '', 10); 9 10$token = filter_input(INPUT_POST,'token',FILTER_SANITIZE_SPECIAL_CHARS); 11$pass = filter_input(INPUT_POST,'pass',FILTER_SANITIZE_SPECIAL_CHARS); 12$id = filter_input(INPUT_POST,'id',FILTER_VALIDATE_INT); 13 14if(!password_verify(session_id(), $token)){ 15 header('Location:bbs.php'); 16 exit(); 17}; 18 19$err_msg = []; 20 21if (!$pass) { 22 $err_msg[] = 'パスワードが入力されていません。'; 23} 24 25if (!$id) { 26 $err_msg[] = 'IDが入力されていません。'; 27} 28 29if(empty($err_msg)){ 30 $bbs->delete($id, $pass); 31 header('Location: bbs.php'); 32 exit(); 33} 34?> 35<html> 36 <head> 37 <meta charset="utf-8"> 38 <title>Page Title</title> 39 </head> 40 <body> 41 <?php echo implode("<br />",$err_msg); ?> 42 <p><a href="bbs.php">戻る</a> 43 </body> 44</html>

投稿2019/03/15 08:35

Stripe

総合スコア2183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

newyee

2019/03/16 10:38 編集

ご親切にありがとうございます。 どのように、処理を切り分けたり、クラスを作るのかが分からなかったのですが、ご回答いただきましたおかげでイメージが掴めました。 自分のコードは、「write.php」「delete.php」「bbs.php」の全てでデータベースへの接続処理を記載していたんですが、クラス一つにまとめれば見やすいし、便利ですね!ご回答いただきましたおかげで、かなり、オブジェクト指向について、イメージが掴めたのですが、自分の知識不足で、理解できていない部分もあります...自分では、大丈夫であろうと思い、オブジェクト指向に取り掛かろうとしたのですが、そこに入る前に、もっときちんと勉強しなければならないと、痛感致しました... 勉強する、段階を間違えてしまったと思っておりまして、現在は参考書にて、もう一度基本的なことを学び直しております。オブジェクト指向も含めすべての復習が終了しましたら、ご回答頂きました、掲示板のコードを参考にさせて頂き、掲示板のコードをオブジェクト指向に書き換えてみます。 ご丁寧に教えてくださいまして、ありがとうございました。
newyee

2019/04/06 11:18 編集

あれから、オブジェクト指向につきまして、書籍にて勉強をし、ご回答頂きましたコードを見直させてもらったのですが、まだ、何点か分からない所がございます... bbs_class.phpのcreate関数内の「return new static($dbh, $num);」とあるのですが、「new static」という書き方は初めてみました...これはどのような意味になるのでしょうか...? もしよろしければ、お手数かとは思いますが、教えて頂けましたら、幸いです。よろしくお願いいたします...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問