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

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

ただいまの
回答率

87.90%

素材を比較したidと共通項目数をデータベースに格納したい

受付中

回答 1

投稿 編集

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

score 8

「まだ回答を求めています」

質問に「まだ回答を求めています」と表示し、閲覧者に状況を知らせることで、新たな回答を得られやすくなります。以下のような場合にご利用ください。
もらった回答を調べてみたが、問題を解決できなかった
質問投稿から時間がたってしまった
ボタンを押してから1週間が経過するか、新たな回答を得られると自動で非表示になります。

始めて質問いたしますphp初心者です。
どぞよろしくお願いいたします。

前提・実現したいこと

PHPで素材の特徴の共通項目数を求めるシステムを作っています。

データベース'compare'のテーブル'answers'に既にいくつかの回答(データ)が入っている状態で質問formから受け取った質問の回答をテーブル'answers'のデータと比較し幾つ共通項目があるかをデータベース'compare'の'result'テーブルのidナンバー(idフィールド)と共通項目数(commonsフィールド)を格納することを目指いしています。

発生している問題・エラーメッセージ

idと共通項目数の値を求めるところまではできているよう思いますがそれらの値をresultテーブルに格納することができません。

printと<br>等を使って表示させるとそれぞれの数字は問題なく出ています。
いろいろ試しエラーメッセージが出ることはないのですが値がテーブルに格納されるという結果が得られません。

御助力いただけますようお願いいたします。

該当のソースコード

質問form

<html>
<head>
<meta charset="UTF-8">
<title>特徴マッチ度</title>
</head>
<body>
<form method="post" action="question_check.php">
熱に強い<br/>
<input type="radio" name="q1" value="1">Yes <input type="radio" name="q1" value="2">No<br/>

柔軟性がある<br/>
<input type="radio" name="q2" value="1">Yes <input type="radio" name="q2" value="2">No<br/>

1、手で破く事ができる2、手で破く事はできない3鋏を使えば切れる4、鋏でも切れない<br/>
<input type="radio" name="q3" value="1">1 <input type="radio" name="q3" value="2">2<input type="radio" name="q3" value="3">3 <input type="radio" name="q3" value="4">4<br/>
<br/>
<input type="button" onclick="history.back()" value="戻る">
<input type="submit" value="OK">
</form>
</body>
</html


これの回答チェックをし

<html>
<head>
<meta charaset="UTF8">
<title>回答チェック</title>
</head>
<body>

<?php
$question1=$_POST['q1'];
$question2=$_POST['q2'];
$question3=$_POST['q3'];

if($question1=='')
{
        print'1番の回答がありません。<br/>';
}
else
{
        print'1番の回答';
        print$question1;
        print'<br/>';
}
if($question2=='')
{
        print'2番の回答がありません。<br/>';
}
if (isset($_POST["q2"])) 
{
        print'2番の回答';
        print$question2;
        print'<br/>';
}

if($question3=='')
{
        print'3番の回答がありません。<br/>';
}
else
{
        print'3番の回答';
        print$question3;
        print'<br/>';
}

if($question1==''||$question2==''||$question3=='')
{
    print'<form>';
    print'<input type="button" onclick="history.back()"value="戻る"    >';
    print'</form>';
}
else
{
    print'<form method="post" action="compair.php">';
        print'<input type="hidden" name="q1" value="'.$question1.'">';
        print'<input type="hidden" name="q2" value="'.$question2.'">';
        print'<input type="hidden" name="q3" value="'.$question3.'">';
        print'<br/>';
        print'<input type="button" onclick="history.back()" value="戻る">';
        print'<input type="submit" value="OK">';
        print'</form>';
}
?>
</body>
</html>


これを

試したこと

<html>
<head>
<meta charaset="UTF8">
<title>素材比較</title>
</head>
<body>

<?php

$question1=$_POST['q1'];
$question2=$_POST['q2'];
$question3=$_POST['q3'];

