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

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

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

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

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

オブジェクト指向

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

Q&A

解決済

1回答

415閲覧

php - インスタンス変数とthisの利用方法

keys

総合スコア215

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

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

オブジェクト指向

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

0グッド

1クリップ

投稿2018/04/04 23:19

編集2018/04/05 01:03

追記

php

1class Test 2{ 3 4 public $hoge = "cccc"; 5 6 7 static public function getNew() 8 { 9 echo "aaaaa/"; 10 echo $this->hoge; 11 } 12} 13 14class Child extends Test 15{ 16} 17 18Child::getNew();

上記のコードを実行すると、aaaaa/とだけ表示されます。何故、ccccは表示されないのでしょうか

やりたいこと

phpでオブジェクト指向を実践しています。PDOのdb接続と、selectをクラスで分割し、オブジェクト思考なコードを書く際、疑問が湧いたので質問します。書くの全体のコードは極めて正しく動くのですが。。

#疑問点

下記全体のコードの一部分、コンストラクトがありますが、$this->dbhというのはクラスDatabaseで作成した変数ですよね?newでDatabaseクラスのインスタンスを作って仕舞えば、インスタンス変数の$dbを利用せずとも、$thisが使え$this->dbhという風にclass Databaseの実装を利用することが可能なのでしょうか。

function __construct() { $db=new Database; $this->dbh=$db->getDBH(); }

実装

<?PHP class Database { function getDBH() { try{ $dsn = 'mysql:host=localhost; dbname=test1;charset=utf8;'; $user = 'root'; $password = 'root'; $dbh = new PDO($dsn, $user,$password); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); return $dbh; }catch(PDOException $e){ die($e->getMessage()); } } } class DataSelect { function __construct() { $db=new Database; $this->dbh=$db->getDBH(); } function test() { try{ $sql="SELECT * FROM tb"; $stmt = $this->dbh->prepare($sql); $stmt->execute([]); $rows=$stmt->fetchAll(PDO::FETCH_ASSOC); print_r($rows); }catch(PDOException $e){ die($e->getMessage()); } } } $myExec=new DataSelect; $myExec->test();

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

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

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

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

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

guest

回答1

0

ベストアンサー

$this は自身のオブジェクトをさします。今回のコードではDataSelectクラスですね。
つまり、現状では$this->dbhにあたるものがDataSelectクラスにありません。
変数未宣言のエラーが出るのでは?

下記のように、対応する変数を宣言してやる必要があります。

php

1class DataSelect 2{ 3 public $dbh = null; 4 5 function __construct() 6 7//以下略

まとめサンプルコード

php

1class Database 2{ 3 protected $dbh; 4 function getDBH() 5 { 6 try{ 7 $dsn = 'mysql:host=localhost; dbname=test1;charset=utf8;'; 8 $user = 'root'; 9 $password = 'root'; 10 $this->dbh = new PDO($dsn, $user,$password); 11 $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 12 $this->dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); 13 $this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); 14 }catch(PDOException $e){ 15 die($e->getMessage()); 16 } 17 } 18} 19 20class DataSelect extends Database 21{ 22 function __construct() 23 { 24 $this->getDBH(); 25 } 26 function test() 27 { 28 try{ 29 $sql="SELECT * FROM tb"; 30 $stmt = $this->dbh->prepare($sql); 31 $stmt->execute([]); 32 $rows=$stmt->fetchAll(PDO::FETCH_ASSOC); 33 print_r($rows); 34 }catch(PDOException $e){ 35 die($e->getMessage()); 36 } 37 } 38} 39$myExec=new DataSelect; 40$myExec->test();

投稿2018/04/04 23:30

編集2018/04/05 01:07
m.ts10806

総合スコア80850

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

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

keys

2018/04/04 23:41

上記のコードはエラーにはならないのです。なぜか。自分も、dbhはどこを指してるんだろうと悩んでます。
keys

2018/04/04 23:44

public $dbh = null;をつけても実行結果は変わりません。これであれば理解ができます。クラスDataSelectの$dbhと、クラスDatabaseの$dbhは別物だとわかるからです。でも、public $dbh = nullがなくてもエラーにはなりません。
keys

2018/04/04 23:47

