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

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

ただいまの
回答率

90.50%

  • PHP

    20775questions

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

  • HTML

    9247questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • MySQL

    5992questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP DBから抽出データ、配列、SESSION、class

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 1,231

Z-TALBO

score 481

はじめに

たぶん、何やってんだろう?という質問内容かと思いますが、アドバイスをいただければと思います。

やりたいこと

漠然としてはいますが、たぶんclassを作るのに、すごい遠回りをし始めているんだと思います。

そして、MVCなどの考え的なのはなんとなくわかるのですが、イマイチclassとかの部分がまだ理解できておりません。

とりあえず、例えばですが、、、

<select>
<option></option>
<?php
$dbh = connectDb();
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = "SELECT id, name FROM users ORDER BY id ASC";
$stmt = prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch()) :
$id = $row['id'];
$name = $row['name'];
?>
<option value="<?= $id; ?>"><?= $name; ?></option>
<?php endwhile; ?>
</select>


上記のように、SelectのoptionをDBから引っ張ってきて作成するというものがあるとします。

これだけで、普通にできているのですが、あえて、、、処理をわけてわざわざ複雑な感じにしてみたいと思います。
※なんでするの?というのは、とりあえず聞かないでください、、、、

とりあえず考えてみたこと

classとかの部分が勉強不足なので、とりあえず処理を分けるということだけを考えてみました。

