利用PHP开发的一款万能、表白墙系统部分代码片段

本文档详述了一个基于layui2.0的网页版表白墙系统的开发过程,涵盖了需求分析、系统架构、数据库配置、代码实现及功能模块,如用户留言、后台管理、分页和图像处理。系统允许用户前端发布信息,后台进行文章和标签的管理,并具备留言增删功能。
摘要由CSDN通过智能技术生成

表白墙系统


前言

本系统最初的模型是高校中传统的“表白墙”,以前大学食堂门口贴满A4纸的“表白墙”,逐渐演变成为一些很火的“万能墙”,但基本上通过都是QQ空间或微信朋友圈的方式发布出稿件!很费力!于是便萌生了这个想法,我们能不能用已学的知识做一个网页版的,全自动的万能墙系统。
此系统采用了layui2.0开源模块UI框架(镜像站www.layuiweb.com),感谢专业前端工程师(贤心)倾情打造,layui的样式本人十分喜爱。


一、需求分析

*MYSQL完成后台管理设计
*系统分为前后台前台展示文章,后台发布文章
*后台需要管理员的账号密码
*后台存在文章管理和栏目管理
*进入后台能够实现删除和修改发表标签功能
*在前台能够发布信息

二、系统分析

1.模块划分在这里插入图片描述

2.E-R图
在这里插入图片描述

二、搭建准备工作(完成数据库和工具准备)

1.搭建环境

工具需要:宝塔面板
在这里插入图片描述

2.下载完成一键安装phpmyadmin nginx或apache php(php版本需要大于5.6以上)

3.创建数据库和数据表相关内容最后写成一键搭建

在这里插入图片描述

三、重要代码以及步骤

1.项目初始化和部分重要函数代码展示

init.php初始化代码:(配置文件操作)

<?php
//设置字符集
header('content-type:text/html;charset=utf-8');
ini_set('session.cookie_httponly', 1); //设置防止xss攻击
session_start(); //开启session
//调试开关
define('APP_DEBUG', true);
//开启调试时,显示错误报告
ini_set('display_errors', APP_DEBUG);
//定义前后台公共目录常量
define('APP_PATH', './app/');   //支持库文件目录
define('UPLOAD_PATH', './upload/');  //上传文件目录
//载入函数库
require APP_PATH . 'function.php';
//载入数据库函数
require APP_PATH . 'db.php';
//载入模块库
require APP_PATH . 'module.php';

app/function.php函数库部分代码

//配置文件操作
function C($name)
{
	static $config = null; //保存项目中的设置
	if (!$config) {          //函数首次被调用时载入配置文件
		$config = require APP_PATH . 'config.php';
	}
	return isset($config[$name]) ? $config[$name] : '';
}

app/config.php配置文件代码

return [
	//数据库连接信息
	'DB_CONNECT' => [
		'host' => 'localhost',	             //服务器地址
		'user' => 'wnq',		     //用户名
		'pass' => 'PGcrPaaiTyWdcMLb',		     //密码
		'dbname' => 'wnq',             //数据库名
		'port' => '3306',		             //端口
	],
	'DB_CHARSET' =>	'utf8',	             //字符集
];

app/db.php数据库部分代码

//通过预处理方式执行SQL
function db_query($sql, $type = '', $data = [])
{
	//获取数据库连接
	$link = db_connect();
	//预处理SQL语句
	if (!$stmt = mysqli_prepare($link, $sql)) {
		E('数据库操作失败。', mysqli_error($link) . "\nSQL语句:" . $sql);
	}
	//无参数绑定时,直接执行
	if ($data == []) {
		mysqli_stmt_execute($stmt);
	} else {
		//批量处理
		$data = (array)$data;							//如果不是数组,强制转换为数组
		is_array(current($data)) || $data = [$data];	//自动识别批量模式
		$params = array_shift($data);					//准备待绑定的变量
		db_bind_param($stmt, $type, $params);			//参数绑定
		mysqli_stmt_execute($stmt);						//执行第1个
		foreach ($data as $row) {							//批量执行剩余的
			foreach ($row as $k => $v) {
				$params[$k] = $v;	//变更参数值
			}
			mysqli_stmt_execute($stmt);
		}
	}
	return $stmt;
}

2.管理员登录和后台相关代码

