• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:クラスの中で関数・変数を使う方法)

クラスの中で関数・変数を使う方法

このQ&Aのポイント
  • クラスの中で関数や変数を使用する方法について教えてください。
  • クラス内での関数や変数の利用方法についてわかりません。
  • クラスの中での関数や変数の使用方法について詳しく教えてください。

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

  • ベストアンサー
noname#244856
noname#244856
回答No.10

>> $recursion_level >> この数値をいじるといけてしまうのでしょうか? そうですね。 3再帰以内の人を取得したいならば $this->getInvitationLeaves($_SESSION['user_id'], 3) 3再帰ちょうどの人を取得したいならば $this->getInvitationLeaves($_SESSION['user_id'], 3, true) といった感じでいくらでも調節できますね。getInvitationTreeメソッドは他にもいろいろ応用が利きそうなので、そのときは是非使いまわしましょう。 出来た時の喜びを掴みたいという意思があれば、自然にどんどんスキルアップしていけますよ!私も最初はド素人から始まって汚いコードばかり書いていましたが、オブジェクト指向でTwitterアプリを手さぐりで作ってみたりしているうちに自然にスキルが身についてきて、そこからQ&Aサイトでの回答をするようになった今の自分があります。

milkkokoa94856
質問者

お礼

ありがとうございました!! 簡単なことは色々できるのですが、応用となると今回みたいにお手上げになっております(´;ω;`) 私も早く回答側に回って困ってる人を助けれる日を夢見て頑張ります(笑) やはり色々実際にやって数をこなしていきたいと思っておりますので今後も意味不明なご質問をさせていただくかもしれませんが、もし目に付いたら救ってやってください(>人<;) 丁寧な回答ありがとうございました^^

その他の回答 (9)

noname#244856
noname#244856
回答No.9

今気づいたのですが、NULLとFALSEによる区別を行うならば、変数$doneは用意する必要が無くなりますね。というわけで public function getInvitationTree($root_id, $recursion_level = 0) { ____$tree = array($root_id => null); ____$info = array($root_id => $this->getUser($root_id)); ____$stmt = $this->pdo->prepare(implode(' ', array( ________'SELECT *', ________'FROM `user`', ________'WHERE `sno` = ?', ____))); ____for ($i = 0; $i <= $recursion_level, $i++) { ________array_walk_recursive($tree, function (&$v, $k) use ($stmt, &$info) { ____________if ($v === false) { ________________return; ____________} ____________$stmt->bindValue(1, $k, PDO::PARAM_INT); ____________$stmt->execute(); ____________if (!$stmt->rowCount()) { ________________$v = false; ________________return; ____________} ____________$v = array(); ____________foreach ($stmt as $row) { ________________$v[$row['id']] = null; ________________$info[$row['id']] = $row; ____________} ________}); ____} ____return array( ________'tree' => $tree, ________'info' => $info, ____); } で十分でしょう。

milkkokoa94856
質問者

補足

か、完璧ですΣ(゜д゜lll) やってみたいことが綺麗にできました!! 毎回お手数をお掛けして本当に申し訳ないです。 とりあえずせっかく教えていただいたこのオブジェクト指向でできたもので色々試しているのですが、出来た時の喜びがすごいです(笑) つまずいたときは苦労がすごいですけど、というか今回のような難易度の高いことをしてみるとまだまだつまずいて毎回助けていただいている現状に涙目です。 じっくりコードを見直して色々試してみます。 ちなみにこれは以前 (再帰レベル1指定なので3,4の招待ユーザーは取得しません) とおっしゃっていたのですが、どんどん奥に(2階層の人が紹介した3階層の人)いこうと思うと $recursion_level この数値をいじるといけてしまうのでしょうか? そうなってくるとコードは変わるのでしょうか? せっかくなのでどんどん奥に行ったりしてこの辺の理解を深めようと思います><

noname#244856
noname#244856
回答No.8

【私が期待している構造の例】で紹介した例で、ユーザー (3,4) と ユーザー(5) の集合を区別する必要ってありますか?再帰を最後まで行った結果見つかったグループと、途中でそれ以上再帰を行う対象が見つからずに中断したグループのことです。もしこれを区別する必要があるなら if (!$stmt->rowCount()) { ____$done[$k] = true; ____return; } を if (!$stmt->rowCount()) { ____$done[$k] = true; ____$v = false; ____return; } として、NULLとFALSEで区別でもしてみましょうか。この変更を加えた上で、葉要素のユーザー情報だけを取得するgetInvitationTreeメソッドのラッパーメソッドも作ってみましょう。 $root_id →根となるID。 $recursion_level →再帰を行う回数を表す0以上の整数。デフォルトは0。 $only_deepest → True: 先ほど述べた「NULL」のみに限定する → False(デフォルト): 先ほど述べた「NULL」「FALSE」の両方を取得する public function getInvitationLeaves($root_id, $recursion_level = 0, $only_deepest = false) { ____$data = $this->getInvitationTree($root_id, $recursion_level); ____$leaves = iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($data['tree']))); ____if ($only_deepest) { ________$leaves = array_filter($leaves, 'is_null'); ____} ____$ret = array(); ____foreach ($leaves as $id => $dummy) { ________$ret[] = $data['info'][$id]; ____} ____return $ret; } メソッドを呼んでみた結果をvar_dumpかprint_rで確認してみてください。

noname#244856
noname#244856
回答No.7

※ $_SESSION['user_id'] は 1 としています。

milkkokoa94856
質問者

お礼

お礼の部分に失礼いたします。 先ほどやっと $second = $ret['info']; <?php foreach ($second as $snouser): ?> <div class="check">会員ID:<?php echo "<pre>"; var_dump($snouser['name']); echo "</pre>";?></div> <?php endforeach; ?> このようにして名前のみを取得できました。 山田1号 山田2号 山田3号 山田4号 山田5号 なのですが2階層目なので山田3号~5号までを表示したいのですが、どうもうまくいきません。 クラスの方で制御するのか表示先のforeachで制御できるのか失礼ながらこちらにご質問させていただきましたm(_ _)m

milkkokoa94856
質問者

補足

本当に毎回お世話になり申し訳ないです。 完璧です、自分の表示したい通りのことを理解し導いて頂きました。 print_r($ret['info']); で中身をみると下記の通り表示されました。 1000 山田1号でログイン中 Array ( ____[1000] => Array ________( ____________[id] => 1000 ____________[name] => 山田1号 ________) _____[1001] => Array ________( ____________[id] => 1001 ____________[name] => 山田2号 ____________[invitid] => 1000 ____________[invit] => 山田1号 ________) _____[1002] => Array ________( ____________[id] => 1002 ____________[name] => 山田3号 ____________[invitid] => 1001 ____________[invit] => 山田2号 ________) _____[1003] => Array ________( ____________[id] => 1003 ____________[name] => 山田4号 ____________[invitid] => 1001 ____________[invit] => 山田2号 ________) _____[1004] => Array ________( ____________[id] => 1004 ____________[name] => 山田5号 ____________[invitid] => 1001 ____________[invit] => 山田2号 ________) _____[1005] => Array ________( ____________[id] => 1005 ____________[name] => 山田5号 ____________[invitid] => 1001 ____________[invit] => 山田2号 ________) ) と確認でき、 print_r($ret['tree']); をした場合 Array ( ______[1000] => Array ________( ____________[1001] => Array ________________( ____________________[1002] => ____________________[1003] => ____________________[1004] => ____________________[1005] => ________________) ____________) ) となり表示したい2階層部分の1002~1005が取得できています。 実際にページに表示しようと多次元配列の記事を読み <?=h($ret[])?> この[]の中に指定をしようと色々やってみたのですが、通常のサイトでは自分で決めた数値でやる場合は載っているのですが、今回のように取得した数値の場合などの記事が見つけれず数時間悩みましたがアドバイスを受けたく追記してしまいました。 この辺の応用力もなく自分に凹みましたがもうしわけございませんが1002~1005の部分の[invit]の文字列を取得したい場合[]には何を指定するべきなのでしょうか。

noname#244856
noname#244856
回答No.6

getInvitationTreeの返り値をvar_dumpなりprint_rなりしてみてください。 【私が期待している構造の例】 $ret = DB::connect()->getInvitationTree($_SESSION['user_id'], 1); としたとき、1が2,5を招待し、2が3,4を招待していたと仮定すると、 (再帰レベル1指定なので3,4の招待ユーザーは取得しません) $ret['tree'] = array( ____1 => array( ________2 => array( ____________3 => null, ____________4 => null, ________), ________5 => array( ____________null, ________), ____), ); $ret['info'] = array( ____1 => 1の情報の配列, ____2 => 2の情報の配列, ____3 => 3の情報の配列, ____4 => 4の情報の配列, ____5 => 5の情報の配列, ); となるように書いたのですが、合ってますかね・・・? デバッグしていないので期待と違っていればごめんなさい。 array_walk_recursive http://php.net/manual/ja/function.array-walk-recursive.php この関数は末端の要素だけを順番に取り出そうとします。この性質を利用して、$recursion_level の指定をうまく反映させています。$done にセットしているのは「招待ユーザーが見つからなかったユーザー」で、これはそれらを次のループで取り出す対象から外すために行っています。 なお、$stmt を use せずにクロージャの中で $this->getInvitedUsers($k) を呼んでもよかったのですが、PDOで同じプリペアドステートメントを複数回利用する場合、一度用意した PDOStatement オブジェクトを使いまわしたほうが圧倒的にパフォーマンスが向上するため、このように少々回りくどい方法を採りました。 以下も参考にどうぞ↓ array_walk http://www.php.net/manual/ja/function.array-walk.php 無名関数(クロージャ) http://php.net/manual/ja/functions.anonymous.php

noname#244856
noname#244856
回答No.5

$recursion_level, ↓ $recursion_level; なかなか気づきませんでした;;

milkkokoa94856
質問者

補足

お手数をおかけして申し訳ありませんでした。 DB.phpの方は無事エラーはなくなったのですが、HTML部分で Warning: htmlspecialchars() expects parameter 1 to be string, array given in 調べると配列ではなく文字列を入れろということらしいのですが、 $invited = DB::connect()->getInvitedUsers($_SESSION['user_id']); これでセッションからの紹介の部分に関しては呼び出せております。 $second = DB::connect()->getInvitationTree($_SESSION['user_id']); これでいま作成している2段目を接続しているのですが、HTMLで表示させようとすると先ほどのエラーがでてしまいます。 HTML部分での記述はどのようにするのでしょうか。 毎回お世話になって質問しづらいのですが、初めて見るエラーばかりでアドバイス通り翻訳してみたもののわかりませんでした。orz

noname#244856
noname#244856
回答No.4

大幅に訂正 public function getInvitationTree($root_id, $recursion_level = 0) { ____$tree = array($root_id => null); ____$info = array($root_id => $this->getUser($root_id)); ____$stmt = $this->pdo->prepare(implode(' ', array( ________'SELECT *', ________'FROM `user`', ________'WHERE `sno` = ?', ____))); ____for ($i = 0; $i <= $recursion_level, $i++) { ________array_walk_recursive($tree, function (&$v, $k) use ($stmt, &$info, &$done) { ____________if (isset($done[$k])) { ________________return; ____________} ____________$stmt->bindValue(1, $k, PDO::PARAM_INT); ____________$stmt->execute(); ____________if (!$stmt->rowCount()) { ________________$done[$k] = true; ________________return; ____________} ____________$v = array(); ____________foreach ($stmt as $row) { ________________$v[$row['id']] = null; ________________$info[$row['id']] = $row; ____________} ________}); ____} ____return array( ________'tree' => $tree, ________'info' => $info, ____); }

milkkokoa94856
質問者

補足

すごい丁寧にありがとうございます。 自分がやってみようと思ったことがこんなに複雑だったとは一人では何日悩んでもここにたどり着いてない気がしてゾッとします。 今やってみたら Parse error: syntax error, unexpected ')', expecting ';' in のエラーで その行には for ($i = 0; $i <= $recursion_level, $i++) { の記述です。 エラーのとおり)に注目してみたものの私のレベルではよくわかりませんでした。 )の数もあってたと思うのですがその周辺も全て数えたのですが間違いないようでした。 その場合は、ほかのとこがエラーになっているのでしょうか?

noname#244856
noname#244856
回答No.3

えーっと、つまり 「まず自分が招待した人々を求める」 「次にそれら1人1人が招待した人々を求める」 (根を0段目とすると)ツリー構造の2段目まで求めたい、こういうことでしょうか?そうであればテーブル・カラムを新たに作成する意味って無いんじゃないですかね。 getInvitedUsersメソッドはそのまま残しておいて、新たにgetInvitationTreeメソッドを作成します。 【getInvitationTreeメソッド】 招待関係をIDでツリー上につなげた配列(tree)と、各IDに対応する情報を格納した配列(info)を配列でまとめて返す。 $root_id →根となるID。 $recursion_level →再帰を行う回数を表す0以上の整数。デフォルトは0。 public function getInvitationTree($root_id, $recursion_level = 0) { ____$tree = array($root_id => null); ____$info = array($root_id => $this->getUser($root_id)); ____$stmt = $this->pdo->prepare(implode(' ', array( ________'SELECT *', ________'FROM `user`', ________'WHERE `sno` = ?', ____))); ____for ($i = 0; $i <= $recursion_level, $i++) { ________array_walk_recursive($tree, function (&$v, $k) use ($stmt, &$info) { ____________$stmt->bindValue(1, $k, PDO::PARAM_INT); ____________$result = $stmt->execute(); ____________$v = array($result['id'] => null); ____________$info[$result['id']] = $result; ________}); ____} ____return array( ________'tree' => $tree, ________'info' => $info, ____); } デバッグしてないので多分ミスあると思います、ご容赦を。

noname#244856
noname#244856
回答No.2

getInvitedUsersメソッドの役割は「引数で渡されたIDのユーザーが招待したユーザーを取得する」でいいですよね?であればすでに回答にあるように引数として渡すだけでいいと思います。 snoカラムってInt型でしたよね?それならばPDO::PARAM_INTで合ってますね。 それと以前の補足に対して回答するのを忘れていましたが、申し訳ないですがよく意味が分かりませんでした。MySQLのエラーメッセージって結構親切なので高卒レベル程度の英語が読めれば何となくどこを直せばいいかぐらいは分かるんじゃないでしょうか。

milkkokoa94856
質問者

補足

とんでもございません、説明が下手で申し訳ないですm(_ _)m なんとか回答を頂いたセッションで表示することができました。 今回の質問はもう一段階招待した人を表示したいと思っております。 なので、 <?php foreach ($user as $suser): ?> <li><?=h($suser['id'])?></li> <?php endforeach; ?> 表示は 1001 1002 1003 これで今回のセッションを使って招待した人を3人表示できたとします。 例のIDと名前は下記のとおり 1001 山田 1002 佐藤 1003 花子 さらにこの3人のIDから招待した人を表示したいと思っております。 DB.phpへ public function getSecondInvited($inviter_id) { $stmt = $this->pdo->prepare(implode(' ', array( 'SELECT *', 'FROM `syoukai`', 'WHERE `syoba` = ?', ))); $stmt->bindValue(1, $inviter_id, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(); } として『?』の部分に1001と山田の番号を入れるとうまく表示できています。 なので『?』の部分に取得した$suser['id']を当てはめたいのですが代入したりして『?』の部分に変えてみたり色々やってみたもののうまくいきません。 WHEREには関数や変数を使うことができないのでしょうか? このような場合はどのように記述するべきなのでしょうか? 説明がごちゃごちゃしていて申し訳ございませんがヒントでもアドバイスを頂けると幸いです。

回答No.1

$stmt->bindValue(1, $inviter_id, PDO::PARAM_INT); としているのだから、getInvitedUsers()の引数に $_SESSION['user_id']を渡せばいいのでは。 あと、バインドしている変数がint型を指定しているので、 PDO::PARAM_INTではなくPDO::PARAM_STRに変えてあげれば いいんじゃないでしょうか。 http://php.net/manual/ja/pdostatement.bindvalue.php http://www.php.net/manual/ja/pdo.constants.php もしでしたら、プリペアドステートメント、プレースホルダーについて 改めて学習し直すといいかもしれません。

milkkokoa94856
質問者

お礼

ありがとうございました、セッションの方を渡して無事に表示することができました^^

関連するQ&A