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

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

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

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

PHP

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

Q&A

解決済

1回答

968閲覧

リロードするといいねの数が0になってしまう

hmom

総合スコア3

MySQL

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

PHP

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

0グッド

0クリップ

投稿2021/05/31 05:04

編集2021/05/31 07:13

###やりたいこと

現在いいね機能を実装中です。
アイコンをクリック後、アイコンの色を塗り潰し、データをMySQLに反映させて、いいねの数を表示することはできたのですが、ページをリロードするといいねの数の表示が0になってしまいます。
(データベースの数は反映された状態でアイコンの色は塗り潰されたままだが、数の表示が0になる)

リロードしてもいいねの数を保持したまま表示できるようにしたいです。(いいね機能自体ではなく、いいねの数を表示させるためのコードに問題があると予想しています。)

###エラー文と原因だと考えている点
######エラー文

PHP Notice: Undefined variable: value

######原因だと考えている部分

$p_id = $value['post_id'];

上記のコード部分に対してエラー文で$valueが定義されていないと出ているので、投稿文を表示させる部分で['post_id']がうまく取得できていないことが原因だと思うのですが、どのようにすれば['post_id']を取得できるかを知りたいです。
(HTML部分でforeach( $message_array as $value )を定義しており、読み込みの順番が先に来ていることが原因かなと予想しているのですが、どうすれば後に読み込ませられるのかが分かりませんでした)

本当の原因は予想と違うかもしれませんが、その際は、ご指摘いただけると助かります。

初心者のため、質問の文言等、曖昧な点があると思いますが、解決法を教えていただけると嬉しいです。

よろしくお願いします。

###テーブル構造とカラム
テーブル構造
テーブル Members

+-------------------+--------------+------+-----+-------------------+-----------------------------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------------+--------------+------+-----+-------------------+-----------------------------------------------+ | member_id | int | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | NULL | | | email | varchar(255) | NO | | NULL | | | password | varchar(100) | NO | | NULL | | | icon | varchar(100) | YES | | NULL | | | member_created_at | datetime | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED | | member_update_at | datetime | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP | +-------------------+--------------+------+-----+-------------------+-----------------------------------------------+

テーブル Post

+-----------+--------------+------+-----+-------------------+-------------------+ | Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+-----+-------------------+-------------------+ | post_id | int | NO | PRI | NULL | auto_increment | | member_id | int | NO | | NULL | | | message | varchar(560) | NO | | NULL | | | post_date | datetime | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED | +-----------+--------------+------+-----+-------------------+-------------------+

テーブル Likes

+-----------------+----------+------+-----+-------------------+-----------------------------------------------+ | Field | Type | Null | Key | Default | Extra | +-----------------+----------+------+-----+-------------------+-----------------------------------------------+ | likes_id | int | NO | PRI | NULL | auto_increment | | post_id | int | NO | MUL | NULL | | | member_id | int | NO | | NULL | | | like_created_at | datetime | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED | | like_update_at | datetime | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP | +-----------------+----------+------+-----+-------------------+-----------------------------------------------+

###function.php

//いいねを取得 function getGood($p_id){ var_dump(' いいねを取得します'); try { $dbh = dbConnect(); $sql = 'SELECT * FROM Likes WHERE post_id = :p_id'; $data = array(':p_id' => $p_id); // クエリ実行 $stmt = queryPost($dbh, $sql, $data); if($stmt){ return $stmt->fetchAll(); }else{ return false; } } catch (Exception $e) { error_log('エラー発生:'.$e->getMessage()); } } //いいねした情報の有無 function isGood($u_id, $p_id){ var_dump('いいねした情報があるか確認'); var_dump('ユーザーID'.$u_id); var_dump('投稿ID:'.$p_id); try { $dbh = dbConnect(); $sql = 'SELECT * FROM Likes WHERE post_id = :p_id AND member_id = :u_id'; $data = array(':u_id' => $u_id, ':p_id' => $p_id); // クエリ実行 $stmt = queryPost($dbh, $sql, $data); if($stmt->rowCount()){ var_dump('お気に入りです'); return true; }else{ var_dump('特に気に入ってません'); return false; } } catch (Exception $e) { error_log('エラー発生:' . $e->getMessage()); } }