$dsn='mysql:dbname=compare;host=localhost';
$user='root';
$password='';
$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql='SELECT code,r1,r2,r3 FROM answers WHERE 1';
$stmt=$dbh->prepare($sql);
$stmt->execute();

$dbh=null;

//回答が共通する計を求める。

while(true)
{
    $rec=$stmt->fetch(PDO::FETCH_ASSOC);
    if($rec==false)
    {
             break;
    }

    if($rec['r1']==$question1)
        {                       
            $s=$s+1;
        }
        else
        {
            $s=0;
        }
    if($rec['r2']==$question2)
        {
            $s=$s+1;
        }
    if($rec['r3']==$question3)
        {
            $s=$s+1;
        }
//試した一例

$dsn='mysql:dbname=compare;host=localhost';
$user='root';
$password='';
$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql = "INSERT INTO results (id, commons) VALUES (:id, :commons)";

$stmt = $dbh->prepare($sql);

$id= array($rec['code']=>$s);

// foreachで挿入する値を1つずつループ処理
foreach ($id as $key => $s) {

  // 連想配列のキーを :name に、値を :population にセットし、executeでSQLを実行
  $stmt->execute(array(':id' => $key, ':commons' => $s));

}
//ここまで一例

//上記の一例の部分を書かずにこの下のprintによって表示される値の様にをデータベースのテーブルresultsのフィールドidとフィールドcommonsに格納したい。

print" |";
print $rec['code'];
print" | ";
print $s;
print" |";
print '<br/>';

//これより上。



$s=0;
}

//新規の素材の回答をテーブルanswersの最後に格納。

$dsn='mysql:dbname=compare;host=localhost';
$user='root';
$password='';
$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql='INSERT INTO answers(r1,r2,r3) VALUES (?,?,?)';
$stmt=$dbh->prepare($sql);
$data[]=$question1;
$data[]=$question2;
$data[]=$question3;
$stmt->execute($data);
$dch=null;
?>

</body>
</html>

補足情報

サーバの種類: MySQL
サーバのバージョン: 5.6.20
Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15

どうぞ宜しくお願いいたします。
始めて質問いたしますphp初心者です。
どぞよろしくお願いいたします。

前提・実現したいこと

PHPで素材の特徴の共通項目数を求めるシステムを作っています。

データベース'compare'のテーブル'answers'に既にいくつかの回答(データ)が入っている状態で質問formから受け取った質問の回答をテーブル'answers'のデータと比較し幾つ共通項目があるかをデータベース'compare'の'result'テーブルのidナンバー(idフィールド)と共通項目数(commonsフィールド)を格納することを目指いしています。

発生している問題・エラーメッセージ

idと共通項目数の値を求めるところまではできているよう思いますがそれらの値をresultテーブルに格納することができません。

printと<br>等を使って表示させるとそれぞれの数字は問題なく出ています。
いろいろ試しエラーメッセージが出ることはないのですが数字がテーブルに格納されるという結果が得られません。

御助力いただけますようお願いいたします。

該当のソースコード

質問form

<html>
<head>
<meta charset="UTF-8">
<title>特徴マッチ度</title>
</head>
<body>
<form method="post" action="question_check.php">
熱に強い<br/>
<input type="radio" name="q1" value="1">Yes <input type="radio" name="q1" value="2">No<br/>

柔軟性がある<br/>
<input type="radio" name="q2" value="1">Yes <input type="radio" name="q2" value="2">No<br/>

1、手で破く事ができる2、手で破く事はできない3鋏を使えば切れる4、鋏でも切れない<br/>
<input type="radio" name="q3" value="1">1 <input type="radio" name="q3" value="2">2<input type="radio" name="q3" value="3">3 <input type="radio" name="q3" value="4">4<br/>
<br/>
<input type="button" onclick="history.back()" value="戻る">
<input type="submit" value="OK">
</form>
</body>
</html


これの回答チェックをし

<html>
<head>
<meta charaset="UTF8">
<title>回答チェック</title>
</head>
<body>

<?php
$question1=$_POST['q1'];
$question2=$_POST['q2'];
$question3=$_POST['q3'];