ちなみに、public $dbh = null;を追加せず、$this->dbh=$db->getDBH();を$this->dbhh=$db->getDBH();とかにするとちゃんとエラーになります。なので、クラスDataSelectで使用している$this->dbhは、確実にクラスDatabaseの$dbhだと思われます。
退会済みユーザー

退会済みユーザー

2018/04/04 23:47

phpはゆるゆるなんでNOTICEレベルは出るかもしれないけど、構造を簡単にかえれるんです。(笑) phpはarrayをベースにオブジェクトをつくってるので‥
keys

2018/04/04 23:47

DataSelectクラスからは、Databaseクラスの$dbh変数が見えています。
keys

2018/04/04 23:51

んんんん、であれば、thisである必要がないと思われたので、試しに、$this->dbh=$db->getDBH();を$dbhhhhh=$db->getDBH();にしてみたらエラーになりました。どうしてここで、thisを使わなければいけないのかわかりません
keys

2018/04/04 23:53

また、 下記のようにしても、エラーになります。 public $dbhhhhhh = null; $db=new Database; $this->dbhhhhhh=$db->getDBH();
keys

2018/04/04 23:55

でも、クラスの変数はインスタンス化しなくても参照できるのに、クラスの関数を使うときは、インスタンス変数を用いてdb->getDBH();のようにしなければいけないっていうのは、なんだか不思議です
keys

2018/04/04 23:56

何故、インスタンス化変数を利用せずに、$thisを使って別のクラスの変数を参照できるのか謎です。
keys

2018/04/04 23:57

また、どうして$this->dbhという変数でなければ、$db->getDBH();からの返り値を受け取れないか、それも謎です
m.ts10806

2018/04/04 23:58

あああー、なるほど。 質問の意図を理解できてなかったかもしれません。 質問本文 > コンストラクトがありますが、$this->dbhというのはクラスDatabaseで作成した変数ですよね? いいえ違います。 正確にはDatabaseクラスのgetDBH()で生成した情報を保持している DataSelectクラスの変数です。あくまで1変数に過ぎません。 $a = "test"; $b = $a; echo $a; echo $b; として、出力結果は同じですが、「同一のもの」ではありません。 あくまで$bというただの変数がたまたま$aの情報を「代入」されただけであり、$aそのものではありません。 それと同じです。 (クラス側で宣言なしに値を突っ込むという横着な実装したことなかったので気づきませんでした・・・)
m.ts10806

2018/04/05 00:00

つまり、 >DataSelectクラスからは、Databaseクラスの$dbh変数が見えています。 これも違います。 あくまで「DataSelectクラスで生成された$dbhを参照している」だけです。 継承しているわけでも、Databaseクラスでパブリック変数として定義されているわけでもないのでDatabaseクラスの情報を参照しているわけではありません。
m.ts10806

2018/04/05 00:03

