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

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

ただいまの
回答率

89.10%

タイムカード作成に関して

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,319

Z-TALBO

score 493

現在個人利用(練習)でタイムカードを作成してみたくやっています。

ページの構成
// index.php 名前を選択して打刻
// insert.php index.phpからの値をDBへ
// Data.php Dataを日時抽出で表示、さらに修正できるようにする
// Update.php Data.phpから修正データを受け取ってupdate

DBの設計

tablename = time
id int not null auto_increment primary key,
name varchar(255),
dakoku varchar(255),
year int,
month int,
day int,
hour int,
minutes int,
secounds int

現在indexとinsertに関しては動作確認できました。
Data.phpに関して日付で抽出し、表示はできており、修正用のフォームまではできました。

しかし、Updateがうまくできません。。。
今書いたコード自体にエラーは見られませんが、値がどうも送信されてないか、受け取り方が悪いかであるのかと思います。

どこが、、、というのが今のレベルでは見つけられないのでお知恵を拝借させてください。


// Data.php
// 条件抽出用のフォーム
<form action="" method="POST">
// optionは省略しております。
<select name="year_select"></select>
<select name="month_select"></select>
<select name="day_select"></select>
<input type="submit" value="検索">
</form>

// tableで表示しますが、修正した後さらにサブミットしたいので、、、
<form action="update.php" method="POST">
<table>
// 何月何日は抽出で出すので表示させません
<thead>
<th>名前</th><th>打刻種別</th><th></th><th></th>
</thead>
<tbody>
<?php
  $year = $_POST['year_select'];
  $month = $_POST['month_select'];
  $day = $_POST['day_select'];

  // try catchでDBをSELECTします。
  try {

  } catch

 while ($row = $stmt->fetch()) :
?>
<tr>
  <td>
    <select name="dakoku">
      <option <?= $row['dakoku'] != '出勤' ?: 'selected' ?>>出勤</option>
      <option <?= $row['dakoku'] != '退勤' ?: 'selected' ?>>退勤</option>
      <option <?= $row['dakoku'] != '休入' ?: 'selected' ?>>休入</option>
      <option <?= $row['dakoku'] != '休戻' ?: 'selected' ?>>休戻</option>
    </select>
  </td>
 <td>
    <select name="hour">
      <?php for ($i = 01; $i <= 24; $i++) : ?>
      <option <?= $row['hour'] != $i ?: 'selected' ?>><?= $i; ?></option>
      <?php endfor; ?>
    </select>
  </td>
 <td>
    <select name="minutes">
      <?php for ($i = 00; $i <= 59; $i++) : ?>
      <option <?= $row['minutes'] != $i ?: 'selected' ?>><?= $i; ?></option>
      <?php endfor; ?>
    </select>
  </td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
<input type="hidden" name="id" value="<?= $row['id']">
<input type="submit" value="保存">
</form>


上記のように表示させ、dakoku, hour, minutesだけ変更できるようにセレクトボックスを配置しました。

// update.php
$dakoku = $_POST['dakoku'];
$hour = $_POST['hour'];
$minutes = $_POST['minutes'];
$id = $_POST['id'];

try {
 $dbh = new PDO(DSN< DB_USER, DB_PASSWORD);
 $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
 $stmt = $dbh->prepare(
    "UPDATE time SET dakoku = ?, hour = ?, minutes = ? WHERE id = ?");
 $stmt->bindParam(1, $dakoku, PDO::PARAM_STR);
 $stmt->bindParam(2, $hour, PDO::PARAM_STR);
 $stmt->bindParam(3, $minutes, PDO::PARAM_STR);
 $stmt->bindParam(4, $id, PDO::PARAM_STR);
 $stmt->execute();
} catch


とりあえず上記のようなupdate文を作成しましたが、、、

Data.phpで表示される行数は一行とは当然限りません。。。
最低でも2行はあるでしょう(タイムカードなので、出と退は必ずあるはず)。

それらを、セレクトボックスで複数修正(選択)後、保存のサブミットで一括でUpdateさせたいのですが、上記のコードで修正すべき点を教えていただけますか?
配列やforeachが必要なのかとは思うのですが、、、、

※例外処理や、エスケープなどの事はここでは外して考えていただけますか?
まずは、動作させたいので、、、、


【追記編集】

<select name="data[]['dakoku']>
<select name="data[]['hour']>
<select name="data[]['minutes']>
<input type="hidden" name="data[]['id']" value="<?= $row['id']; ?>">


いろいろ見て回って、上記のようなname属性にしてみて、