前台登录样式login.php

	<div class="bg-image-pattern"></div>
	<div class="layui-container">
		<div class="admin-login-background">
			<div class="layui-form login-form">
				<form class="layui-form" action="">
					<div class="layui-form-item logo-title">
						<h1>系统登录</h1>
					</div>
					<div class="layui-form-item">
						<label class="layui-icon layui-icon-username" for="username"></label>
						<input type="text" id="username" lay-verify="required|account" placeholder="用户名或者邮箱" autocomplete="off" class="layui-input" >
					</div>
					<div class="layui-form-item">
						<label class="layui-icon layui-icon-password" for="password"></label>
						<input type="password" id="password" lay-verify="required|password" placeholder="密码" autocomplete="off" class="layui-input" value="">
					</div>
					<div class="layui-form-item">
						<div class="layui-btn layui-btn-fluid login" lay-submit="" lay-filter="login">登 入</div>
					</div>
				</form>
			</div>
		</div>
	</div>

后台登陆api/login.php

// 初始化
require './init.php';

class Login
{
    /**
     * 登录
     * @return array|string
     */
    public static function inLogin()
    {
        $username = I('username', 'post', '');
        $password = I('password', 'post', '');
        // 查询列表
        $result = module_login_to($username, $password);
        $arr = [];
        if ($result) {
            $arr = [
                'code' => 200,
                'tips' => "登录成功",
            ];
            $_SESSION['islogin'] = true;
        } else {
            $arr = [
                'code' => 100,
                'tips' => "账号密码错误",
            ];
            $_SESSION['islogin'] = false;
        }
        return toJson($arr);
    }

后台相关功能部分代码:(留言增删api/comment.php,api/post.php,标签增删api/tag.php,)

// 初始化
require './init.php';

class Comment
{
    /**
     * 留言
     * @return array|string
     */
    public static function CommentList()
    {
        $id = I('id', 'post', 'string', "");

        if ($id == "") {
            return toJson([
                'code' => 100,
                'data' => [],
                'tips' => "ID不能为空"
            ]);
        }
        // 查询列表
        $result = module_comment_list($id);
        $arr = [];
        foreach ($result as $key => $row) {
            $data[] = [
                'id' => $id,
                'cid' => $row['c_id'],
                'content' => $row['c_content'],
                'post_id' => $row['post_id'],
                'avatar' => $row['user_id'] ? qqAvatar($row['user_id']) :  'asset/images/anonymous.png',
                "c_time" => TimeAgo($row['c_time']),
                "i" => $key + 1
            ];
        }
        $arr = [
            'islogin' => $_SESSION['islogin'] ? '1' : '',
            'code' => 200,
            'data' => $data,
        ];
        return toJson($arr);
    }
    /**
     * 添加留言
     */
    public static function SaveComment()
    {
        //id
        $id = I('id', 'post', 'string', "");

        if ($id == "") {
            return toJson([
                'code' => 100,
                'data' => [],
                'tips' => "ID不能为空"
            ]);
        }
        //QQ
        $qq = baoguoInput($_POST['qq']);
        //内容
        $content = baoguoInput($_POST['content']);
        // 表单类型验证
        get_form_type($qq, $qq, $content);
        //敏感词拦截
        get_fuck($content);
        //判断内容长度
        get_text_length($content, 2);
        $result =  db_exec(DB_AFFECTED, 'INSERT INTO `post_comment` (`post_id`,`user_id`,`c_content`,`c_time`) VALUES(?,?,?,?)', 'ssss', [$id, $qq, $content, $_SERVER["REQUEST_TIME"]]);
        //判断插入状态
        if ($result) {
            $sup = module_comment_count($id);
            $sups = isset($sup['count']) ? $sup['count'] : 0;
            $data = ['code' => 200, 'tips' => '发布成功,数据重载中', "count" => $sups];
            exit(toJson($data));
        } else {
            $data = ['code' => 400, 'tips' => "发布失败"];
            exit(toJson($data));
        }
    }

    /**
     * 删除留言
     */
    public static function delComment()
    {
        $id = I('id', 'post', '');
        if (module_comment_del($id)) {
            return toJson([
                'code' => 200,
                'tips' => "删除成功",
            ]);
        } else {
            return toJson([
                'code' => 500,
                'tips' => "删除失败",
            ]);
        }
    }
}


if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    if (I('save', 'post', 'string', "") == 1) {
        // 添加数据
        Comment::SaveComment();
    } else if (I('save', 'post', 'string', "") == 2) {
        if (isset($_SESSION['islogin']) && $_SESSION['islogin']) {
            Comment::delComment();
        } else {
            exit(toJson(['code' => 400, 'tips' => '非法访问']));
        }
    } else {
        // 获取列表
        Comment::CommentList();
    }
} else {
    exit(toJson(['code' => 400, 'tips' => '非法访问']));
}

