😁
PHPとajax(jquery)でいいね機能実装
学習日記 20230930
今回はタイトルの件をまとめてみました。
ある投稿サービスを作成している人間です。(開発の実務は未経験で、学習中の人間です)
※使用しているPHPフレームワークは"パーフェクトPHP"という書籍で扱っている
独自のフレームワークになります。
なるべく上記の独自な書き方の箇所は直しますが、キリがないと判断した場合、
処理全体のイメージだけでもつかんでいただければと思います、
使用するもの
今回は下記の環境で実施します。
- PHP 8.2
- jquery 3.6.0
- MySQL(phpmyadmin)
- fontawesome
- レンタルサーバ上
処理の流れ
- ハートアイコンのクリックでイベント発火
- クリックした要素をthisで取得、付随するカスタムデータ属性の値も取得
- ajaxの処理
- 取得した値をphpファイルに渡す
- ajaxから取得した値とSESSIONから取得した値のバリデーション
- どちらも通ったなら、既にいいねしているか判別
- 5の結果により、DBへの追加か削除も処理をする。
- 処理結果をレスポンス用データ変数に格納
- json形式でajaxに返却
- ajax側でレスポンスを受け取る
- レスポンスの中身にある"追加"か"削除"かを表すデータを取得して、処理を分ける
- 追加、削除したかによって、htmlにおけるクラスのつけ外しをjqueryで行う
- レスポンスの中身にあるいいね数データも取得して、html側に反映
- html側では、いいねしているかといいね数を既に表示する処理をphpで記述する
※(14はクリックイベントとは別で常時表示する際の処理) - css適用
使用するテーブル
いいねのデータを格納する際のテーブルを作成します。
投稿に対し、
- "どの投稿に対して(投稿記事のID)"
- "誰がいいねしたのか(ユーザID)
が分かればいいので下記のようなテーブルを作成します。
処理の流れ(コード付き)
- ハートアイコンのクリックでイベント発火
- クリックした要素をthisで取得、付随するカスタムデータ属性の値も取得
※like-btnが同じページに複数存在するので、クリックされたlike-btnのみを
表現するためにvar $this = $(this);
としています。
list.html
<i class="like-btn fa-heart far" data-articleid = <記事のID></i>
->この場合、html上に黒枠のハートアイコンが表示されるはずです。
ajax.js
$(function() {
$('.like-btn').on('click', function() {
//$(this)でクリックしたもののみのクラス?を取得
var $this = $(this);
var article_id = $this.data('articleid');
});
});
- ajaxの処理
ajax.js
$(function() {
$('.like-btn').on('click', function() {
//$(this)でクリックしたもののみのクラス?を取得
var $this = $(this);
var span = $this.next();
var article_id = $this.data('articleid');
ここから追記
$.ajax({
url: "URL", // phpへのURLを指定
type: "POST", // GET,POSTなどを指定
dataType: "json",
data: { // データを指定
article_id : article_id,
}
}).done(function (data) {
// 通信成功時のコールバック処理
console.log('Ajax Successe');
}).fail(function (data) {
// 通信失敗時のコールバック処理
console.log('fail');
console.log(data);
}).always(function (data) {
// 常に実行する処理
console.log('always');
console.log(data);
// alert(json);
});
});
});
- ajaxから取得した値とSESSIONから取得した値のバリデーション
- どちらも通ったなら、既にいいねしているか判別
- 5の結果により、DBへの追加か削除も処理をする。
- 処理結果をレスポンス用データ変数に格納
- json形式でajaxに返却
ajax.php
<?php
class ApiController extends Controller
{
public $code;
public function ajaxAction()
{
//投稿記事IDの取得
$article_id = !empty($_POST['article_id']) ? $_POST['article_id'] : null;
try {
if (empty($article_id))
throw new Exception('error');
//セッションからログインユーザ情報の取得
$user = !empty($this->session->get('user')) ? $this->session->get('user') : throw new Exception('user none');
//バリデーションは良きにやってください。
//6.いいねをすでにしているか
$isgood = $this->db_manager->get('Good')->isGood($user['id'], $article_id) ? true : false;
//7.していないなら削除、しているなら追加
if($isgood){
$this->db_manager->get('Good')->delete($user['id'], $article_id);
}else{
$this->db_manager->get('Good')->insert($user['id'], $article_id);
}
//8.レスポンス用のデータ作成
$GoodCount = $this->db_manager->get('Good')->goodCount($article_id);
$res['isgood'] = $isgood;
$res['goodCount'] = $GoodCount['cnt'];
$this->code = $res;
} catch (Exception $e){
$this->code = array('error' => $e->getMessage());
}
$json = json_encode($this->code);
//9.Json形式で返却
header('Content-type: application/json; charset=utf-8');
echo $json;
exit;
}
}
- レスポンスの中身にある"追加"か"削除"かを表すデータを取得して、処理を分ける
- 追加、削除したかによって、htmlにおけるクラスのつけ外しをjqueryで行う
- レスポンスの中身にあるいいね数データも取得して、html側に反映
この時、phpから返却されるデータは下記になります。
{['isgood'] => trueかfalse, ['goodCount'] => いいねの数}
list.html
<i class="like-btn fa-heart far" data-articleid = <記事のID></i>
ajax.js
$(function() {
$('.like-btn').on('click', function() {
//$(this)でクリックしたもののみのクラス?を取得
var $this = $(this);
var span = $this.next();
var article_id = $this.data('articleid');
$.ajax({
url: "URL", // phpへのURLを指定
type: "POST", // GET,POSTなどを指定
dataType: "json",
data: { // データを指定
article_id : article_id,
}
}).done(function (data) {
// 通信成功時のコールバック処理
console.log('Ajax Successe');
ここから追記
//11,12.レスポンスがtrue(いいねしていた)である時、ハートのアイコンを白地にする。
if(data['isgood']){
$this.removeClass('active fas');
$this.addClass('far');
span.removeClass('active');
} else {
$this.removeClass('far');
$this.addClass('active fas');
span.addClass('active');
}
//13.同時に取得してきたいいね数をviewに反映する。
span.text(data['goodCount']);
ここまで
}).fail(function (data) {
// 通信失敗時のコールバック処理
console.log('fail');
console.log(data);
}).always(function (data) {
// 常に実行する処理
console.log('always');
console.log(data);
// alert(json);
});
});
});
- html側では、いいねしているかといいね数を既に表示する処理をphpで記述する
※(14はクリックイベントとは別で常時表示する際の処理)
このコードは冒頭で触れた独自フレームワークの書き方が多いです。
$articleというものは、このビューであるlist.phpに渡す前に
コントローラ側でデータベースから取得してきたものを連想配列に整形したものです。
list.php(先ほどのlist.htmlの書き換え)
<i class="like-btn fa-heart <?php $article['isgood'] ? print ' active fas' : print ' far'; ?>"
data-articleid = <?php echo $article['id']; ?>>
</i>
<span class="<?php if($article['isgood']) echo ' active'; ?>">
<?php echo $article['goodcnt']; ?>
</span>
$articleの中身
array(10) {
["id"]=>
int(75)
["user_id"]=>
int(6)
["name"]=>
string(4) "hoge"
["icon_image_file"]=>
string(0) ""
["create_at"]=>
string(19) "2023-09-22 00:53:31"
["image"]=>
string(28) "hogehogehogehoghoge.jpg"
["isgood"]=>
bool(false)
["goodcnt"]=>
int(1)
}
- css適用
style.css
.like-btn {
cursor: pointer;
}
.active{
color: #f60909;
}
成功イメージ
いいね前
いいね後
実装を通して
1週間で実装しましたが、たまたま参考になる資料を見つけたからでした。
参考資料の方も言っていましたが、詰まった際はメモ帳か何かに
やろうとしている処理を、事細かに、段階を踏んで、書いてみることが大事だと思います。
私も学習日記たるものをなるべくつけるようにしていますが、
日本語がめちゃくちゃでもとりあえず書いてます。
そうすれば、おのずと、見えてくるものがあるはずです。
未経験で詰まると、精神的にきついですが、めげずにやっていこうと思います。
今後はXのようにいいねのアニメーションもつけてみたいと思っています。
参考資料
この方の資料のおかげで大変はかどりました。
Discussion