[index.php]
<!-- select_box -->
<?php select_box(); ?>
[db.php]
function select_db() {
$dbh = connectDb();
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = "SELECT id, name FROM users ORDER BY id ASC";
$stmt = prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll();
$_SESSION['rows'] = $rows;
}
[processing.php]
function select_box() {
select_db();
$cnt = count($_SESSION['rows']);
echo "<select name='select_box'><option></option>";
for ($i = 0; $i <= $cnt; $i++) {
$select['id'] = $_SESSION['rows'][$i]['staff_id'];
$select['name'] = $_SESSION['rows'][$i]['name'];
echo "<option value=" . $select['id'] . ">" . $select['name'] . "</option>";
}
echo "</select>";

とりあえずの結果

表示することはとりあえずできました。

問題等

処理を分けるという考え方だけなら、indexは表示だけ、dbがDBからのデータを抽出しただけ、processingでデータを加工?したという感じ?になったような気はしますが、、、
とりあえず、よくわかってない部分で、、、
1.これでデータを取得したら、なぜかデータの最後に空白ができてた。
当然最初に<option></option>があるので、最初は空白ですが、その後データの最後にまた空白ができてしまっていました。

2.上記はとりあえず独学と、いろいろ質問させてもらったりサイトを見たのを使いながらゴリゴリ書いていきましたが、これをもう少しこうすれば?というアドバイスやヒントなどいただければと思って質問いたしました。

ここは、こうしたほうがわかりやすい。
ここは、無駄でなくてもいいはず。
さらにここは省略するべきなど、、、ご意見いただけますでしょうか?

なんじゃこの書き方は?と思われるでしょうが、参考のために、、、

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+1

2.上記はとりあえず独学と、いろいろ質問させてもらったりサイトを見たのを使いながらゴリゴリ書いていきましたが、これをもう少しこうすれば?というアドバイスやヒントなどいただければと思って質問いたしました。

基本的な文法や使い方がわかってきている段階に見えますので、
ここいらで書籍を使って学習することをお勧めします。
もちろんネットで学習できることも多いですし、書籍でもダメなものはありますが、
「なぜ処理をまとめた方が便利なのか」という部分の学習も含めてコードが設計されていることが多いので、
効率よく学習出来ることが多いです。

例えば今回のケースだと
戻り値の使い道についてピンと来ていないように見えます。

[db.php]
function select_db() {
$dbh = connectDb();
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = "SELECT id, name FROM users ORDER BY id ASC";
$stmt = prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll();
$_SESSION['rows'] = $rows;
}


だと切り出しただけであんまり意味が無いです。
具体的には、結果を$_SESSIONに格納してしまっているので、
どこか別のタイミングで呼ばれたとしても$_SESSIONを意図せず汚してしまうことになります。

なので例えば

function select_db() {
$dbh = connectDb();
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = "SELECT id, name FROM users ORDER BY id ASC";
$stmt = prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll();
return $rows;
}


と、結果を戻り値で返すようにしてやって

[processing.php]
function select_box() {
$rows = select_db();
$cnt = count($rows);
echo "<select name='select_box'><option></option>";
for ($i = 0; $i <= $cnt; $i++) {
$select['id'] = $rows[$i]['staff_id'];
$select['name'] = $rows[$i]['name'];
echo "<option value=" . $select['id'] . ">" . $select['name'] . "</option>";
}
echo "</select>";


としてやれば、select_db()は別の場所で使っても問題の無い関数になります(処理の再利用が出来るようになったので、別ページで同じことをしようとした時に同じコードをコピペしなくてよくなります)

同様に、
引数についても正しく使えば便利で
例えば

function select_db($order,$sort) {
$dbh = connectDb();
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = "SELECT id, name FROM users ORDER BY :order :sort";
$stmt = $dbh->prepare($sql);
$stmt->bindValue(':order', $order, PDO::PARAM_STR);
$stmt->bindValue(':sort', $sort, PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll();
return $rows;
}


とすれば、呼び出すタイミングでソートするキーと昇順/降順を指定するだけで、実際に実行されるSQLを変更することが出来て便利だったりします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/20 08:41

    回答ありがとうございます!
    確かにreturnの返り値や引数という部分がぴんと来ていませんでした。。。

    SESSIONもこんなにやるとUNSETも増えたりで、なんか大変だよな、、、とは思っていたのですが、、、そこに気づけませんでした。

    大変参考になりました!ありがとうございます!

    キャンセル

+1

MVCは自信ないのでoptionの件だけ・・・

最後のoptionが空になるのはfor ($i = 0; $i <= $cnt; $i++)のせいですね
count($_SESSION['rows'])でデータ数を取得していますが実際のデータは0から始まるので
for ($i = 0; $i < $cnt; $i++)としてあげてください。

$data配列のデータ数が2の場合は$data[0]$data[1]の2つだけと考えて見てください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/19 19:36

    あっ!そうですよね!
    よく忘れるんです、、、0からなの、、、
    ありがとうございます!

    キャンセル

0

とりあえず自分の好みでいうとこんな感じかなあ

[index.php]
<!-- select_box -->
<select name='select_box'><option></option>
<?php echo select_box(); ?>
</select>

[db.php]
function select_db($sql) {
  $dbh = connectDb();
  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
  $stmt = prepare($sql);
  $stmt->execute();
  return $stmt->fetchAll();
}

[processing.php]
function select_box() {
  $sql = "SELECT id, name FROM users ORDER BY id ASC";
  $ret = '';
  foreach (select_db($sql) as $row) {
    $id = $row['id'];
    $name = $row['name'];
    $ret .= "<option value=" . $id . ">" . $name . "</option>\n";
  }
  return $ret;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/20 08:37

    回答ありがとうございます!
    なんだか、スッキリしました。
    for文で考えていたので、foreachの方も参考にいたします!
    indexの方で<select>タグはやはり出しておいたほうが、いいですね。
    nameが~ってなった時にfunctionを見に行かなくて済みます。

    キャンセル

0

基本的にDBのクラスからはHTMLを出力したりするのはメンテしにくくなるので、単純に配列出会ったり、オブジェクトを返すだけにしたほうが汎用性が上がります。
スケルトンで書いてみましたが、以下のようにクラスを実装してみては?

<?php

class MySQL
{

    /**
     * ホスト
     */
    private $host = 'localhost';

    /**
     * データベース
     */
    private $database = 'database';

    /**
     * ユーザー
     */
    private $user = 'root';

    /**
     * パスワード
     */
    private $pass = '';

    /**
     * DSN
     */
    private $dsn = null;

    /**
     * 接続
     */
    private $dbh = null;

    /**
     * コンストラクタ
     */
    public function __construct()
    {
        $this->connect();
    }

    /**
     * 接続する
     * @return $dbh
     */
    private function connect()
    {
        $this->dsn = "mysql:dbname={$this->database};host={$this->host};charset=utf8";
        $this->dbh = new PDO($this->dsn, $this->user, $this->pass);
    }

    /**
     * SELECT
     * @param string $sql
     * @param array $arrParams
     * @return array
     */
    public function select($sql, $arrParams)
    {
        // @todo
        return $arrRecords;
    }

    /**
     * UPDATE
     * @param string $sql
     * @param array $arrParams
     * @return bool
     */
    public function update($sql, $arrParams)
    {
        // @todo
        return $bool;
    }

    /**
     * INSERT
     * @param string $sql
     * @param array $arrParams
     * @return int
     */
    public function insert($sql, $arrParams)
    {
        // @todo
        return $insertId;
    }

}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/20 08:38

    回答ありがとうございます!

    クラスの実装に関してアドバイスいただき、大変参考になります!

    クラス部分の作り方など参考にさせていただきます!

    キャンセル

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

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20775questions

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

  • HTML

    9247questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • MySQL

    5992questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。