index.php

<php? //共通変数・関数ファイルを読込み require_once 'function.php'; try { // データベースに接続 $db = dbConnect(); // セッションを変数に格納 $member_id = $_SESSION["member_id"]; // 全ての投稿を取得 $sql = "SELECT * FROM Post LEFT OUTER JOIN Members ON Post.member_id = Members.member_id ORDER BY post_date DESC"; $res = $db->query($sql); if( $res ) { $message_array = $res->fetchAll(PDO::FETCH_ASSOC); } // いいね数取得 $p_id = $value['post_id']; $dbPostGoodNum = count(getGood($p_id)); // ログイン者の情報を取得 $sql2 = "SELECT * FROM Members WHERE member_id = :member_id"; // bindする(プリペアドステートメント) $res2 = $db->prepare($sql2); $res2->bindValue(":member_id","$member_id",PDO::PARAM_STR); $res2->execute(); foreach ($res2 as $row){ $row['name']; // name } } catch (PDOException $e) { $error_message[] = 'データの読み込みに失敗しました。'; $error_message[] = $sql; $e->getMessage(); //でエラー内容を参照可能(デバッグ時のみ表示) echo $e->getMessage(); } ?> <!-- 投稿文部分のHTML --> <div class="all_post"> <section> <?php if( !empty($message_array) ){ ?> <?php foreach( $message_array as $value ){ ?> <article> <div class="info"> <h2><div class="username"><?php echo $value['name']; ?></div></h2> <h3><div class="member_id">id:<?php echo $value['member_id']; ?></div></h3> <time><?php echo date('Y年m月d日 H:i', strtotime($value['post_date'])); ?></time> </div> <p><?php echo $value['message']; ?></p> <section class="post" data-postid="<?php echo sanitize($value['post_id']); ?>"> <div class="btn-good <?php if(isGood($_SESSION['member_id'], $value['post_id'])) echo 'active'; ?>"> <!-- 自分がいいねした投稿にはハートのスタイルを常に保持する --> <i class="fa-heart fa-lg px-16 <?php if(isGood($_SESSION['member_id'],$value['post_id'])){ //いいね押したらハートが塗りつぶされ る echo ' active fas'; }else{ //いいねを取り消したらハートのスタイルが取り消される echo ' far'; }; ?>"></i><span><?php echo $dbPostGoodNum; ?></span> </div> </section> </article> <?php } ?> <?php } ?> </section> </div>

ajax.php

<?php session_start(); require_once 'function.php'; // postがある場合 if(isset($_POST['postId'])){ $p_id = $_POST['postId']; try{ //DB接続 $dbh = dbConnect(); // Likesテーブルから投稿IDとユーザーIDが一致したレコードを取得するSQL文 $sql = 'SELECT * FROM Likes WHERE post_id = :p_id AND member_id = :u_id'; $data = array(':p_id' => $p_id, 'u_id' => $_SESSION['member_id']); // クエリ実行 $stmt = queryPost($dbh, $sql, $data); $resultCount = $stmt->rowCount(); // レコードが1件でもある場合 if(!empty($resultCount)){ // レコードを削除する $sql = 'DELETE FROM Likes WHERE post_id = :p_id AND member_id = :u_id'; $data = array(':p_id' => $p_id, ':u_id' => $_SESSION['member_id']); // クエリ実行 $stmt = queryPost($dbh, $sql, $data); echo count(getGood($p_id)); }else{ // レコードを挿入する $sql = 'INSERT INTO Likes (post_id, member_id, like_created_at) VALUES (:p_id, :u_id, :date)'; $data = array(':p_id' => $p_id, ':u_id' => $_SESSION['member_id'], ':date' => date('Y-m-d H:i:s')); // クエリ実行 $stmt = queryPost($dbh, $sql, $data); echo count(getGood($p_id)); var_dump(count(getGood($p_id))); } }catch(Exception $e){ error_log('エラー発生:'.$e->getMessage()); } } ?>