例えば以下のようにする。 class DataSelect { public $dbhSelect = null; function __construct() { $db=new Database; $this->dbhSelect=$db->getDBH(); } function test() {   ・・・   $stmt = $this->dbhSelect->prepare($sql);    ---------- 下記のようにしてエラーが出たのは実際に使っている先で $this->dbh->prepare($sql);としたからでは? > $this->dbhhhhhh=$db->getDBH(); $thisは自身なので自身にはdbhというプロパティは存在しないわけですし。
退会済みユーザー

退会済みユーザー

2018/04/05 00:08

>$dbhhhhh=$db->getDBH();にしてみたらエラーになりました。どうしてここで、thisを使わなければいけないのかわかりません そりゃ、$this->を書かないと、$dbhhhhhは関数内のローカル変数として扱われるからです。 $thisっていうのはインスタンスのメンバであることを指すのです。 で、asahina1979が書いている通り、PHPは動的にメンバ変数を作れます。 だから、class Dto {} みたいな宣言だけしておいて、 $dto = new Dto();とインスタンスを作って、 $dto->a = 1; $dto->b = "hoge";  : みたいに、どんどんメンバ変数を作っていけます。 これが、PHPのとても便利なところです。 で、これらは全部publicな変数になります。 ですから、$this->dbhについてもpublicです。 そうすると、カプセル化もへったくれもなくなるので、 private $dbhと、class内できちんと宣言しておくことが望まれます。 というか、普通はclass Databaseあたりを基底クラスとして class DataSelect extends Database {}にして、 protected $dbh; ですね。 そんなわけで、天地がひっくり返っても誰かさんみたいに、 public $dbh = null; とかやらないでください。
keys

2018/04/05 00:08

なるほどおおお。こういう見解は的外れですか? Databaseクラスの$db->getDBH();関数の返り値は、あくまでもDatabaseクラス内の変数に返さないといけないから、$this->dbhのようにしなければいけない。 $db->getDBH();という時点で、Databaseクラスはインスタンス化されているから、 $this->dbhがよくわからないけど、Databaseクラスの中のdbhってことで、目を瞑る。
m.ts10806

2018/04/05 00:15 編集

>でも、クラスの変数はインスタンス化しなくても参照できるのに、クラスの関数を使うときは、インスタンス変数を用いてdb->getDBH();のようにしなければいけないっていうのは、なんだか不思議です 少し勘違いされています。 うまく伝えられるか分かりませんが、 $thisは自身の「オブジェクト」なので参照できています。 static宣言された変数であればself::{変数名} というような参照の仕方もできます。 もちろんインスタンス化することなく参照することも可能です。 メソッドをstaticにすれば良いのです。 class Database { static function getDBH() { すると class DataSelect { function __construct() {    $this->dbh=Database::getDBH(); の、ように利用することができます。 ※これもstaticにするメリットデメリットはきちんと調べてから利用した方が良いです。 確かPDOにもstaticなやり方ありましたよね。
m.ts10806

2018/04/05 00:14 編集

luckerさん 補足ありがとうございます。明示的なので別に「誰かさん」のように隠さなくても結構です。 ポンポン動的に増えるのは実装としては賢明ではありません。 publicとしたのは現在の質問者さんのレベルからひとまず宣言したものを使うようにしましょうという例として出しており、protectedが適当であるのは理解しております。 ※前の質問で継承するときに親クラスで宣言するようにも伝えてます(「とか」にしてますが)
m.ts10806

2018/04/05 00:19

>Databaseクラスの$db->getDBH();関数の返り値は、あくまでもDatabaseクラス内の変数に返さないといけないから、$this->dbhのようにしなければいけない。 ちょっとどういう解釈でそうなったか分からないですが、 微妙に違うようにも思います。 luckerさんの仰るように、というか前の質問のように継承しておいて Database側に子クラスも参照可能な形で宣言しておけばDataSelectクラスから$this->で利用可能となるわけですし。 継承せずに個別のクラスとするなら、DataSelectクラス側で用意しておいた任意の変数で受けるだけなので、別に変数名はdbhにする必要もなく本当に任意の変数名で良いです。
m.ts10806

2018/04/05 00:33

ひとまず$this は「(親クラスも含めた)自身のオブジェクトである」という観点で再構成してみると良いかもしれません。 Databaseクラスの情報を$thisで利用したいのであれば継承するしかありません。
keys

2018/04/05 01:03

ありがとうございます。再勉強します。ご親切にありがとうございました。
m.ts10806

2018/04/05 01:04

念のためまとめのコード載せておきますので、参考まで。
keys

2018/04/05 01:12

ありがとうございます!参考になります、
m.ts10806

2018/04/05 01:16 編集

ちなみに冒頭のコードは class Test { static $hoge = "cccc"; static public function getNew() { echo "aaaaa/"; echo self::$hoge; } } とすると aaaaa/cccc と表示されます。 クラスをインスタンス化せずにstaticでメソッドを呼び出しているので呼び出しもstaticにしなければなりません。 エラー表示はOnにしていますか?最初の書き方だとエラーが必ず表示されますので まずはそのエラーメッセージを解決の糸口としてください。 (あと前の質問でもコメントしたかもしれませんが、Eclipseなどのエラーを自動検出してくれる高機能エディタを利用してください。定義ミスなどはおおよそ実行前に見つかります)
yambejp

2018/04/05 01:15

なんか私の書いた雑なソースで紛糾してしまって申し訳ないです。
m.ts10806

2018/04/05 01:18

yambejpさん あれはあれで考え方としてありだとは思います。 どういう役割分担をするかというので参考になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問