又是努力写代码的一天!!!
今写许愿墙
项目介绍
在生活中,许愿墙是承载愿望的实体。最初人们将自己的愿望写在小纸片上,贴到墙上,形成了许愿墙。随着互联网的发展,在网站中实现发表愿望、展示愿望的功能,供人们表达自己的愿望并且浏览其他人的愿望,是网络形式的许愿墙。
许愿墙的功能主要包括查看愿望、发表愿望、修改愿望和删除愿望,并且在修改和删除时需要输入密码,防止其他用户误删除别人的愿望。
项目代码
<?php
/**
* 接收输入的函数
* @param array $method 输入的数组(可用字符串 get、post 来表示)
* @param string $name 从数组中取出的变量名
* @param string $type 表示类型的字符串
* @param mixed $default 变量不存在时使用的默认值
* @return mixed 返回的结果
*/
function input($method, $name, $type = 's', $default = '')
{
switch ($method) {
case 'get': $method = $_GET; break;
case 'post': $method = $_POST; break;
}
$data = isset($method[$name]) ? $method[$name] : $default;
switch ($type) {
case 's':
return is_string($data) ? $data : $default;
case 'd':
return (int)$data;
case 'a':
return is_array($data) ? $data : [];
default:
trigger_error('不存在的过滤类型“' . $type . '”');
}
}
/**
* 格式化日期
* @param type $time 给定时间戳
* @return string 从给定时间到现在经过了多长时间(天/小时/分钟/秒)
*/
function format_date($time)
{
$diff = time() - $time;
$format = [86400 => '天', 3600 => '小时', 60 => '分钟', 1 => '秒'];
foreach ($format as $k => $v) {
$result = floor($diff / $k);
if ($result) {
return $result . $v;
}
}
return '0.5 秒';
}
/**
* 获取 LIMIT 的参数
* @param int $page 当前页码值
* @param int $size 每页显示的条数
* @return string 生成后的结果
*/
function page_sql($page, $size)
{
return ($page - 1) * $size . ',' . $size;
}
/**
* 生成分页导航 HTML
* @param string $url 链接地址
* @param int $total 总记录数
* @param init $page 当前页码值
* @param int $size 每页显示的条数
* @return string 生成的 HTML 结果
*/
function page_html($url, $total, $page, $size)
{
// 计算总页数
$maxpage = max(ceil($total / $size), 1);
// 如果不足 2 页,则不显示分页导航
if ($maxpage <= 1) {
return '';
}
if ($page == 1) {
$first = '<span>首页</span>';
$prev = '<span>上一页</span>';
} else {
$first = "<a href=\"{$url}1\">首页</a>";
$prev = '<a href="' . $url . ($page - 1) . '">上一页</a>';
}
if ($page == $maxpage) {
$next = '<span>下一页</span>';
$last = '<span>尾页</span>';
} else {
$next = '<a href="' . $url . ($page + 1) . '">下一页</a>';
$last = "<a href=\"{$url}{$maxpage}\">尾页</a>";
}
// 组合最终样式
return "<p>当前位于:$page/$maxpage</p>$first $prev $next $last";
}
<?php
// 连接数据库
$link = mysqli_connect('localhost', 'root', '', 'php_wish');
if (!$link) {
exit('数据库连接失败:' . mysqli_connect_error());
}
mysqli_set_charset($link, 'utf8');
// 设置 mbstring 扩展的内置编码
mb_internal_encoding('UTF-8');
?>
body{margin:0;background:#F7F7F7;}
.top{height:50px;border-bottom:1px solid #ebebeb;background:#fff;}
.top h1{margin:0;font-weight:400;font-size:1.8em;font-family:'Microsoft YaHei';line-height:50px;}
.top h1 a{color:#2FAE36;text-decoration:none;}
.container{margin:0 auto;width:80%;}
.note{margin-top:20px;padding:0 10px;padding-bottom:30px;border:1px solid #eee;background:#fff;color:#666;font-size:12px;font-family:arial,simsun;}
.note:after{clear:both;display:block;content:"";}
.note-top{margin:20px auto;margin-bottom:10px;text-align:center;}
.note-top-add{display:inline-block;padding:6px 18px;border-radius:2px;background-color:#6acd6a;color:#fff;cursor:pointer;transition:background-color .5s;}
.note-top-add:hover{background-color:#2FAE36;}
.note-top-add:active{background-color:#1F9E26;}
.note-box{display:flex;flex-wrap:wrap;justify-content:center;list-style-type: none;}
.note-list{position:relative;box-sizing:border-box;margin:10px;padding:10px;width:160px;height:175px;box-shadow:2px 2px 0 #DDD;}
.note-list-red{border:1px solid #FDC4F2;background-color:#FFD6F4;}
.note-list-blue{border:1px solid #A6E3FC;background-color:#C6F3FC;}
.note-list-yellow{border:1px solid #EDEB7C;background-color:#FFFCBC;}
.note-list-green{border:1px solid #A5F88B;background-color:#D5F8BB;}
.note-list:hover .note-list-action{display:block;}
.note-list-action{position:absolute;top:5px;right:8px;display:none;}
.note-list-edit{position:relative;top:-2px;float:left;margin-right:5px;color:#666;text-decoration:none;font-size:16px;}
.note-list-edit:hover{color:#EB1C27;}
.note-list-delete{float:left;color:#666;text-decoration:none;font-size:18px;}
.note-list-delete:hover{color:#EB1C27;}
.note-list-box{margin:0;margin-top:10px;padding:0;list-style:none;font-size:13px;line-height:20px;}
.note-list-name{margin-bottom:5px;padding-bottom:5px;border-bottom:1px dotted #fff;font-size:12px;}
.note-list-name span{font-weight:700;font-size:13px;}
.note-list-date{padding-top:5px;font-size:12px;}
.note-list-content{word-break:break-all;}
.note-layer{position:fixed;top:0;right:0;bottom:0;left:0;display:flex;background-color:rgba(150,150,150,.2);align-items:center;justify-content:center;}
.note-edit{padding:15px;width:400px;border:10px solid rgba(106,205,106,.3);border-radius:5px;background-color:#fff;background-clip:padding-box;}
.note-edit-title{margin-bottom:8px;border:0;color:#299C30;font-weight:700;}
.note-edit-table{width:100%;border:0;border-collapse:collapse;}
.note-edit-table-w{width:210px;}
.note-edit-table td{padding-bottom:5px;}
.note-edit p{margin:0;margin-bottom:5px;}
.note-edit-content{box-sizing:border-box;margin-bottom:5px;padding:3px;width:100%;height:80px;border:1px solid #ccc;color:#666;font-size:12px;font-family:arial,simsun;}
.note-edit-pwd{padding:3px;width:115px;border:1px solid #ccc;color:#666;font-size:12px;font-family:arial,simsun;}
.note-edit-name{padding:3px;width:180px;border:1px solid #ccc;color:#666;font-size:12px;font-family:arial,simsun;}
.note-edit-submit{padding:4px 10px;border:1px solid #2cb82c;border-radius:2px;background-color:#6acd6a;color:#fff;letter-spacing:2px;font-size:12px;cursor:pointer;transition:background-color .5s;}
.note-edit-submit:hover{background-color:#2FAE36;}
.note-edit-submit:active{background-color:#1F9E26;}
.note-edit-cancel{margin-left:5px;padding:4px 10px;border:1px solid #2cb82c;border-radius:2px;background-color:#6acd6a;color:#fff;letter-spacing:2px;font-size:12px;cursor:pointer;transition:background-color .5s;}
.note-edit-cancel:hover{background-color:#2FAE36;}
.note-edit-cancel:active{background-color:#1F9E26;}
.note-edit-red input{display:none;}
.note-edit-red{display:inline-block;width:20px;height:20px;border:1px solid #FDB4E2;background-color:#FDC4F2;cursor:pointer;}
.note-edit-red:hover{border:1px solid #CD74A2;}
.note-edit-red-curr{border:1px solid #CD74A2;}
.note-edit-blue input{display:none;}
.note-edit-blue{display:inline-block;width:20px;height:20px;border:1px solid #A6E3FC;background-color:#A6E3FC;cursor:pointer;}
.note-edit-blue:hover{border:1px solid #55A5B7;}
.note-edit-blue-curr{border:1px solid #55A5B7;}
.note-edit-yellow input{display:none;}
.note-edit-yellow{display:inline-block;width:20px;height:20px;border:1px solid #FDFB8C;background-color:#FDFB8C;cursor:pointer;}
.note-edit-yellow:hover{border:1px solid #BEBC45;}
.note-edit-yellow-curr{border:1px solid #BEBC45;}
.note-edit-green input{display:none;}
.note-edit-green{display:inline-block;width:20px;height:20px;border:1px solid #A5F88B;background-color:#A5F88B;cursor:pointer;}
.note-edit-green:hover{border:1px solid #78C755;}
.note-edit-green-curr{border:1px solid #78C755;}
.note-page{overflow:hidden;text-align:center;line-height:14px;}
.note-page a{display:inline-block;margin:0 3px;padding:2px 12px;height:24px;border:1px solid #ccc;background:#fff;color:grey;text-decoration:none;font-size:12px;line-height:24px;transition:all .2s;}
.note-page a:hover{border:1px solid #2FAE36;color:#2FAE36;}
.note-page span{display:inline-block;margin:0 3px;padding:2px 12px;border:1px solid #ccc;background:#fcfcfc;color:#bbb;font-size:12px;line-height:24px;}
.note-page p{margin:1em 0;}
/* 设置单选框选中效果 */
(function(){
var curr = function(target){
var label = ["red", "green", "yellow", "blue"], obj = [], v;
for(v in label){
obj[v] = target.find(".note-edit-" + label[v]);
obj[v].find("input:checked").length && obj[v].addClass("note-edit-" + label[v] + "-curr");
obj[v].click(function(){
for(v in obj){
var curr = "note-edit-" + label[v] + "-curr";
obj[v].find("input:checked").length ? obj[v].addClass(curr) : obj[v].removeClass(curr);
}
});
}
};
curr($(".js-note-add"));
curr($(".js-note-edit"));
})();
/* 添加按钮 */
$(".note-top-add").click(function(){
$(".js-note-add").fadeIn(200);
});
/* 取消按钮 */
$(".note-edit-cancel").click(function(){
$(this).parents(".note-layer").fadeOut(200);
});
/* 删除按钮 */
$(".note-list-delete").click(function(){
return confirm('您确定要删除吗?');
});
<div class="note-layer js-note-add" style="display:none">
<div class="note-edit">
<div class="note-edit-title">我要许愿</div>
<form method="post" action="./save.php">
<table class="note-edit-table">
<tr>
<td class="note-edit-table-w">
<p>我的名字:</p>
<input class="note-edit-name" type="text" name="name" placeholder="匿名">
</td>
<td>
<p>贴纸颜色:</p>
<label class="note-edit-green"><input type="radio" name="color" value="green" checked></label>
<label class="note-edit-blue"><input type="radio" name="color" value="blue"></label>
<label class="note-edit-yellow"><input type="radio" name="color" value="yellow"></label>
<label class="note-edit-red"><input type="radio" name="color" value="red"></label>
</td>
</tr>
<tr>
<td colspan="2">
<p>我的愿望:</p>
<textarea class="note-edit-content" name="content" placeholder="80个字符以内(中文占2个字符位)"></textarea>
</td>
</tr>
<tr>
<td>
保护密码:
<input class="note-edit-pwd" type="password" name="password" placeholder="6个字符以内">
</td>
<td>
<input class="note-edit-submit" type="submit" value="提交">
<input class="note-edit-cancel" type="button" value="取消">
</td>
</tr>
</table>
</form>
</div>
</div>
<div class="note-layer js-note-edit">
<div class="note-edit">
<div class="note-edit-title">编辑愿望</div>
<form method="post" action="./save.php?id=<?=$id?>&page=<?=$page?>">
<table class="note-edit-table">
<tr>
<td class="note-edit-table-w">
<p>我的名字:</p>
<input class="note-edit-name" type="text" name="name" placeholder="匿名" value="<?=htmlspecialchars($edit['name'])?>">
</td>
<td>
<p>贴纸颜色:</p>
<label class="note-edit-green"><input type="radio" name="color" value="green" <?=$edit['color']=='green' ? 'checked' : ''?>></label>
<label class="note-edit-blue"><input type="radio" name="color" value="blue" <?=$edit['color']=='blue' ? 'checked' : ''?>></label>
<label class="note-edit-yellow"><input type="radio" name="color" value="yellow" <?=$edit['color']=='yellow' ? 'checked' : ''?>></label>
<label class="note-edit-red"><input type="radio" name="color" value="red" <?=$edit['color']=='red' ? 'checked' : ''?>></label>
</td>
</tr>
<tr>
<td colspan="2">
<p>我的愿望:</p>
<textarea class="note-edit-content" name="content"><?=htmlspecialchars($edit['content'])?></textarea>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="hidden" name="password" value="<?=htmlspecialchars($password)?>">
<input class="note-edit-submit" type="submit" value="提交">
<input class="note-edit-cancel" type="button" value="取消">
</td>
</tr>
</table>
</form>
</div>
</div>
<div class="note-layer">
<div class="note-edit">
<div class="note-edit-title">验证密码</div>
<form method="post">
<table class="note-edit-table">
<?php if(isset($tips)): ?>
<tr>
<td colspan="2"><?=$tips?></td>
</tr>
<?php endif; ?>
<tr>
<td class="note-edit-table-w">
输入密码:
<input class="note-edit-pwd" type="password" name="password" placeholder="6个字符以内">
</td>
<td>
<input class="note-edit-submit" type="submit" value="验证">
<input class="note-edit-cancel" type="button" value="取消">
</td>
</tr>
</table>
</form>
</div>
</div>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>许愿墙</title>
<link rel=stylesheet href="./css/style.css">
</head>
<body>
<div class="top">
<div class="container"><h1><a href="index.php">许愿墙</a></h1></div>
</div>
<div class="container note">
<div class="note-top"><div class="note-top-add">我要许愿</div></div>
<div class="note-box">
<!-- 输出许愿墙 -->
<?php foreach($data as $v): ?>
<div class="note-list note-list-<?=$v['color']?>">
<div class="note-list-action">
<a class="note-list-edit" href="./index.php?action=edit&id=<?=$v['id']?>&page=<?=$page?>" title="修改">✎</a>
<a class="note-list-delete" href="./index.php?action=delete&id=<?=$v['id']?>&page=<?=$page?>" title="删除">×</a>
</div>
<ul class="note-list-box">
<li class="note-list-name">FROM: <span><?=htmlspecialchars($v['name'])?></span></li>
<li class="note-list-content"><?=htmlspecialchars($v['content'])?></li>
<li class="note-list-date">(<?=format_date($v['time'])?>前 <?=date('H:i', $v['time'])?>)</li>
</ul>
</div>
<?php endforeach; ?>
</div>
<!-- 添加愿望表单 -->
<?php require './view/common/add.html'; ?>
<!-- 编辑愿望表单 -->
<?php if ($id): require './view/common/password.html'; endif; ?>
<?php if ($id):
require './view/common/' . ($checked ? 'edit' : 'password') . '.html';
endif; ?>
<!-- 分页链接 -->
<div class="note-page">
<?=page_html('./index.php?page=', $total, $page, $size)?>
</div>
</div>
<script src="./js/jquery-1.12.4.min.js"></script>
<script src="./js/common.js"></script>
</body>
</html>
<?php
require './common/init.php';
require './common/function.php';
// 获取当前页码,限制最小值为 1
$page = max(input('get', 'page', 'd'), 1);
$size = 4; // 每页显示的条数
$sql = 'SELECT count(*) FROM `wish`';
if (!$res = mysqli_query($link, $sql)) {
exit("SQL[$sql]执行失败:" . mysqli_error($link));
}
$total = (int)mysqli_fetch_row($res)[0];
// 分页查询愿望
$sql = 'SELECT `id`,`name`,`content`,`time`,`color` FROM `wish`
ORDER BY `id` DESC LIMIT ' . page_sql($page, $size);
if (!$res = mysqli_query($link, $sql)) {
exit("SQL[$sql]执行失败:" . mysqli_error($link));
// 查询结果为空时,自动返回第 1 页
if (empty($data) && $page > 1) {
header('Location: index.php?page=1');
exit;
}
}
// 获取待编辑的愿望 id
$id = max(input('get', 'id', 'd'), 0);
if ($id) {
// 根据 id 查询出愿望信息
$password = input('post', 'password', 's');
$sql = 'SELECT `name`,`content`,`color`,`password` FROM `wish`
WHERE `id`=' . $id;
if (!$res = mysqli_query($link, $sql)) {
exit("SQL[$sql]执行失败:" . mysqli_error($link) . $sql);
}
if (!$edit = mysqli_fetch_assoc($res)) {
exit('该愿望不存在!');
}
mysqli_free_result($res);
// 验证密码是否正确
$checked = isset($_POST['password']) || empty($edit['password']);
if ($checked && $password !== $edit['password']) {
$tips = '密码不正确!';
$checked = false;
}
if ($checked && $action == 'delete') {
$sql = 'DELETE FROM `wish` WHERE `id`=' . $id;
if (!mysqli_query($link, $sql)) {
exit('SQL 执行失败:' . mysqli_error($link));
}
header('Location: index.php');
exit;
}
}
$data = mysqli_fetch_all($res, MYSQLI_ASSOC);
mysqli_free_result($res);
mysqli_close($link);
require './view/index.html';
<?php
require './common/init.php';
require './common/function.php';
// 接收变量
$name = trim(input('post', 'name', 's'));
$color = input('post', 'color', 's');
$content = trim(input('post', 'content', 's'));
$password = input('post', 'password', 's');
// 限制名称最多占用 12 个字符位置(1 个汉字占用 2 个位置)
$name = mb_strimwidth($name, 0, 12);
// 当名称为空时,使用“匿名”作为默认值
$name = $name ?: '匿名';
// 限制颜色值在合法范围内,使用“green”作为默认值
if (!in_array($color, ['blue', 'yellow', 'green', 'red'])) {
$color = 'green';
}
// 限制内容长度最多占用 80 个字符位置
$content = mb_strimwidth($content, 0, 80);
// 限制密码长度最多为 6 位
$password = (string)substr($password, 0, 6);
// 保存用户的发布时间
$time = time();
// 接收待修改的愿望 id
$id = max(input('get', 'id', 'd'), 0);
if ($id) {
// 验证密码是否正确
$sql = 'SELECT `password` FROM `wish` WHERE `id`=' . $id;
if (!$res = mysqli_query($link, $sql)) {
exit("SQL[$sql]执行失败:" . mysqli_error($link));
}
if (!$data = mysqli_fetch_assoc($res)) {
exit('该愿望不存在!');
}
if ($data['password'] !== $password) {
exit('密码不正确!');
}
// 保存到数据库
$sql = 'UPDATE `wish` SET `name`=?,`color`=?,`content`=? WHERE `id`=?';
if (!$stmt = mysqli_prepare($link, $sql)) {
exit("SQL[$sql]预处理失败:" . mysqli_error($link));
}
mysqli_stmt_bind_param($stmt, 'sssi', $name, $color, $content, $id);
if (!mysqli_stmt_execute($stmt)) {
exit('数据库操作失败:' . mysqli_stmt_error($stmt));
}
// 执行完成,跳转回许愿墙,并传递页码值
$page = max(input('get', 'page', 'd'), 1);
header("Location: index.php?page=$page");
exit;
}
$sql = 'INSERT INTO `wish` (`name`,`color`,`content`,`password`,`time`)
VALUES (?,?,?,?,?)';
if (!$stmt = mysqli_prepare($link, $sql)) {
exit("SQL[$sql]预处理失败:" . mysqli_error($link));
}
mysqli_stmt_bind_param($stmt, 'ssssi', $name, $color, $content, $password, $time);
if (!mysqli_stmt_execute($stmt)) {
exit('数据库操作失败:' . mysqli_stmt_error($stmt));
}
header('Location: index.php');
项目数据库
运行截图
小新码农,不足点请多多包含,也欢迎大家一起探讨哦~