登录页面逻辑
1.表单校验是否空
2. 数据校验是否合理
3. 表单状态保持(将数据更新到数据库)
4. 记录登录状态
5. 跳转
//载入配置文件
require_once'../config.php';
function login(){
// 1.校验
if(empty($_POST['email'])){
$GLOBALS['message']='请填写邮箱';
return;
}
if(empty($_POST['password'])){
$GLOBALS['message']='请填写密码';
return;
}
$email=$_POST['email'];
$password=$_POST['password'];
// 当客户端提交完整的表单信息就应该开始对其进行数据校验,把例子换位数据库校验
$conn=mysqli_connect(DB_HOST,DB_USER,DB_PASS,DB_NAME);
if(!$conn){
exit('<h1>连接数据库失败</h1>');
}
$query=mysqli_query($conn,"select * from users where email='{$email}' limit 1;");
if(!$query){
$GLOBALS['message']='登陆失败请重试';
return;
}
$user=mysqli_fetch_assoc($query);
if(!$user){
$GLOBALS['message']='用户名不存在';
return;
}
if($user['password']!=($password)){
$GLOBALS['message']='密码错误';
return;
}
// 表单状态保持
// 记录登陆状态
session_start();
$_SESSION['current_login_user']=$user;
// 一切ok,跳转
header('Location:/admin/');
}
if($_SERVER['REQUEST_METHOD']=='POST')
{
login();
}
页面访问权限控制
利用session在首页的代码页开头检测登录标识,若没有,则跳转到登陆页,不允许访问内容页面
session_start();
if(empty($_SESSION['current_login_user'])){
header('Location:/admin/login.php');
}
动态获取登陆用户头像
在avatar.php中
<?php
// 根据用户邮箱获取用户头像
// email=》image
require_once '../../config.php';
// 1.接收传递过来的邮箱
if(empty($_GET['email'])){
exit('缺少必要参数');
}
$email=$_GET['email'];
// 连接数据库
$conn=mysqli_connect(DB_HOST,DB_USER,DB_PASS,DB_NAME);
if(!$conn){
exit('连接数据库失败');
}
$res=mysqli_query($conn,"select avatar from users where email = '{$email}' limit 1;");
if(!$res){
exit('查询失败');
}
$row=mysqli_fetch_assoc($res);
echo $row['avatar'];
?>
在login.php中
<script src="/static/assets/vendors/jquery/jquery.js"></script>
<script>
$(function(){
// 1.单独作用域
// 2.确保页面加载过后执行
// 目标:在用户输入自己的邮箱过后,页面上显示这个邮箱的头像
// 实现:
// 时机:邮箱文本框失去焦点,并且能够拿到文本框中填写的邮箱时
// 事情:获取这个文本框中填写的邮箱对应的头像地址,展示到上面的img元素上
var emailFormat=/[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/;
// test()校验正则表达式,exec()提取正则表达式里的组
$('#email').on('blur',function(){
var value=$(this).val();
// 忽略邮箱为空或不是邮箱
if(!value||!emailFormat.test(value)) return;
// 因为客户端无法用js操作数据库,所以发送ajax请求,告诉服务端的某个接口,让这个接口帮助客户端获取头像地址
$.get('/admin/api/avatar.php',{email:value},function(res){
// 希望res=》这个邮箱对应的头像地址
if(!res) return;
// 展示到img元素上
$('.avatar').attr('src',res);
})
})
})
</script>
输入邮箱后,emial框失去焦点后显示出头像
*require 载入文件路径问题*
index.php incude了sidebar.php require的相对路径是相对于index不是sidebar来看的
封装数据库查询操作
在functions.php(用于封装公共函数)中定义函数
// 通过一个数据库查询获取数据
function bx_fetch($sql){
$conn=mysqli_connect(DB_HOST,DB_USER,DB_PASS,DB_NAME);
if(!$conn){
exit('连接失败');
}
$query=mysqli_query($conn,$sql);//查询失败可能是语句写错,所以给个机会,不要直接exit
if(!$query) {
return false;
}
while($row=mysqli_fetch_assoc($query)){
$result[]=$row;
}
return $result;
}
// 获取单条数据
function bx_fetch_one($sql){
$res=bx_fetch($sql);
return isset($res[0])?$res[0]:null;
}
回到index.php中调用
// 重复的操作一定封装起来
// 为社么count(1/2/3/4) 效率最高,因为直接select 1也会产生4行数据 count*会扫描里面有多少字段,浪费 count(id)也会看有多少id
$posts_count=bx_fetch_one('select count(1) as num from posts;')['num'];
//as num设置返回列的名字
// var dump发现返回指是一个关联数组 array(1){array(1){["num"]=>string(1) "4"}
// 所以想要直接得到数字$posts_count['num']
$categories_count=bx_fetch_one('select count(1) as num from categories;')['num'];
$comments_count=bx_fetch_one('select count(1) as num from comments;')['num'];
在html中调用
<ul class="list-group">
<li class="list-group-item"><strong><?php echo $posts_count;?></strong>篇文章(<strong>2</strong>篇草稿)</li>
<li class="list-group-item"><strong><?php echo $categories_count;?></strong>个分类</li>
<li class="list-group-item"><strong><?php echo $comments_count;?></strong>条评论(<strong>1</strong>条待审核)</li>
</ul>
通过session获取登陆信息显示在页面上
$_SESSION['current_login_user']=$user;
在公用函数页定义函数functions.php
session_start();
function bx_get_current_user(){
if(empty($_SESSION['current_login_user'])){
header('Location:/admin/login.php');
exit();//没有必要再执行之后的代码(包括html)
}
return $_SESSION['current_login_user'];
}
在sidebar.php中
<?php
require_once '../functions.php';
$current_page=isset($current_page)?$current_page:'';
$current_user=bx_get_current_user();
?>
<div class="aside">
<div class="profile">
<img class="avatar" src="<?php echo $current_user['avatar'];?>">
<h3 class="name"><?php echo $current_user['nickname'];?></h3>
</div>
<ul class="nav">
<li <?php echo $current_page=='index.php'?'class="active"':'' ?>>
<a href="index.php"><i class="fa fa-dashboard"></i>仪表盘</a>
</li>
<?php $menu_posts=array('posts.php','post-add.php','categories.php');?>
<li <?php echo in_array($current_page,$menu_posts)?'class="active"':'' ?>>
<a href="#menu-posts" <?php echo in_array($current_page,$menu_posts)?'':'class="collapsed"'?> data-toggle="collapse">
<i class="fa fa-thumb-tack"></i>文章<i class="fa fa-angle-right"></i>
</a>
<ul id="menu-posts" class="collapse<?php echo in_array($current_page,$menu_posts)?' in':''?>">
<li <?php echo $current_page=='posts.php'?'class="active"':'' ?>><a href="posts.php">所有文章</a></li>
<li <?php echo $current_page=='post-add.php'?'class="active"':'' ?>><a href="post-add.php">写文章</a></li>
<li <?php echo $current_page=='categories.php'?'class="active"':'' ?>><a href="categories.php">分类目录</a></li>
</ul>
</li>
<li <?php echo $current_page=='comments.php'?'class="active"':'' ?>>
<a href="comments.php"><i class="fa fa-comments"></i>评论</a>
</li>
<li <?php echo $current_page=='users.php'?'class="active"':'' ?>>
<a href="users.php"><i class="fa fa-users"></i>用户</a>
</li>
<?php $menu_posts2=array('nav-menus.php','slides.php','settings.php');?>
<li <?php echo in_array($current_page,$menu_posts2)?'class="active"':'' ?>>
<a href="#menu-settings"
<?php echo in_array($current_page,$menu_posts2)?'':'class="collapsed"' ?> data-toggle="collapse">
<i class="fa fa-cogs"></i>设置<i class="fa fa-angle-right"></i>
</a>
<ul id="menu-settings" class="collapse <?php echo in_array($current_page,$menu_posts2)?' in':'' ?>">
<li <?php echo $current_page=='nav-menus.php'?'class="active"':'' ?>><a href="nav-menus.php">导航菜单</a></li>
<li <?php echo $current_page=='slides.php'?'class="active"':'' ?>><a href="slides.php">图片轮播</a></li>
<li <?php echo $current_page=='settings.php'?'class="active"':'' ?>><a href="settings.php">网站设置</a></li>
</ul>
</li>
</ul>
</div>
categories页数据分类展示
php中
$categories=bx_fetch('select * from categories');
html中,用foreach渲染
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th class="text-center" width="40"><input type="checkbox"></th>
<th>名称</th>
<th>Slug</th>
<th class="text-center" width="100">操作</th>
</tr>
</thead>
<tbody>
<?php foreach($categories as $item): ?>
<tr>
<td class="text-center"><input type="checkbox"></td>
<td><?php echo $item['name'];?></td>
<td><?php echo $item['slug'];?></td>
<td class="text-center">
<a href="javascript:;" class="btn btn-info btn-xs">编辑</a>
<a href="javascript:;" class="btn btn-danger btn-xs">删除</a>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>
添加分类功能
增加一个公用函数functions.php
// 增删查改
function bx_execute($sql){
$conn=mysqli_connect(DB_HOST,DB_USER,DB_PASS,DB_NAME);
if(!$conn){
exit('连接失败');
}
$query=mysqli_query($conn,$sql);//查询失败可能是语句写错,所以给个机会,不要直接exit
if(!$query) {
return false;
}
$affected_rows=mysqli_affected_rows($conn);
mysqli_close($conn);
return $affected_rows;
}
在categories.php中
表单校验,保存,连接添加到数据库,在列表中显示出新增数据。
function add_category(){
if(empty($_POST['name']||empty($_POST['slug']))){
$GLOBALS['message']='请完整填写表单';
$GLOBALS['success']=false;
return;
}
// 接受并保存
$name=$_POST['name'];
$slug=$_POST['slug'];
// 添加到数据库
$rows=bx_execute("insert into categories values(null,'{$slug}','{$name}');");
$GLOBALS['success']=$rows>0;
$GLOBALS['message']=$rows<=0?'添加失败':'添加成功';
}
if($_SERVER['REQUEST_METHOD']=='POST'){
add_category();
}
单条数据删除
点击删除按钮跳转到删除处理页:新建categories-delete.php
通过categories界面传来的id连接数据库删除id对应的数据后返回categories界面。
categories.php
<a href="categories-delete.php?id=<?php echo $item['id'];?>" class="btn btn-danger btn-xs">删除</a>
categories-delete.php
<?php
// 根据客户端穿过来的id删除对应数据
require_once '../functions.php';
if(empty($_GET['id'])){
exit('缺少必要参数');
}
$id=$_GET['id'];
$rows=bx_execute('delete from categories where id='.$id);//
// (删除成功跳转到列表页)
header('Location:/admin/categories.php');
?>
批量删除
从传1个id到传多个id到服务端
checkbox
attr与prop的区别
- attr获取元素属性
- prop获取元素对应的dom对象属性
- checked属性是dom中的,元素并没有写出,除非在标签中明确写出checked=”checked/…“
- 若在标签中没有写checked=”checked/…“,则用attr访问checked的结果是undefined,用prop访问是true
- 若标签中写出checked=”checked/…“,则用attr访问checked结果是checked,用prop访问结果是true。(html与dom封装对象的属性里将checked=checked改为布尔值true/false)
$(function($) {
var $tbodyCheckbox = $('tbody input');
var $btnDelete = $("#btn_delete");
// ***********************方法1***************************
var allChecks = []; //数组用于存储所有被选中信息
$tbodyCheckbox.on('change', function() {
// 三种获取自定义属性的方法
// 1.$(this).dataset['id']
// 2.$(this).attr('data-id')
// 3.$(this).data('id')
var id = $(this).data('id');
if ($(this).prop('checked')) { //只访问当前点击的
allChecks.push(id);
console.log(allChecks);
} else {
allChecks.splice(allChecks.indexOf(id), 1); //当此勾选状态不是true时,将其从数组中删除
}
console.log(allChecks);
allChecks.length ? $btnDelete.fadeIn() : $btnDelete.fadeOut();
$btnDelete.prop('href', '/admin/categories-delete.php?id=' + allChecks);
})
})
</script>
***********************方法2(最容易理解)***************************
// 在表格中的任意一个checkbox选中状态改变时(此处最好用change不用click因为change是针对改变的触发)
$tbodyCheckbox.on('change', function() {
// 有任意一个checkbox选中就显示批量删除的按钮,否则隐藏
var flag = false;
$tbodyCheckbox.each(function(i, item) {
// 看有没有被选中的
if ($(item).prop('checked')) flag = true;
})
flag ? $btnDelete.fadeIn() : $btnDelete.fadeOut();
})
此时,categories-delete.php中
$rows=bx_execute('delete from categories where id='.$id);//
应改为
$rows=bx_execute('delete from categories where id in('.$id.');');//
- !(’.$id.’)注意字符串拼接
- =换为in!
$id=$_GET['id'];//不要$id=(int)$_GET['id']
编辑功能
categories页中的功能
1.列表数据查询
默认有
2.数据新增
必须post请求
并且没有在url中传id
3.更新
在url中传id
- 点击编辑按钮传递id值,服务端返回编辑表单页
<a href="/admin/categories.php?id=<?php echo $item['id']; ?>" class="btn btn-info btn-xs">编辑</a>
- 获取id值
// 若有传到id
if (!empty($_GET['id'])) {
// 客户端通过url传递了一个id
// =>客户端要来拿一个修改数据的表单
// =>需要拿到用户想要修改的数据
$current_edit_category= bx_fetch_one('select * from categories where id =' . $_GET['id']);
}
- 在页面中相应修改/显示值
若为编辑页则显示编辑框,否则显示添加框
<div class="row">
<div class="col-md-4">
<?php if (isset($current_edit_category)) : ?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?> " method="post">
<h2>编辑《<?php echo $current_edit_category['name'] ?>》</h2>
<div class="form-group">
<label for="name">名称</label>
<input id="name" class="form-control" name="name" type="text" placeholder="分类名称" value="<?php echo $current_edit_category['name'] ?>">
</div>
<div class="form-group">
<label for="slug">别名</label>
<input id="slug" class="form-control" name="slug" type="text" placeholder="slug" value="<?php echo $current_edit_category['slug'] ?>">
<p class="help-block">https://zce.me/category/<strong>slug</strong></p>
</div>
<div class="form-group">
<button class="btn btn-primary" type="submit">保存</button>
</div>
</form>
<?php else : ?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?> " method="post">
<h2>添加新分类目录</h2>
<div class="form-group">
<label for="name">名称</label>
<input id="name" class="form-control" name="name" type="text" placeholder="分类名称">
</div>
<div class="form-group">
<label for="slug">别名</label>
<input id="slug" class="form-control" name="slug" type="text" placeholder="slug">
<p class="help-block">https://zce.me/category/<strong>slug</strong></p>
</div>
<div class="form-group">
<button class="btn btn-primary" type="submit">添加</button>
</div>
</form>
<?php endif ?>
</div>
- 若有id值传入则为编辑页,调用edit函数
if ($_SERVER['REQUEST_METHOD'] == 'POST') { //在增加了编辑功能后需多加一个对是否url传有id的判断
if (empty($_GET['id'])) {
add_category();
} else {
edit_category();
}
}
- edit函数
function edit_category() //3.数据更新(编辑)
{
global $current_edit_category;
// 接受并保存
//=>要么是提交过来的数据要么是原有的值
//=>若提交的值为空,则为原有的值current_edit_category
$id = $_GET['id'];
$name = empty($_POST['name']) ? $current_edit_category['name'] : $_POST['name'];
$current_edit_category['name'] = $name; //因为html页面显示的数据为$current_edit_category['name'] ,所以需更新数据为新post的数据
$slug = empty($_POST['slug']) ? $current_edit_category['slug'] : $_POST['slug'];
$current_edit_category['slug'] = $slug;
// 添加到数据库
//此处用到id,所以获取编辑id数据的代码段放前面
$rows = bx_execute("update categories set slug='{$slug}', name='{$name}' where id={$id}");//?????
$GLOBALS['success'] = $rows > 0;
$GLOBALS['message'] = $rows <= 0 ? '保存失败': '保存成功';
}
疑问: $rows = bx_execute("update categories set slug='{$slug}', name='{$name}' where id={$id}");//?????
没有返回值????