$dbh->beginTransaction();
foreach($data as $dakoku) {
$stmt->bindParam(1, $data, PDO::PARAM_STR);

var_dump($data); // var_dump($dakoku[?]);
print_r($data); // print_r($dakoku[?]);


上記のような形にしてみると、当然なのでしょうが、、Arrayでズラズラ表示されたり$dakoku[??]に数字を入れればそこがとれたりはしましたが、、、

やはり、値としてはとれてないようです。

いろいろ書いてはみるのですが、一向に当たりません。
ご指摘よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

0

送信データの取り扱いにだいぶ悩まれているようなので、POST周りの動くサンプルコードを上げておきます。データベースの関連部分は書いてありません。
複数の出退勤データを一気に更新できる仕様です。
サンプルコードにはid項目がありませんので追加してみてください。
(見づらいソースコードですみません。)

丸ごとコピーしてtest.phpなどのファイル名を付けて文字コードUTF-8, 改行コードLFで保存してください。

送信されたフォームの配列データが$_POSTにどのように入って、値を取り出すにはどうしたら良いか書き換えたりして試してみてください。

質問に書かれたように、フォームのinputのname内の要素名の真ん中に空の[]があると配列が深くならずに以下のようになってしまいます。

<select name="data[]['dakoku']">
<select name="data[]['hour']">
<select name="data[]['minutes']">


$_POST['data'][0]['name'] = なまえ1
$_POST['data'][1]['dakoku'] = 出勤
$_POST['data'][2]['hour'] = 8
$_POST['data'][3]['minutes'] = 12
$_POST['data'][4]['name'] = なまえ2
$_POST['data'][5]['dakoku'] = 退勤
$_POST['data'][6]['hour'] = 19
$_POST['data'][7]['minutes'] = 56
$_POST['submit'] = 送信

添字に数字を入れると下のようになります。

<select name="data[0]['dakoku']">
<select name="data[0]['hour']">
<select name="data[0]['minutes']">

$_POST['data'][0]['name'] = 山田 太郎
$_POST['data'][0]['dakoku'] = 出勤
$_POST['data'][0]['hour'] = 07
$_POST['data'][0]['minutes'] = 12
$_POST['data'][1]['name'] = 山田 太郎
$_POST['data'][1]['dakoku'] = 退勤
$_POST['data'][1]['hour'] = 17
$_POST['data'][1]['minutes'] = 00

<?
    if( !empty( $_POST ) ) {
        //POSTされている場合には row[] に代入する
        $ary = $_POST['data'];
        $row_ct = count( $ary );//_POST['data']の要素数

        for( $i=0; $i<$row_ct; $i++ ) {
            //配列の添字が数値の場合は変数に代入して指定する
            // $row = $_POST; でも同じ結果になるが説明の為に個別に代入している
            $row['data'][$i]['name']   = $_POST['data'][$i]['name'];
            $row['data'][$i]['dakoku'] = $_POST['data'][$i]['dakoku'];
            $row['data'][$i]['hour']   = $_POST['data'][$i]['hour'];
            $row['data'][$i]['minutes']= $_POST['data'][$i]['minutes'];
        }
    } else {
        //POSTされていない場合(初期値)
        //本来はDBから取得する
        //テスト用データ
        $row = array( 
                    "data" => array(
                        array(
                            "name" => "山田 太郎",
                            "dakoku" => "出勤",
                            "hour" => "07",
                            "minutes" => "12" ),
                        array(
                            "name" => "山田 太郎",
                            "dakoku" => "退勤",
                            "hour" => "17",
                            "minutes" => "00" ),
                        array(
                            "name" => "鈴木 花子",
                            "dakoku" => "出勤",
                            "hour" => "07",
                            "minutes" => "59" ),
                        array(
                            "name" => "鈴木 花子",
                            "dakoku" => "休入",
                            "hour" => "12",
                            "minutes" => "01" ),
                        array(
                            "name" => "鈴木 花子",
                            "dakoku" => "休戻",
                            "hour" => "12",
                            "minutes" => "58" ),
                        array(
                            "name" => "鈴木 花子",
                            "dakoku" => "退勤",
                            "hour" => "21",
                            "minutes" => "03" )
                        )
                    );
        //row['data']の要素数
        $row_ct = count( $row['data'] );
    }
?>
<?php echo '<?xml version="1.0"?>'; ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja" dir="ltr">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>出退勤管理画面</title>
</head>
<body>
<div id="wrapper">
  <h1>出退勤管理</h1>
    <div id="contents">
      <div id="container">
        <br /><h2>出退勤</h2><br />
        <div class="alcenter">
          <form id="form1" name="form1" class="form1" method="post" action="">
<?
    print "件数:" . $row_ct ."件<br>\n";
    for( $no=0; $no<$row_ct; $no++ ) {
?>
      氏名<input type ='text' name='data[<?=$no;?>][name]' id='data[<?=$no;?>][name]' size='10' value='<?= $row['data'][$no]['name']; ?>' />
       打刻<input type ='text' name='data[<?=$no;?>][dakoku]' id='data[<?=$no;?>][dakoku]' size='10' value='<?= $row['data'][$no]['dakoku']; ?>' />
      <select name="data[<?=$no;?>][hour]">
<?
        for ($i = 0; $i <= 23; $i++) { 
            $str = sprintf( "%02d", $i );//書式設定
?>
        <option value="<?= $str; ?>"<? 
            if( $row['data'][$no]['hour']==$str ) { 
                print " selected"; 
            }?>><?= $str; ?></option>
<?
        }
?>
      </select>時 
      <select name="data[<?=$no;?>][minutes]">
<?
        for ($i = 0; $i <= 59; $i++) { 
            $str = sprintf( "%02d", $i );//書式設定
?>
        <option value="<?= $str; ?>"<? 
            if( $row['data'][$no]['minutes']==$str ) { 
                print " selected"; 
            }?>><?= $str; ?></option>
<?
        }
?>
      </select>分<br>
<?
    }
?>
<input type="submit" name="submit" id="submit" value="送信" />
<?
    if( !empty( $_POST ) ) {
/*
        // $_POST確認(出力する場合はコメントを外してください)
        print "<br><br>\n";
        print_r( $_POST );
        print "<br><br>\n";
*/
        print "<br><br>\n";
        //配列内の要素のアクセス名と値の一覧を出力する
        print "配列内容(&#36;_POST):<br>";
        dispPostData( "", "&#36;_POST", $_POST, 0 );
        print "<br><br>\n";

        print "配列内容(&#36;row):<br>";
        dispPostData( "", "&#36;row", $row, 0 );
        print "<br><br>\n";
    }

    //配列の中身を表示する関数
    // name: 配列の階層名
    // array_name:  配列の名前
    // ary:  配列
    // depth: 配列の深さ
    function dispPostData( $name=array(), $array_name="", $ary, $depth ) {
        foreach( $ary AS $key => $val ) {
            if( is_array( $val ) ) {
                //$val が配列の場合
                $name2 = $name;
                $name2[] = $key;//要素名リストにキー名を追加する
                //配列なら再帰処理を行う
                dispPostData( $name2, $array_name, $val, $depth + 1 );
            } else {
                //$val が値の場合
                for( $i = 0; $i < $depth; $i++ ) {
                    print "&nbsp;&nbsp;";//インデント
                }
                print $array_name;//配列名の出力
                if( !empty( $name ) ) {
                    //配列の要素名の出力
                    foreach( $name AS $val2 ) {
                        if( preg_match("/[^0-9\s]/", $val2 ) ) {
                            print "['" . $val2 . "']";//文字列
                        } else {
                            print "[" . $val2 . "]";//数字
                        }
                    }
                }
                if( preg_match("/[^0-9\s]/", $key ) ) {
                    print "['" . $key . "']";//文字列
                } else {
                    print "[" . $key . "]";//数字
                }
                //値の出力
                print " = " . $val . "<br>\n";
            }
        }
    }
?>
          </form>
        </div>
      </div>
    </div>
<!-- ▲ Contents -->

<!-- ▽ Footer -->
    <div id="foot">
      CopyFree 2016 HogeHage.co.,Ltd. All Rights Reserved.</div>
    </div>
<!-- ▲ Footer -->

  </div>
<!-- ▲ Wrapper -->
</body>
</html>


動作確認: Windows7 Firefox 44.0 / Wadax WX共用サーバー

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/15 21:28

    これだけのコードをありがとうございます!
    いろいろやってみるのに時間かかるかもしれないので、一度質問はBAつけておきます!

    キャンセル

0

こっちはどうですか?
ちなみにダブルクオーテーションの区切りがおかしかったですよ。

<select name="data['dakoku'][]">
<select name="data['hour'][]">
<select name="data['minutes'][]">
<input type="hidden" name="data['id'][]" value="<?= $row['id']; ?>">


参考:PHP:POSTの値を、多次元配列にしたい。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/13 02:39

    解答ありがとうございます。
    検証してみます。

    キャンセル

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

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

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