3.用户发表留言和前台相关代码

发送缩略图片api/image.php,留言内容限制,相关样式代码

html代码

<!--loading-->
	<div id="loading"></div>
	<!--背景-->
	<div class="bg-image"></div>
	<div class="bg-image-pattern"></div>
	<!--提示-->
	<div class="post-loading">
		<div class="post-tips"></div>
	</div>
	<!--header-->
	<div class="header">
		<div class="top" id="main">
			<div class="logo action"><a class="home">万能墙</a></div>
						<span class="start"><i class="baoguo-write-l" style="margin-right:0px;font-weight: 600;"></i></span>
		</div>

	</div>
	<!--发布表单-->
	<div class="addPost">
		<div class="inputPost" id="inputPost">
			<!--<input type="text" id="code" name="code" placeholder="qq邮箱验证码">-->
			<div class="tagList">
			</div>
			<!--<input type="text" id="tag" name="tag" placeholder="点击进行选择" readonly>-->
			<textarea id="content" placeholder="说点你想说的话..."></textarea>
			<div class="inputBottom">
				<input type="text" id="qq" name="qq" placeholder="你的QQ...">
				<a class="anonymous"><i class="baoguo-user-l"></i></a>
				<a class="upimage"><i class="baoguo-image-l add"></i></a>
				<input type="file" name="image" id="image" accept="image/*" style="display:none">
				<div class="submit s1"><img src="/asset/images/submit.png"></div>
			</div>
			<div id="yulan-image"><img class="yulan"></div>
		</div>
	</div>
		<!--评论表单-->
	<div class="addComment">
		<div class="inputComment inputPost">
			<textarea id="ccontent" placeholder="说点你想说的话..."></textarea>
			<div class="inputBottom">
				<input type="text" id="cqq" name="qq" placeholder="你的QQ...">
				<div class="submit s2"><img src="/asset/images/submit.png"></div>
				<div class="submit-close closeComment">取消</div>
			</div>
			<div id="yulan-image"><img class="yulan"></div>

			<div>
				<style>
					.ly-color .layui-timeline-item {
						color: #ff7b8c;
					}
				</style>
				<ul class="layui-timeline ly-color" id="CommentList">
					<li class="layui-timeline-item">
						<div class="layui-timeline-content layui-text">
							<div class="user">
								<div class="desc"><img class="avatar" src="">
									<div>
										<div class="title"> 一楼 </div>
										<div class="subtitle">11分钟前 | 来自网页端</div>
									</div>
								</div>
							</div>
							<p class="comment-content">
								万能墙的一切准备工作似乎都已到位。发布之弦,一触即发。
								<br>不枉近百个日日夜夜与之为伴。因小而大,因弱而强。
								<br>无论它能走多远,抑或如何支撑?至少我曾倾注全心,无怨无悔
							</p>
						</div>
					</li>
				</ul>
			</div>

		</div>


	</div>
	<!--帖子-->
	<div class="post"></div>
	<!--更多-->
	<div class="more"><a><i class="baoguo-angle-down-l"></i></a></div>
	<!--footer-->
	<div class="footer">万能墙系统
	<br>
	此页面仅供演示使用!
	<br>

发送缩略图app/image.php

//图像处理函数

//定义常量,表示缩略图缩放类型
define('IMAGE_FILL', 0);		//等比例填充白色背景
define('IMAGE_SCALE', 1);		//等比例缩放
define('IMAGE_SCALE_FILL', 2);	//等比例缩放,最大缩放

/**
 * 为图片生成缩略图
 * @param int $mode 缩略图生成模式
 * @param string $file_path 原图路径
 * @param int $new_width 目标宽度
 * @param int $new_height 目标高度
 * @param array $config 保存选项
 * @return array [0]表示成功或失败,成功时[1]表示文件路径,失败时[1]表示错误信息
 */