if($question1=='')
{
        print'1番の回答がありません。<br/>';
}
else
{
        print'1番の回答';
        print$question1;
        print'<br/>';
}
if($question2=='')
{
        print'2番の回答がありません。<br/>';
}
if (isset($_POST["q2"])) 
{
        print'2番の回答';
        print$question2;
        print'<br/>';
}

if($question3=='')
{
        print'3番の回答がありません。<br/>';
}
else
{
        print'3番の回答';
        print$question3;
        print'<br/>';
}

if($question1==''||$question2==''||$question3=='')
{
    print'<form>';
    print'<input type="button" onclick="history.back()"value="戻る"    >';
    print'</form>';
}
else
{
    print'<form method="post" action="compare.php">';
        print'<input type="hidden" name="q1" value="'.$question1.'">';
        print'<input type="hidden" name="q2" value="'.$question2.'">';
        print'<input type="hidden" name="q3" value="'.$question3.'">';
        print'<br/>';
        print'<input type="button" onclick="history.back()" value="戻る">';
        print'<input type="submit" value="OK">';
        print'</form>';
}
?>
</body>
</html>


これを

試したこと(compare.php)

<html>
<head>
<meta charaset="UTF8">
<title>素材比較</title>
</head>
<body>

<?php

$question1=$_POST['q1'];
$question2=$_POST['q2'];
$question3=$_POST['q3'];

$dsn='mysql:dbname=compare;host=localhost';
$user='root';
$password='';
$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql='SELECT code,r1,r2,r3 FROM answers WHERE 1';
$stmt=$dbh->prepare($sql);
$stmt->execute();

$dbh=null;

//回答が共通する計を求める。

while(true)
{
    $rec=$stmt->fetch(PDO::FETCH_ASSOC);
    if($rec==false)
    {
             break;
    }

    if($rec['r1']==$question1)
        {                       
            $s=$s+1;
        }
        else
        {
            $s=0;
        }
    if($rec['r2']==$question2)
        {
            $s=$s+1;
        }
    if($rec['r3']==$question3)
        {
            $s=$s+1;
        }
//試した一例

$dsn='mysql:dbname=compare;host=localhost';
$user='root';
$password='';
$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql = "INSERT INTO results (id, commons) VALUES (:id, :commons)";

$stmt = $dbh->prepare($sql);

$id= array($rec['code']=>$s);

// foreachで挿入する値を1つずつループ処理
foreach ($id as $key => $s) {

  // 連想配列のキーを :name に、値を :population にセットし、executeでSQLを実行
  $stmt->execute(array(':id' => $key, ':commons' => $s));

}
//ここまで一例

//上記の一例の部分を書かずにこの下のprintによって表示される値の様にをデータベースのテーブルresultsのフィールドidとフィールドcommonsに格納したい。

print" |";
print $rec['code'];
print" | ";
print $s;
print" |";
print '<br/>';

//これより上。



$s=0;
}

//新規の素材の回答をテーブルanswersの最後に格納。

$dsn='mysql:dbname=kachikan;host=localhost';
$user='root';
$password='';
$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql='INSERT INTO answers(r1,r2,r3) VALUES (?,?,?)';
$stmt=$dbh->prepare($sql);
$data[]=$question1;
$data[]=$question2;
$data[]=$question3;
$stmt->execute($data);
$dch=null;
?>

</body>
</html>

補足情報

サーバの種類: MySQL
サーバのバージョン: 5.6.20
Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15

どうぞ宜しくお願いいたします。

エラーはでていません。

テーブル'answers'はフィールドがcode(int11)AI主,r1(int11),r2(int11),r3(int11)です。
テーブル'results'はフィールドid(int11)主,commons(int11)です。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2017/07/21 14:24

    エラーがあれば追記願います(実際に実行されたSQLに何か問題があるかも)。また、それぞれのテーブル定義はありますか?

    キャンセル

  • pintxos

    2017/07/28 00:32

    ご質問頂いていたのに本文の編集の方でお答えしていました。大変失礼いたしました。エラーはでていません。 テーブル'answers'はフィールドがcode(int11)AI主,r1(int11),r2(int11),r3(int11)です。 テーブル'results'はフィールドid(int11)主,commons(int11)です。

    キャンセル