likes_test.js

$(function(){ var $good = $('.btn-good'), //いいねボタンセレクタ goodPostId; //投稿ID $good.on('click',function(e){ e.stopPropagation(); var $this = $(this); //カスタム属性(postid)に格納された投稿ID取得 goodPostId = $this.parents('.post').data('postid'); $.ajax({ type: 'POST', url: 'Likes/ajax.php', //post送信を受けとるphpファイル data: { postId: goodPostId} //{キー:投稿ID} }).done(function(data){ console.log('Ajax Success'); // いいねの総数を表示 $this.children('span').html(data); // いいね取り消しのスタイル $this.children('i').toggleClass('far'); //空洞ハート // いいね押した時のスタイル $this.children('i').toggleClass('fas'); //塗りつぶしハート $this.children('i').toggleClass('active'); $this.toggleClass('active'); }).fail(function(msg) { console.log('Ajax Error'); }); }); });

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

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

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

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

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

m.ts10806

2021/05/31 05:10

DBのほうもマークダウンcodeされたほうが見やすいのでご対応願います
m.ts10806

2021/05/31 05:12

$valueという変数はどこにも定義されることなくいきなり連想配列として参照してますね。 どこで定義したどんなデータを参照したいのですか?
hmom

2021/05/31 08:09 編集

回答ありがとうございます! DB部分もマークダウン記法にすると見やすいんですね。 ご指摘ありがとうございます。 $value は HTML部分の3行目の部分で出てきていて、こちらで定義していると思っていたのですが、このコードでは定義されていないのでしょうか? この部分を $p_id = $value['post_id']; よりも前に定義するにはどうすればいいのかが分からず質問させていただいた状態です。 初歩的な質問ですみません。 <!-- 投稿文部分のHTML --> <div class="all_post"> <section> <?php if( !empty($message_array) ){ ?> <?php foreach( $message_array as $value ){ ?>      ... <?php } ?> <?php } ?> </section>
退会済みユーザー

退会済みユーザー

2021/05/31 08:11

助言のために第三者に再現してもらいたいときは、隠さず使っているコードをすべて示すと良いです。
guest

回答1

0

ベストアンサー

「いいね」する、という操作は、何に対してどのように行っているのでしょう?
とくにFORM要素があるようでもないし、ajaxにて送信しているわけでもない。
そして、その「いいね」したときの記録はどのようにしているのでしょうか。

この下り:

php

1 // 全ての投稿を取得 2 $sql = "SELECT * FROM Post LEFT OUTER JOIN Members ON Post.member_id = Members.member_id ORDER BY post_date DESC"; 3 $res = $db->query($sql); 4 5 if( $res ) { 6 $message_array = $res->fetchAll(PDO::FETCH_ASSOC); 7 } 8 9 // いいね数取得 10 $p_id = $value['post_id']; 11 $dbPostGoodNum = count(getGood($p_id));

投稿のすべてを取得するクエリーからじゃ、どう頑張ってもいいね数は取れないと思いますよ。
コピペで作るにしても雑すぎる。

コードを書いてないけど、$value['post_id']はもしかして$_GET['post_id']と勘違いしたとか?


憶測の上に推察しますが、
LIKESテーブルに「いいね」を記録するものだとした場合、
記録に係る処理がどこにもなさそうなので、
記録してないんだからカウントもゼロになりそうって思いましたが、
察するに、
$dbPostGoodNumにいいねが入っている前提の設計でしょうか。
その抽出箇所は、

php

1 // いいね数取得 2 $p_id = $value['post_id']; 3 $dbPostGoodNum = count(getGood($p_id));

ですが、この時点での$valueは未定義だと思います。
「PHP Notice: Undefined variable: value」が出ているのはそういうことかと。

例えば、こっからはSQLの話ですが、

sql

1SELECT post_id, COUNT(like_id) 2FROM likes 3GROUP BY post_id 4ORDER BY post_id;

であれば、投稿ごとのいいねの数をカウントできそうですね。

投稿と一緒にいいね数を取得するのに、

sql

1SELECT p.post_id, p.member_id, m.name, p.message, p.post_date, l.cnt 2FROM post AS p 3LEFT OUTER JOIN members AS m ON p.member_id = m.member_id 4LEFT OUTER JOIN ( 5 SELECT post_id, COUNT(like_id) AS cnt 6 FROM likes 7 GROUP BY post_id 8) AS l on p.post_id = l.post_id 9ORDER BY p.post_date;

みたいになるんですかね、あくまで机上のSQL。

function getGood() にて、
LIKESテーブルの全行を配列に読み込もうとしていますが、
PHPの配列上に何十行何百行何千行読み込むつもりでしょうか、
その上で配列を走査していいね数をカウントするくらいなら、
通常その手の集計はSQLでデータベースに行わせてください。
適切にインデックスも施されていれば、
サクッとカウントくらいできます。

投稿2021/05/31 05:36

編集2021/05/31 05:45
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

hmom

2021/05/31 08:01

ご回答ありがとうございます。 いいね機能自体はうまく機能していて、post_id がうまく取得できないことが原因でいいねの数がカウント できていないのかなと考えた為、いいね機能部分のファイルがあると分かりにくくなってしまうかと思って、ファイルを省略してしまったのですが、余計に分かりにくくなってしまったようですみません。 ajaxといいね機能部分のphpファイルも追加しました。 いいねの数をカウントする場合は、SQLでCOUNTを使うといいんですね。 コードまで教えていただきありがとうございます。 $p_id = $value['post_id']; この部分ですが、下記のように index.phpのHTML部分の3行目以降で定義していると考えているのですが、これをどうすれば$p_id = $value['post_id'];の前で定義できるのかが分からず、質問した状態です。 定義という言葉自体の使い方が間違っていたらすみません。 $value['post_id']の値が取得できれば、count(getGood($p_id))でいいねの数が取得できるのかなと予想してました。この予想自体が間違っていたら、教えていただけると嬉しいです。 色々説明不足で分かりにくく申し訳ありませんが、ご返答いただけると嬉しいです。 <!-- 投稿文部分のHTML --> <div class="all_post"> <section> <?php if( !empty($message_array) ){ ?> <?php foreach( $message_array as $value ){ ?> ... ... <?php } ?> <?php } ?> </section>
退会済みユーザー

退会済みユーザー

2021/05/31 08:10

foreachループで$value['post_id']ごとにいいね数を集計するのは、 投稿件数が少ないうちは気づきにくいですが、100とか1000とか10000とかなってくるとかなり遅くなるかと。 投稿全部→投稿個別にいいね数カウント、という流れではなく、 クエリーを駆使すれば、 いいね数を集計し終わった状態の投稿全部、を取得することが出来ることを、 回答内に示したSQLを使えばできます。 インデックスが適切に施されてあれば、何万とかのオーダーでも十分まともに動くと思いますよ。 ($message_array に収まる結果を求めるクエリーを、試しに私のSQLで置き換えてみてください。)
hmom

2021/05/31 09:22

早速のご回答ありがとうございます。 カウントの方法で速度が変わってきてしまうんですね。 教えていただいたSQLを当てはめて試してみたいと思います!
hmom

2021/06/01 06:12

教えていただいたSQLでいいね数の表示を保てるようになりました。 カウントはSQLで行う方が良いなど、重要な事柄も教えていただき助かりました。 また、機会がありましたら、ご指導よろしくお願いします。 今回はありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問