function image_thumb($mode, $file_path, $new_width, $new_height, $config=[]){
	//获取原图的宽高,并判断文件类型
	$info = getimagesize($file_path);
	$width = $info[0];      //图片宽度
	$height = $info[1];     //图片高度
	$mime = $info['mime'];  //图片类型
	//关联图像 MIME 类型和文件扩展名
	$file_type = [
		'image/png' => '.png',
		'image/jpeg' => '.jpg'
	];
	//判断图像类型,只允许 JPG 和 PNG 两种类型
	if(!isset($file_type[$mime])){
		return [false, '图片创建缩略图失败:只支持 jpg 和 png 类型的图片。'];
	}
	//生成缩略图
	$im = image_create($mime, $file_path);
	switch($mode){
		case IMAGE_FILL:
			$im = image_thumb_fill($im, $width, $height, $new_width, $new_height);
			break;
		case IMAGE_SCALE_FILL:
			$im = image_thumb_scale($im, $width, $height, $new_width, $new_height, true);
			break;
		default: 
			$im = image_thumb_scale($im, $width, $height, $new_width, $new_height);
	}
	//准备保存选项
	$config = array_merge([
		'base_path' => './',			//上传基本路径
		'sub_path' => date('Y-m/d/'),	//自动生成的子目录
		'name'=> md5(uniqid(rand())).$file_type[$mime] //自动创建文件名
	], $config);
	//自动创建目录
	$save_path = $config['base_path'].$config['sub_path'];
	if(!file_exists($save_path) && !mkdir($save_path, 0777, true)){
		return [false, '文件保存失败:创建目录失败'];
	}
	//将保存缩略图到指定目录
	image_save($mime, $im, $save_path.$config['name']);
	//返回文件路径(不包括base_path)
	return [true, $config['sub_path'].$config['name']];
}

/**
 * 生成缩略图(等比例填充白色背景)
 * @param resource $im 原图资源
 * @param int $width 原图宽度
 * @param int $height 原图高度
 * @param int $new_width 目标宽度
 * @param int $new_height 目标高度
 * @return 缩略图资源
 */
function image_thumb_fill($im, $width, $height, $new_width, $new_height){
	//等比例缩放计算
	if($width/$new_width > $height/$new_height) {
		$dst_width = $new_width;
		$dst_height = round($new_width / $width * $height);
	}else{
		$dst_height = $new_height;
		$dst_width = round($new_height / $height * $width);
	}
	//创建缩略图资源
	$thumb = imagecreatetruecolor($new_width, $new_height);
	//填充白色背景
	imagefill($thumb, 0, 0, imagecolorallocate($thumb, 255, 255, 255));
	//计算缩略图在画布上的位置
	$dst_x = ($new_width - $dst_width) / 2;
	$dst_y = ($new_height - $dst_height) / 2;
	//将按比例将缩略图重新采样,调整其位置
	imagecopyresampled($thumb, $im, $dst_x, $dst_y, 0, 0, $dst_width, $dst_height, $width, $height);
	return $thumb;
}

/**
 * 生成缩略图(等比例缩放)
 * @param resource $im 原图资源
 * @param int $width 原图宽度
 * @param int $height 原图高度
 * @param int $max_width 最大宽度
 * @param int $max_height 最大高度
 * @param bool $fill  是否最大缩放
 * @return 缩略图资源
 */
function image_thumb_scale($im, $width, $height, $max_width, $max_height, $fill=false){
	$dst_width = $width;
	$dst_height = $height;
	if($width/$max_width > $height/$max_height) {
		if($fill || ($width > $max_width)){
			$dst_width = $max_width;
			$dst_height = round($max_width / $width * $height);
		}
	}else{
		if($fill || ($height > $max_height)){
			$dst_height = $max_height;
			$dst_width = round($max_height / $height * $width);
		}
	}
	//创建缩略图资源
	$thumb = imagecreatetruecolor($dst_width, $dst_height);
	//将原图缩放填充到缩略图画布中
	imagecopyresampled($thumb, $im, 0, 0, 0, 0, $dst_width, $dst_height, $width, $height);
	return $thumb;
}

/**
 * 根据原图文件创建图像资源
 * @param string 图像MIME类型
 * @param string 原图文件路径
 * @return 返回创建的图像资源
 */