回答 1

+1

SQL実行時のエラーを確認しないと詳細はわかりませんが、おかしいと思ったところを指摘します。

$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql = "INSERT INTO results (id, commons) VALUES (:id, :commons)";

$stmt = $dbh->prepare($sql);

$id= array($rec['code']=>$s);

// foreachで挿入する値を1つずつループ処理
foreach ($id as $key => $s) {

  // 連想配列のキーを :name に、値を :population にセットし、executeでSQLを実行
  $stmt->execute(array(':id' => $key, ':commons' => $s));

}

この部分、executeをループさせていますが、これだと動かないと思います。
生成されたステートメントに対して、値のバインドは1回のみじゃないですか?

なので、こうじゃないかと私は思います。

$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql = "INSERT INTO results (id, commons) VALUES (:id, :commons)";

$id= array($rec['code']=>$s);

// foreachで挿入する値を1つずつループ処理
foreach ($id as $key => $s) {
  // ステートメントの生成は毎回行わないと・・・。
  $stmt = $dbh->prepare($sql);
  // 連想配列のキーを :name に、値を :population にセットし、executeでSQLを実行
  $stmt->execute(array(':id' => $key, ':commons' => $s));

}

 コメント頂いた部分について

なるほど、仕様はわかりました。
そうなると、resultsテーブルへ格納するレコードは、while(true)の各ループで1件だけですよね。
そうであれば、foreachはいらないです。

根本的にこれという原因はソースコードから見つけられませんでしたが、resultsにデータが入っていないということと、resultsテーブルへの格納SQLが実行されているのであれば、必ずエラーが出ています。
apacheのerror_logに吐き出されるはずなので、そちらを確認してください。

とりあえず、resultへのinsert処理で値のバインド処理が省略されていた形でしたので、明示的にバインドするソースに書き換えてみました。
こちらでどうなるか、試してみていただけないでしょうか?

<html>
<head>
<meta charaset="UTF8">
<title>素材比較</title>
</head>
<body>

<?php

$question1=$_POST['q1'];
$question2=$_POST['q2'];
$question3=$_POST['q3'];

$dsn='mysql:dbname=compare;host=localhost';
$user='root';
$password='';
$dbh=new PDO($dsn, $user, $password);
$dbh->query('SET NAMES utf8');

$sql='SELECT code,r1,r2,r3 FROM answers WHERE 1';
$stmt=$dbh->prepare($sql);
$stmt->execute();

$dbh=null;

//回答が共通する計を求める。

while(true)
{
    $rec=$stmt->fetch(PDO::FETCH_ASSOC);
    if($rec==false)
    {
             break;
    }

    if($rec['r1']==$question1)
        {
            $s=$s+1;
        }
        else
        {
            $s=0;
        }
    if($rec['r2']==$question2)
        {
            $s=$s+1;
        }
    if($rec['r3']==$question3)
        {
            $s=$s+1;
        }
//試した一例
$sql = "INSERT INTO results (id, commons) VALUES (:id, :commons)";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':id', $rec['code'], PDO::PARAM_INT);
$stmt->bindParam(':commons', $s, PDO::PARAM_INT);
$stmt->execute();
//ここまで一例

//上記の一例の部分を書かずにこの下のprintによって表示される値の様にをデータベースのテーブルresultsのフィールドidとフィールドcommonsに格納したい。

print" |";
print $rec['code'];
print" | ";
print $s;
print" |";
print '<br/>';

//これより上。



$s=0;
}

//新規の素材の回答をテーブルanswersの最後に格納。
$sql='INSERT INTO answers(r1,r2,r3) VALUES (?,?,?)';
$stmt=$dbh->prepare($sql);
$data[]=$question1;
$data[]=$question2;
$data[]=$question3;
$stmt->execute($data);
$dch=null;
?>

