index.php
<?php
session_start();
require_once("config.php");
$sql="SELECT tweets.u_id AS u,nickname,tweet,created,likes,t_id FROM tweets,users WHERE tweets.u_id=users.u_id ORDER BY t_id DESC";
$res=$pdo->query($sql);
//ろぐいんしすてむそのものがひつようでない
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Test掲示板 タイムライン</title>
<link rel="stylesheet" href="css/style.css">
<script src="../jquery-3.4.1.min.js"></script>
</head>
<body>
<div id="container">
<h1>Test掲示板</h1>
<form method="post" action="make_user.php">
<table>
<tr>
<th><label for="u_id">ユーザ名</label></th>
<td><input type="text" name="u_id" id="u_id"></td>
</tr>
<tr>
<th><label for="pass">パスワード</label></th>
<td><input type="password" name="pass" id="pass"></td>
</tr>
<tr>
<th><label for="nickname">ニックネーム</label></th>
<td><input type="text" name="nickname" id="nickname"></td>
</tr>
</table>
<p><button type="submit">登録</button></p>
</form>
<!--ツイートの数だけwhileで繰り返す-->
<?php while($row = $res->fetch(PDO::FETCH_ASSOC)): ?>
<!--articleのくくりが1件のツイートに相当-->
<article>
<header>
<img src="css/<?php echo htmlspecialchars($row["u"],ENT_QUOTES); ?>.png">
<?php echo htmlspecialchars($row["nickname"],ENT_QUOTES); ?>
</header>
<p><?php echo htmlspecialchars($row["tweet"],ENT_QUOTES); ?></p>
<div>
<span data-t_id="<?php echo $row["t_id"]; ?>">いいね<img src="img/heart_small.png"> <?php echo $row["likes"] ?></span>
<?php echo $row["created"]; ?>
</div>
</article>
<?php endwhile; ?>
</div>
<script src="tweet.js"></script>
</body>
</html>
tweets.js
$(function(){
//console.log("hoge");
$('article div span').on('click',function(){
var elehoge=$(this);
//インクリメントするt_idの取得
var obj = $(this).data();//いったんオブジェクトとして受け取り、
var t_id = obj.t_id;//そこからt_idを取り出す
//console.log(obj);
//console.log(t_id);
//Ajax
$.ajax({
url:'update_likes.php',
data:{'t_id' : t_id},
Type:'get',
dataType:'text',
})
.done(function(data){
//console.log(data);
elehoge.text("いいね"+'♥'+data);
})//doneメソッドのおわり
.fail(function(){
});//failのおわり
});
});
login.php
<?php
session_start();
$_SESSION=[];//セッションデータの中の値を捨てる
setcookie(session_name(),'',time()-60);//こっち側を捨てる
session_destroy();//通信を切る
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ログインフォーム</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="container">
<h1>ユーザーログイン</h1>
<form method="post" action="auth.php">
<table>
<tr>
<th><label for="u_id">ユーザ名</label></th>
<td><input type="text" name="u_id" id="u_id"></td>
</tr>
<tr>
<th><label for="pass">パスワード</label></th>
<td><input type="password" name="pass" id="pass"></td>
</tr>
</table>
<p><button type="submit">認証</button></p>
</form>
<p>
または<a href="user_form.php">新規登録</a>
</p>
</div>
</body>
</html>
auth.php
<?php
session_start();
//評価するデータが来ているかいないか
if(empty($_POST["u_id"]) || empty($_POST["pass"])){
header("Location: login.php");
exit();
}
//DBへ接続
require_once("config.php");
//SQL文
$sql="SELECT * FROM users WHERE u_id=:u_id";//一回全部読んでくる
$stmt=$pdo->prepare($sql);//構文を焼く。こんがり。
$stmt->bindValue(":u_id",$_POST["u_id"],PDO::PARAM_STR);
$stmt->execute();
//FETCH 房をばらして連想配列にするために$rowに入れる
$row=$stmt->fetch(PDO::FETCH_ASSOC);//1件とりだし
//認証処理
if(password_verify($_POST["pass"],$row["pass"])){
//セッションID の再発行
session_regenerate_id();//毎回変わる。新しい鞄。そのなかに以下のものを入れる
$_SESSION["login"] = true;
$_SESSION["u_id"]=$row["u_id"];//=$_POST["u_id"]でも構わない
$_SESSION["nickname"]=$row["nickname"];
header("Location: index.php");//リダイレクト
exit();
}else{
$_SESSION["login"]=false;//ログイン失敗
header("Location: login.php");
exit();
}
?>
config.php
<?php
//--------------------------
//DB接続設定
//環境に合わせて再定義のこと
//--------------------------
$user="root";
$dbpass="";
$host="localhost";
$dbname="twitter";
//--------------------------
$dsn="mysql:host={$host};dbname={$dbname};charset=utf8";
$pdo=new PDO($dsn,$user,$dbpass);
?>
exec.php
<?php
session_start();
//セッション情報がないかfalse
if(empty($_SESSION["login"])){
header("Location: login.php");
exit();
}
//tweetがからっぽ
if(empty($_POST["tweet"])){
header("Location: index.php");
exit();
}
require_once("config.php");
$sql="INSERT INTO tweets(u_id,tweet) VALUES(:u_id,:tweet)";//プレースホルダを使う
$stmt=$pdo->prepare($sql);
$stmt->bindValue(":u_id",$_SESSION["u_id"],PDO::PARAM_STR);
$stmt->bindValue(":tweet",$_POST["tweet"],PDO::PARAM_STR);
$stmt->execute();
header("Location: index.php");
exit();
?>
make_user.php
<?php
session_start();
require_once("config.php");
$sql="INSERT INTO users(u_id,pass,nickname) VALUES(:u_id,:pass,:nickname)";
$stmt=$pdo->prepare($sql);
$stmt->bindValue(":u_id",$_POST["u_id"],PDO::PARAM_STR);
//passwordのハッシュ
$pass=password_hash($_POST["pass"],PASSWORD_DEFAULT);//第二引数を定数で指定(時代が変わってもOK)
$stmt->bindValue(":pass",$pass,PDO::PARAM_STR);
$stmt->bindValue("nickname",$_POST["nickname"],PDO::PARAM_STR);
$stmt->execute();
//ログインしたことにして、タイムラインにダイレクトに転送
$_SESSION["login"]=true;
$_SESSION["u_id"]=$_POST["u_id"];
$_SESSION["nickname"]=$_POST["nickname"];
//ページに留まるのは危険なので移動
header("Location: index.php");
exit();
?>
update_likes.php
<?php
//いいねを1つ増やす処理
require_once("config.php");
$sql="UPDATE tweets SET likes=likes+1 WHERE t_id=:t_id";
$stmt=$pdo->prepare($sql);//構文を焼く
$stmt->bindValue(":t_id",$_GET["t_id"],PDO::PARAM_INT);//番号だからINT
$stmt->execute();
//echo 'ok';
//いいねがいくつか取得する処理
//同じ名前は使えないので
$sql2 = "SELECT likes FROM tweets WHERE t_id=:t_id";
$stmt2=$pdo->prepare($sql2);
$stmt2->bindValue(":t_id",$_GET["t_id"],PDO::PARAM_INT);
$stmt2->execute();
//fetchして中身を取り出す
$row=$stmt2->fetch(PDO::FETCH_ASSOC);
echo $row["likes"];
?>
user_form.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ユーザフォーム</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="container">
<h1>ユーザー登録</h1>
<form method="post" action="make_user.php">
<table>
<tr>
<th><label for="u_id">ユーザ名</label></th>
<td><input type="text" name="u_id" id="u_id"></td>
</tr>
<tr>
<th><label for="pass">パスワード</label></th>
<td><input type="password" name="pass" id="pass"></td>
</tr>
<tr>
<th><label for="nickname">ニックネーム</label></th>
<td><input type="text" name="nickname" id="nickname"></td>
</tr>
</table>
<p><button type="submit">登録</button></p>
</form>
</div>
</body>
</html>
style.css
body{
background-image: url("../../img/fish_kue2.png");
color:#333;
}
#container{
width:80%;
margin: auto;
background:#fff;
padding:0.5rem;
border-left:solid 1px #eee;
border-right:solid 1px #eee;
}
table{
border-collapse:collapse;
}
th,td{
border:solid 1px #333;
padding: 0.2rem 0.3rem;
text-align: left;
}
th{
background:#eee;
}
h1{
border-left:10px solid #ffa50a;
/*border-radius:2rem;*/
padding:0.5rem;
color:#ffa50a;
margin-left:1.5rem;
}
.linkbox{
text-align: right;
padding-right:1.5rem;
}
.link{
display: inline ;
text-align:right;
background:#6ccc0c;
border-radius:1rem;
padding:0.2rem;
}
.link a{
text-decoration: none;
color:#fff;
font-size:0.8rem;
}
/*タイムライン*/
article{
margin:2rem;
border-bottom:dotted 2px #ffa50a;
}
article p{
margin:0.5rem 0;
}
article header{
font-weight:bold;
font-size:0.8rem;
}
article div{
color:#333;
font-size:0.8rem;
text-align:right;
}
article div span{
color:#ffa50a;
padding-right:1.5rem;
cursor:pointer;
}
article div span img{
width:20px;
}
article header img{
width:60px;
border:3px solid #ddd;
border-radius:9999px;
}
#tweetform img{
width:30px;
}
#tweetform textarea{
font-size:1.2rem;
padding:0.3rem;
border-radius:0.2rem;
}