function image_create($mime, $file_path){
	switch($mime){
		case 'image/png':  return imagecreatefrompng($file_path);
		case 'image/jpeg': return imagecreatefromjpeg($file_path);
	}
}
/**
 * 保存图像资源
 * @param string $mime 图像MIME类型
 * @param resource $im 图像资源
 * @param string $save_path 保存路径
 * @return 成功返回true
 */
function image_save($mime, $im, $save_path){
	switch($mime){
		case 'image/png':  return imagepng($im, $save_path);
		case 'image/jpeg': return imagejpeg($im, $save_path, 100);
	}
}

生成分页app/page.php

//分页函数

//获取SQL分页 Limit
function page_sql($page, $size){
	return ($page-1) * $size . ',' . $size;
}

//生成URL参数
function page_url(){
	$params = $_GET;
	unset($params['page']);
	return http_build_query($params);	
}

//获取分页HTML(简单效果)
function page_html_simple($total, $page, $size){
	//计算总页数
	$maxpage = max(ceil($total/$size), 1);
	//如果不足2页,则不显示分页导航
	if($maxpage <= 1) return '';
	//获取URL参数字符串
	$url = page_url();
	$url = $url ? "?$url&page=" : '?page=';
	//拼接 首页
	$first = "<a href=\"{$url}1\">首页</a>";
	//拼接 上一页
	$prev = ($page==1) ? '<span>上一页</span>' :
			'<a href="'.$url.($page-1).'">上一页</a>';
	//拼接 下一页
	$next = ($page==$maxpage) ? '<span>下一页</span>' :
			'<a href="'.$url.($page+1).'">下一页</a>';
	//拼接 尾页
	$last = "<a href=\"{$url}{$maxpage}\">尾页</a>";
	//组合最终样式
	return "$first $prev $next $last 当前为:$page/$maxpage";
}

//获取分页HTML
function page_html($total, $page, $size, $num=5){
	$page = max((int)$page, 1);             //当前访问的页码,最低为1
	$maxpage = max(ceil($total/$size), 1);  //计算总页数
	$num = floor($num/2);                   //计算当期页前后显示的相关链接个数
	$url = page_url();		                //获取URL参数字符串
	//拼接URL
	$url = $url ? "?$url&page=" : '?page=';
	$html = ''; //保存拼接结果
	//生成首页、上一页
	if($page > 1){
		$html .= "<a href=\"{$url}1\">首页</a>";
		$html .= '<a href="'.$url.($page-1).'">上一页</a>';
	}else{
		$html .= '<span>首页</span>';
		$html .= '<span>上一页</span>';
	}
	//生成分页导航
	$start = $page - $num;
	$end = $page + $num;
	if($start < 1){
		$end = $end+(1-$start);
		$start = 1;
	}
	if($end > $maxpage){
		$start = $start-($end-$maxpage);
		$end = $maxpage;
	}
	($start < 1) && $start = 1;
	($start > 1) && $html .= '<i>...</i>';
	for($i=$start; $i<=$end; ++$i){
		if($i == $page){
			$html .= "<a href=\"{$url}{$i}\" class=\"curr\">$i</a>";
		} else {
			$html .= "<a href=\"{$url}{$i}\">$i</a>";
		}
	}
	($end < $maxpage) && $html .= '<i>...</i>';
	//生成下一页、尾页
	if($page == $maxpage){
		$html .= '<span>下一页</span>';
		$html .= '<span>尾页</span>';
	}else{
		$html .= '<a href="'.$url.($page+1).'">下一页</a>';
		$html .= "<a href=\"{$url}{$maxpage}\">尾页</a>";
	}
	//返回结果
	return $html;
}

留言字数限制app/function.php

function get_text_length($content, $len = 3)
{
	//最少字数限制
	$minCommentlength = $len;
	//最多字数限制
	$maxCommentlength = 500;
	$pointCommentlength = mb_strlen($content, 'utf-8');
	if ($pointCommentlength < $minCommentlength) {
		header("Content-type: text/html; charset=utf-8");
		$data = array(
			'code' => 400,
			'tips' => '内容最少输入10字'
		);
		exit(json_encode($data));
	}
	if ($pointCommentlength > $maxCommentlength) {
		header("Content-type: text/html; charset=utf-8");
		$data = [
			'code' => 400,
			'tips' => '内容最多输入500字'
		];
		exit(json_encode($data));
	}
}

4.相关成果展示

万能墙系统介绍

之前写过点击这里查看

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FJSAY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值