</body>
</html>

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/21 22:47

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

    ご指摘の内容を反映してみたところresultsテーブルのidフィールドとcommonsフィールドに各1つ値が入りました。
    ただ私が求めているものとは少し違っていました。
    私の書き方が要領を得てないのでわかりにくいかと思います(スミマセン)。

    求めている結果と言うのは、
    テーブル'answers'にすでに3つの素材の特徴の回答が下記の様に入っていたとします。

    code | r1 | r2 | r3 |
    1 | 2 | 1 | 4 |
    2 | 1 | 2 | 3 |
    3 | 2 | 3 | 1 |

    新規に1つの素材(code 4)の回答(2,2,4)をformから送った場合

    code 4とcode 1の共通項目はr1とr3で共通項目数は2。
    code 4とcode 2の共通項目はr2のみで共通項目数は1。
    code 4とcode 3の共通項目はr1のみで共通項目数は1。

    テーブル'results'には

    id | commons|
    1 | 2 |
    2 | 1 |
    3 | 1 |

    という結果が格納されてほしく(codeとidの内容は同じで同一の素材です)

    テーブル'answers'にはcode 4の回答を最後に格納して

    code | r1 | r2 | r3 |
    1 | 2 | 1 | 4 |
    2 | 1 | 2 | 3 |
    3 | 2 | 3 | 1 |
    4 | 2 | 2 | 4 |

    と言う結果になることを求めています。

    ご指摘を頂いた部分の理解を深めて自分自身でも解決を模索いたしますが、さらにご助言頂けるようでしたら幸いです。

    どうぞよろしくお願いいたします。






    キャンセル

  • 2017/07/25 02:01

    ご回答有難うございます。
    また返信が遅くなりまして大変失礼しました。

    >while(true)の各ループで1件だけですよね。
    私がご質問の意味を理解しているかどうかが不安ですが、各ループ id1件、共通項目数1件になります。

    今回ご提案頂いたソースをソースを試させて頂いた結果ですが、テーブル 'results'には何も格納されませんでした。

    apacheのerror_logですが知識がなく今の所読み解けておりません。
    この辺りかなと言うところを下記に記します。
    お助けいただければ幸いです。

    [Tue Jul 25 01:25:24.365393 2017] [ssl:warn] [pid 2864:tid 276] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
    [Tue Jul 25 01:25:24.412193 2017] [core:warn] [pid 2864:tid 276] AH00098: pid file C:/xampp/apache/logs/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
    [Tue Jul 25 01:25:24.724194 2017] [ssl:warn] [pid 2864:tid 276] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
    [Tue Jul 25 01:25:24.848994 2017] [mpm_winnt:notice] [pid 2864:tid 276] AH00455: Apache/2.4.10 (Win32) OpenSSL/1.0.1i PHP/5.5.15 configured -- resuming normal operations
    [Tue Jul 25 01:25:24.848994 2017] [mpm_winnt:notice] [pid 2864:tid 276] AH00456: Apache Lounge VC11 Server built: Jul 17 2014 11:50:08
    [Tue Jul 25 01:25:24.848994 2017] [core:notice] [pid 2864:tid 276] AH00094: Command line: 'c:\\xampp\\apache\\bin\\httpd.exe -d C:/xampp/apache'
    [Tue Jul 25 01:25:24.848994 2017] [mpm_winnt:notice] [pid 2864:tid 276] AH00418: Parent: Created child process 9888
    [Tue Jul 25 01:25:25.535395 2017] [ssl:warn] [pid 9888:tid 288] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
    [Tue Jul 25 01:25:25.956596 2017] [ssl:warn] [pid 9888:tid 288] AH01909: www.example.com:443:0 server certificate does NOT include an ID which matches the server name
    [Tue Jul 25 01:25:25.987796 2017] [mpm_winnt:notice] [pid 9888:tid 288] AH00354: Child: Starting 150 worker threads.

    どうぞよよろしくお願いいたします。


    キャンセル

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

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

関連した質問

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