一、表单传值
学习目标:了解表单传值的作用和意义,掌握基础的表单传值的实现
- 表单传值概念
- GET传值
- POST传值
- PHP接收表单传值
1、表单传值
目标:了解表单传值的概念、价值和意义
概念
表单传值:通过HTML表单,实现数据在浏览器端录入,并传递给后端语言
- 表单传值是一种数据的传递方式
- 表单传值有多种,但是在网站应用里通常使用两种
- GET传值
- POST传值
- 表单传值给服务器做动态数据支撑提供了必要条件
- 数据可以从浏览器端存储到服务器(数据新增)
- 数据可以通过浏览器让服务器进行数据筛选(数据查询)
- 表单传值需要用到表单元素
- form表单:用来包裹多个表单元素一并提交
- input表单元素
- text:文本数据
- password:密文数据
- textarea:长文本数据
- hidden:隐藏数据
- submit:提交按钮
- 下拉框表单:select
- 按钮选择
- radio:单选框(互斥选框)
- CheckBox:多选框
- url传值
- a标签:直接在请求链接后使用 ? + 数据
步骤
1、确定浏览器传值给服务器
2、选择传值的方式
- url传值:a标签
- form表单传值:表单元素
示例
1、url传值
<html>
<body>
<a href="login.php?username=XXX">登录</a>
</body>
</html>
2、表单传值
<html>
<body>
<form action="#提交对象:login.php" method="GET/POST">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="登录">
</form>
</body>
</html>
小结
1、表单传值是利用HTML里的表单元素收集用户数据,或者是提供url绑定数据
- form表单:通常是用户提交写入的数据
- url绑定:通常是系统提供的数据,然后让用户点击操作
2、表单传值打通了用户与服务器的数据关系,允许用户将自己的数据提交给服务器,从而有了服务器的可操作空间
2、POST传值
目标:了解POST传值的方法和目的
概念
POST传值:通过form表单使用post方式,将数据从浏览器以肉眼不可见形式传输给服务器
- POST传值必须使用form表单
- form表单的属性method的值为post(不区分大小写)
- 所有需要提交给服务器的数据元素都必须在form表单内部
- 要提交的表单元素本身必须拥有name属性(无name属性无法提交)
步骤
1、form表单method属性使用post
2、根据需要提交的数据的数量和类型选择合适的form表单元素
示例
1、提交用户登录信息:用户名和密码信息,提交给login.php处理
<html>
<body>
<form action="login.php" method="post">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" name="submit" value="登录">
</form>
</body>
</html>
2、提交新闻信息入库:标题、作者、内容
<html>
<body>
<form action="insert.php" method="post">
标题:<input type="text" name="title">
作者:<input type="text" name="author">
内容:<textarea name="content"></textarea>
<input type="submit" value="提交">
</form>
</body>
</html>
小结
1、post提交数据是基于form表单,只能通过form表单实现
2、post提交的数据不会在浏览器的地址栏出现,是为了让数据的安全性增加
3、post的原始意义在于数据的提交入库:也就是说通过post提交的数据通常是要进行数据库的写操作的(安全要求除外)
3、GET传值
目标:了解GET传值的方法和目的
概念
GET传值:将浏览器的数据以肉眼可见的形式提交给服务器
- GET传值可以通过form表单实现也可以通过url直接实现
- form表单:method属性使用GET(要提交的元素必须有name属性)
- URL:直接在a标签href属性里增加要传递的数据
- GET传值的数据可以在浏览器地址栏里看到
步骤
1、确定使用GET方式传递数据
2、选择合适的传值方式
- form表单method为GET提交多个数据
- a标签href属性提交数据:index.php?name=value&name=value…
示例
1、使用form表单提交检索数据
<html>
<body>
<form action="check.php" action="get">
商品名字:<input type="text" name="goods_name">
商品颜色:<select name="goods_color">
<option value=1>红色</option>
<option value=2>绿色</option>
<option value=3>蓝色</option>
</select>
<input type="submit" value="查询">
</form>
</body>
</html>
2、使用url传值:要删除的数据(新闻)
<html>
<body>
<ul>
<li><a href="delete.php?id=1">太平洋竟然漏水</a></li>
<li><a href="delete.php?id=2">珠穆朗玛峰长高了</a></li>
<li><a href="delete.php?id=3">白令海峡结冰了</a></li>
<li><a href="delete.php?id=4">北极熊去南极找企鹅</a></li>
<li><a href="delete.php?id=5">百慕大又双叕沉船</a></li>
</ul>
</body>
</html>
小结
1、GET传值是会让用户能够直接在地址栏里看到具体的数据信息的
2、GET传值的目的,通常是为了将数据提交给服务器用户数据的查询操作(提交的数据通常是查询条件)
3、GET不会传输特别重要的数据信息
4、PHP接收表单数据
目标:了解PHP中接收数据的语法,掌握PHP中不同的接收方式所代表的含义
概念
PHP接收表单数据:PHP将用户通过表单传递的数据变成PHP可识别的数据和可操作的方式
- PHP接收数据的系统行为,自动接收(PHP语言为了开发者使用方便)
- PHP接收数据有三种方式,每一种方式都是表单元素的name属性的值作为数组元素下标,具体数据作为数组元素的值
- $_GET:接收浏览器GET方式传递的数据
- $_POST:接收浏览器POST方式传递的数据
- $_REQUEST:接收浏览器GET和POST提交的数据
- POST与GET如果有同名表单(名字),POST会覆盖GET
步骤
1、明确浏览器数据提交的方式:开发者后台定义后,不受浏览器端用户控制
2、选择合适的PHP接收方式
3、在浏览器请求的PHP脚本中使用PHP接收指令
4、通过数组下标(表单元素名字)访问数据(提交的值)
示例
1、接收用户登录提交的信息:login.php
# 用户是POST提交,所以应该使用$_POST或者$_REQUEST接收
var_dump($_GET,$_POST,$_REQUEST);
# 取出数据加工
$username = $_POST['username'];
$password = $_POST['password'];
2、接收用户的删除信息:delete.php
$id = $_GET['id'];
# 安全接收方式
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
# isset判定是为了让脚本在没有真正接到数据时不会报错,从而不友好
# intval是因为id通常是逻辑的,需要加工成整型,这样可以防止外部进行SQL攻击
# 默认值0是为了方便后续进行判定,因为逻辑主键不会存在0的
小结
1、PHP提供了三种方式接收用户提交的普通表单数据
- $_GET:接收浏览器GET方式传递的数据
- $_POST:接收浏览器POST方式传递的数据
- $_REQUEST:接收浏览器GET和POST提交的数据(因为覆盖所以不安全)
2、接收数据时要考虑到数据的安全性
- 恶意访问:isset进行存在性判定
- 数据乱写:类型转换保证数据安全
- 数据判定:保证数据的可靠性再进行服务器其他操作(提升服务器的有效工作效率)
二、新闻管理系统
学习目标:灵活运用PHP操作MySQL数据库,掌握PHP和SQL的综合运用,实现数据库的一套基本增删改查操作
- 数据库设计
- 新增新闻
- 查看新闻
- 新闻列表
- 编辑新闻
- 删除新闻
1、数据库设计
目标:能够根据具体的需求信息,分析数据库的实体范围、实体关系,创建对应的数据库环境
概念
数据库设计:根据要做的系统分析出内部存在的实体以及实体间的联系,然后创建对应的表来实现需求里复杂的关系
步骤
1、分析找出需求中存在的实体(确定表数量)
2、找出实体本身应该存在的信息(确定表内在属性)
3、找出实体间的关联关系(确定表关系)
4、必要时确定表关系的约束性(外键、唯一键等)
5、创建数据库
示例
1、一个新闻管理系统应该包含的信息如下
- 新闻发布者:作者author
- 新闻本身:news
- 新闻分类:category
- 发布者来源:新闻平台platform
- 评论信息:comment
- 用户管理:user
简易新闻管理系统:作者、新闻
2、确定试题内在联系(简易新闻管理系统)
- 作者:作者id、名字、所属平台
- 新闻:新闻id,标题、内容、发布时间
3、确定实体间的关联关系(简易新闻管理系统)
- 新闻:作者id
4、创建数据库
# 数据库
create database news charset utf8;
# 创建数据表
create table news.author(
id int primary key auto_increment,
name varchar(50) not null,
platform varchar(50) comment '发布平台'
)charset utf8;
insert into news.author values(null,'佚名','佚名自媒体'),
(null,'留白','海上自媒体'),(null,'花田错','音乐自媒体');
create table news.news(
id int primary key auto_increment,
title varchar(50) not null comment '新闻标题',
content text not null comment '新闻内容',
a_id int unsigned not null comment '作者id',
publish int unsigned not null comment '发布时间'
)charset utf8;
小结
1、根据需求设计数据库实际上是一个经验活,需要做的多之后才知道具体该怎么划分和设计,但是总的步骤是不变的
- 确定实体数量(表)
- 确定实体内在关联(字段)
- 确定实体间关系(外联)
- 设置数据库
2、数据库的设计就是看上去平台可能不大,但是实际涉及的实体数量和字段却很多。大型项目的实体数量和字段数量是非常多的
2、新增新闻
目标:了解新增数据的业务逻辑,运用表单传值和PHP操作数据库实现数据的新增入库
概念
新增新闻:用户通过新增表单实现新闻入库
步骤
1、确定访问新增表单的url:用户直接访问(add.php)
-
获取作者信息
-
PHP加载HTML文件进行表单展示
2、确定表单的提交方式和提交对象
- method:post提交
- action:将来处理新闻新增的PHP文件:insert.php
- 显示作者信息
3、PHP接收用户提交的数据
- 安全接收
- 数据逻辑验证
4、PHP操作数据库
- 连接认证(选择数据库)
- 字符集设置
- 安全验证
5、组织SQL入库
- 组织SQL指令
- 执行SQL指令
- 安全验证SQL执行
6、提示操作结果
- 正确:跳转到列表页
- 错误:回到新增页面
实现
1、创建add.php,然后加载添加新闻的表单
# 包含模板文件
include 'news_add.html';
2、修改资源:静态资源(js、css)和表单资源
<form action="insert.php" method="post">
<div class="form-group">
<label for="news_title">新闻标题</label>
<input type="text" name="title" class="form-control" id='news_title'>
</div>
<div class="form-group">
<label for="news_author">作者</label>
<select name="author">
<option value="a_id">作者名字</option>
</select>
</div>
<div class="form-group">
<label for="news_content">新闻内容</label>
<textarea class="form-control" name="content" rows="12"></textarea>
</div>
<button class="btn btn-primary btn-block">添加</button>
</form>
3、在add.php中,加载新增表单之前要获取所有作者信息(假设作者是注册的)
# 连接认证
$conn = @mysqli_connect('localhost','root','root','news','3306') or die(mysqli_connect_error());
# 设置字符集
mysqli_set_charset($conn,'utf8') or die(mysqli_error($conn));
# 获取所有数据
$res = mysqli_query($conn,'select id,name from author') or die(mysqli_error($conn));
# 取出数据
$authors = [];
while($row = mysqli_fetch_assoc($res)){
$authors[] = $row;
}
# 包含模板文件
include 'news_add.html';
4、在模板中显示所有的作者信息
<form action="insert.php" method="post">
<div class="form-group">
<label for="news_title">新闻标题</label>
<input type="text" name="title" class="form-control" id='news_title'>
</div>
<!--正常不用增加这一栏,一般需要用户登录才能发表-->
<div class="form-group">
<label for="news_author">作者</label>
<input type="text" name="author" class="form-control" id='news_author'>
<select name="author">
<?php foreach($authors as $author):?>
<option value="<?php echo $author['id'];?>"><?php echo $author['name'];?></option>
<?php endforeach;?>
</select>
</div>
<div class="form-group">
<label for="news_content">新闻内容</label>
<textarea class="form-control" name="content" rows="12"></textarea>
</div>
<button class="btn btn-primary btn-block">添加</button>
</form>
5、创建insert.php接收数据
# 接收数据
$title = $_POST['title'] ?? '';
$content = $_POST['content'] ?? '';
$a_id = $_POST['author'] ?? 0;
# 安全判定(简单判定)
if(empty($title) || empty($content)){
# 错误跳转重来
header('refresh:3;url=add.php');
echo '新闻标题和内容都不能为空!';
exit;
}
6、连接认证数据库
# 连接认证
$conn = @mysqli_connect('localhost','root','root','news','3306') or die(mysqli_connect_error());
# 设置字符集
mysqli_set_charset($conn,'utf8') or die(mysqli_error($conn));
7、组织数据入库
# 数据入库:时间戳可以使用mysql自动生成,也可以使用PHP生成好放进去(建议生成好)
$publish = time();
$sql = "insert into news values(null,'{$title}','{$content}',{$a_id},{$publish})";
$res = mysqli_query($conn,$sql);
8、判定结果,然后处理
- 正确跳转到列表页(首页):index.php
- 失败回到新增页面:add.php
# 判定数据
if($res){
header('refresh:2;url=index.php');
echo '新闻:' . $title . ' 新增成功!';
}else{
header('refresh:3;url=add.php');
echo '新闻:' . $title . '新增失败!';
}
# 最后可以不用使用exit终止脚本了
小结
1、新增的核心逻辑是分成两个部分的
- 提供新增表单:让用户可以提供数据
- 提供新增处理:接收用户数据后安全入库
2、表单页面通常属于HTML文件,一般情况下,我们都不会让浏览器直接访问HTML文件,而是访问对应的PHP文件,由PHP去选择是加载HTML文件还是进行其他逻辑处理
3、新增要考虑成功后的逻辑
- 成功后去到列表:提示成功即可,也不需要获取成功操作的其他数据
- 成功后去到查看详情页:需要获取到当前操作成功的id,然后带着id去请求另外一个实现详情页的文件(PHP文件)
3、封装
目标:了解封装代码的意义,以及如何进行实际的封装操作
概念
封装:将需要重复使用的代码或者某些特定的功能使用函数进行管理
- 根据业务需求对操作进行封装,后续只需要直接对文件进行包含,然后对函数调用即可
- 业务封装主要是根据数据库的操作需求实现各类封装
- 初始化
- 数据新增
- 数据编辑(更新和删除)
- 数据查询
步骤
1、初始化封装:连接认证、数据库选择、字符集设置
2、SQL指令执行封装:错误处理
3、自动更新封装:提供数据自动构造更新指令,实现更新
4、自动查询操作:提供查询条件,自动构造查询指令,实现查询
5、普通查询:用户自己组装SQL指令
实现
1、初始化封装(Sql.php)
# 初始化功能:连接认证、选择数据库、设定字符集
# 成功返回连接对象,失败返回false,错误记录在错误参数中
function connect($user,$pass,$dbname,&$error,$host = 'localhost',$port = '3306',$charset = 'utf8'){
# 连接认证
$conn = @mysqli_connect($host,$user,$pass,$dbname,$port);
# 验证错误
if(!$conn){
$error = iconv('gbk','utf-8',mysqli_connect_error());
return false;
}
# 设置字符集
if(!mysqli_set_charset($conn,$charset)){
$error = mysqli_error($conn);
return false;
}
# 返回对象
return $conn;
}
2、SQL指令执行封装
# 外部传入SQL,负责执行也验证SQL语法问题,成功返回结果,失败返回false,错误记录在错误参数中
function query($conn,$sql,&$error){
# 执行SQL
$res = mysqli_query($conn,$sql);
# 判定
if($res === false){
$error = mysqli_error($conn);
return false;
}
# 返回执行的正确结果
return $res;
}
- 以上操作也是普通的写操作
3、简易自动更新
# 用户提供要更新的数据和主键id,自动组装SQL
# 成功返回受影响的行数,失败返回false(0表示没有更新)
function auto_update($conn,$data,$table,&$error,$id = 0){
# 组织更新部分数据:字段名 = 值
$set = '';
foreach($data as $k => $v){
$set .= $k . "='{$v}',";
} # title = 'title',content = 'content',
# 清除多余的右侧逗号
$set = rtrim($set,','); # $set : title = 'title',content = 'content'
# 组织更新指令
$sql = "update {$table} set {$set} ";
# 组装where条件(id不为0才组织):要求主键字段名字必须为ID
if($id) $sql .= ' where id = ' . $id;
# update 表名 set title = 'title',content = 'content' where id = 1
# 执行
if(query($conn,$sql,$error))
return mysqli_affected_rows($conn);
else return false;
}
4、简易自动查询
# 系统提供查询条件(只能是=比较和and逻辑运算),可以查询一条记录或者多条记录
# 成功返回数组(多条二维数组,一条一维数组)失败返回false,错误记录在参数中
function auto_read($conn,$table,&$error,$where = [],$all = false){
# 组装查询条件:默认永远为真
$where_clause = ' where 1 '; # where 1
if($where){ # 空数组自动转换成布尔false
# 解析条件
foreach($where as $k => $v){
$where_clause .= ' and ' . $k . " = '$v' ";
} # where 1 and title = 'news' ...
}
# 组织完整SQL
$sql = "select * from {$table} {$where_clause}";
$res = query($conn,$sql,$error);
# 判定执行结果
if($res === false) return $res;
# 判定获取一条还是多条
$lists = [];
if($all){
# 获取多条,二维数组存储
while($row = mysqli_fetch_assoc($res)){
$lists[] = $row;
}
}else{
# 获取一条,一维数组存储
$lists = mysqli_fetch_assoc($res);
}
# 释放资源,返回结果
mysqli_free_result($res);
return $lists;
}
5、普通查询
# 用户提供SQL指令,可以查询一条或者多条记录
function read($conn,$sql,&$error,$all = false){
# 执行SQL,并判定结果
$res = query($conn,$sql,$error);
if($res === false) return false;
# 解析结果集
$lists = [];
if($all){
# 多条数据:二维数组
while($row = mysqli_fetch_assoc($res)){
$lists[] = $row;
}
}else{
# 一条数据:一维数组
$lists = mysqli_fetch_assoc($res);
}
# 释放资源,返回结果
mysqli_free_result($res);
return $lists;;
}
小结
1、封装是为了代码能够更好的实现复用
- 复用性
- 灵活性
2、封装需要考虑封装事务的独立性,不要试图用一个函数去解决一个很大的问题
4、新闻列表
目标:了解显示数据的业务逻辑,以及当前新闻列表实现的具体步骤
概念
新闻列表:将新闻信息从数据库取出,然后在模板中显示
步骤
1、新增列表处理文件:index.php
2、在PHP中根据模板显示的要求,获取相应的数据
3、PHP加载显示数据的模板
4、在模板中使用PHP输出相应的数据
示例
1、创建首页(列表页)处理脚本index.php
# 显示新闻列表
2、根据模板显示要求获取数据信息:新闻id、标题、内容、作者名字、发布时间
# 加载封装的数据库操作文件
include 'sql.php';
# 完成初始化操作
$conn = connect('root','root','news',$error);
# 判定结果
if(!$conn) die($error);
# 组织数据SQL,获取数据(手动组织:需要连表)
$sql = "select n.*,a.name from news n left join author a on n.a_id = a.id";
$news = read($conn,$sql,$error,true);
3、加载模板
# 加载首页模板
include 'news_index.html'; # 注意路径
4、在模板中对应位置显示对应的数据
<?php foreach($news as $n):?>
<!-- 列表项开始 -->
<div class="news-list-item">
<!-- 作者以及发布时间 -->
<div class="author-time"> <span><?php echo $n['name'];?></span> 发表于 <span><?php echo date('Y-m-d H:i:s',$n['publish']);?></span> </div>
<!-- 新闻详情 -->
<div class="news-des">
<!-- 新闻标题 -->
<h3 class="news-title" style='float: left;'>
<i></i><a href="02-新闻详情页.html"><?php echo $n['title'];?></a>
</h3>
<!-- 编辑,删除 -->
<div class="operate">
<a href="04-新闻修改页.html">编辑</a> <a href="#" οnclick="return confirm('你确认要删除本条新闻吗?')">删除</a>
</div>
<div style='clear:both'></div>
<!-- 新闻内容 -->
<div class="news-content-des ellipsis"><?php echo $n['content'];?></div>
</div>
</div>
<!-- 列表项结束 -->
<?php endforeach;?>
小结
1、显示数据的核心逻辑是获取数据、显示数据
5、编辑新闻
目标:了解编辑的逻辑,掌握新闻编辑的实现
概念
编辑新闻:将已有的新闻取出来,然后再次进行加工操作,并提交更新到服务器
步骤
1、提供操作链接:编辑通常是针对单条记录,需要在列表页针对每一条记录制作对应的编辑链接
2、后台新增接收编辑的PHP脚本:edit.php
- 接收要编辑的新闻信息
- 从数据库取出要编辑的新闻
- 加载编辑模板(表单)
- 显示编辑取出来的新闻
3、用户编辑数据后提交到update.php
- 接收用户提交的信息
- 被编辑的内容(要入库)
- 不可编辑的内容(条件匹配)
- 数据安全性验证
- 组织更新指令更新入库(自动更新)
4、根据执行结果提示用户操作信息并进行跳转
示例
1、修改列表页,增加编辑链接:需要传入要编辑的新闻id
<!-- 编辑,删除 -->
<div class="operate">
<a href="edit.php?id=<?php echo $n['id'];?>">编辑</a> <a href="#" οnclick="return confirm('你确认要删除本条新闻吗?')">删除</a>
</div>
2、增加edit.php脚本,实现新闻的获取
# 接收要获取的新闻id
$id = $_GET['id'] ?? 0;
if(!$id) {
header("Refresh:3;url={$_SERVER['HTTP_REFERER']}");
echo '当前要编辑的新闻不存在!';
exit;
}
# 获取新闻数据
include 'sql.php';
$conn = connect('root','root','news',$error);
# 判定结果
if(!$conn) {
header("Refresh:3;url=index.php");
echo $error;
exit;
}
# 自动查询
$news = auto_read($conn,'news',$error,['id' => $id]);
if(!$news){
header("Refresh:3;url=index.php");
echo '当前要编辑的新闻不存在!';
exit;
}
3、加载模板
# 加载模板
include 'news_edit.html';
4、在模板中显示要编辑的数据:id必须传,但是需要隐藏
<form action="update.php" method="post">
<input type="hidden" name="id" value="<?php echo $news['id'];?>">
<div class="form-group">
<label for="news_title">新闻标题</label>
<input type="text" name="title" class="form-control" id='news_title' value='<?php echo $news['title'];?>'>
</div>
<div class="form-group">
<label for="news_content">新闻内容</label>
<textarea class="form-control" name="content" rows="12"><?php echo $news['content']?></textarea>
</div>
<button class="btn btn-danger btn-block">修改</button>
</form>
5、后台增加update.php 用于处理用户提交的表单
# 接收数据:数组接收可能修改的数据(下标与表字段名一致)
$id = $_POST['id'];
$data['title'] = $_POST['title'] ?? '';
$data['content']= $_POST['content'] ?? '';
# 判定
if(empty($data['title']) || empty($data['content'])){
header('Refresh:3;url=edit.php?id=' . $id);
echo '标题和内容都不能为空!';
exit;
}
# 自动更新
include 'sql.php';
$conn = connect('root','root','news',$error);
# 判定结果
if(!$conn) {
header("Refresh:3;url=index.php");
echo $error;
exit;
}
$res = auto_update($conn,$data,'news',$error,$id);
6、根据更新结果进行跳转
# 结果判定
if($res){
header('Refresh:3;url=detail.php?id='.$id);
echo '更新成功!';
exit;
}else{
# 是没有要更新的数据
header('Refresh:3;url=index.php');
echo '没有要更新的数据!';
exit;
}
小结
1、编辑操作是所有增删改查里步骤最复杂的一个
6、删除新闻
目标:了解删除的处理逻辑,实现新闻的删除
概念
删除新闻:对已有新闻从数据库指定移出
步骤
1、提供操作链接:删除通常是针对单条记录,需要在列表页针对每一条记录制作对应的删除链接(需要明确要删除的数据的参数)
2、后台新增实现删除的PHP脚本:delete.php
- 接收要删除的记录参数(通常是主键)
- 必要时进行数据安全验证
- 组织SQL指令执行删除操作
3、根据删除结果进行跳转提示
示例
1、修改列表页,增加删除链接:需要传入要删除的新闻id
<!-- 编辑,删除 -->
<div class="operate">
<a href="edit.php?id=<?php echo $n['id'];?>">编辑</a> <a href="delete.php?id=<?php echo $n['id'];?>" onclick="return confirm('你确认要删除本条新闻吗?')">删除</a>
</div>
- 一般删除会做一个前端安全限定:js的确认验证
2、后台增加一个delete.php实现数据的删除操作
$id = $_GET['id'] ?? 0;
if(!$id){
header('Refresh:3;url=index.php');
echo '当前要删除的新闻不存在!';
exit;
}
# 实现数据库操作
include 'sql.php';
$conn = connect('root','root','news',$error);
# 判定结果
if(!$conn) {
header("Refresh:3;url=index.php");
echo $error;
exit;
}
# 删除操作
$sql = "delete from news where id = {$id}";
$res = query($conn,$sql,$error);
# 判定下执行结果
if($res)
$res = mysqli_affected_rows($connn);
else{
header("Refresh:3;url=index.php");
echo $error;
exit;
}
if($res){
header("Refresh:3;url=index.php");
echo '删除成功!';
exit;
}else{
header("Refresh:3;url=index.php");
echo '删除失败!';
exit;
}
小结
1、删除操作是增删改查里本质最简单的一种业务,但是实际开发中删除操作却是非常谨慎的
- 删除不可逆
- 数据的删除不利于大数据分析
2、实际实现中,一般的业务数据可以删除,但是比较重要的数据虽然给用户的感觉是删除,但是实际上数据库里并不会删除
- 数据表增加字段记录状态
- 数据查询时根据状态来进行数据筛选
- 数据删除时只要改变状态不让普通查询可查即可
7、查看新闻
目标:了解查看数据的逻辑,实现新闻详情的查看
目标
查看新闻:用户通过点击新闻标题查看新闻详细信息
步骤
1、找到列表页中出现新闻标题的位置
2、给每一个标题增加一个访问链接:后台处理文件detail.php
3、给每个请求追加具体新闻信息id
4、后台detail.php接收要查看的新闻数据:id
5、从数据库查询新闻信息:按模板显示需求
6、加载显示新闻详情的模板
7、显示数据
示例
1、显示新闻详情
- 在新闻列表页增加标题点击链接,请求detail.php
<!-- 新闻标题 -->
<h3 class="news-title" style='float: left;'>
<i></i><a href="detail.php?id=<?php echo $n['id'];?>"><?php echo $n['title'];?></a>
</h3>
- 在后台增加detail.php获取新闻信息,加载新闻详情模板
# 接收新闻id
$id = $_GET['id'] ?? 0;
if(!$id){
header('Refresh:3;url=index.php');
echo '非法访问!';
exit;
}
# 获取新闻数据
include 'Sql.php';
$conn = connect('root','root','news',$error);
# 判定结果
if(!$conn){
header('Refresh:3;url=index.php');
echo $error;
exit;
}
# 查询数据
$sql = "select n.*,a.name from news n left join author a on n.a_id = a.id where n.id = {$id}";
$news = read($conn,$sql,$error);
if(!$news){
header('Refresh:3;url=index.php');
echo '您所访问的新闻不存在!';
exit;
}
# 加载模板
include 'news_detail.html';
- 在模板中显示新闻信息
<div class="news-list-item" style='border-bottom: none;'>
<!-- 新闻标题 -->
<h3 class="news-title"><?php echo $news['title'];?></h3>
<!-- 作者以及发布时间 -->
<div class="author-time"> <span><?php echo $news['name']?></span> 发表于 <span><?php echo date('Y-m-d H:i:s',$news['publish']);?></span> </div<!-- 新闻详情 -->
<div class="news-des">
<!-- 新闻内容 -->
<div class="news-content-des"><?php echo $news['content']?></div>
</div>
</div>
小结
1、显示详情的话通常是通过列表进入,然后给出点击链接实现
2、数据显示往往比较简单:保证数据查询是到位的
8、分页
目标:了解分页的逻辑和原理,实现新闻系统首页的分页功能
概念
分页:将数据按照一种类似于页码的逻辑呈现,用户通过不同页码看到的数据不同
- 分页里有几个核心需要关注的数据
- 总记录数:决定页码数量的有效记录数
- 每页显示量:每一个页面里要显示的记录数
- 总页数:总记录数 / 每页显示量
- 当前页码:进行数据筛选的最关键标志
- 分页的逻辑有两大类
- 服务器数据分页:服务器在获取数据时,只获取当前用户需要页面的数据
- 减少服务器压力
- 减少网络传输延迟
- JS脚本分页:服务器不管分页,一次性提交所有数据给浏览器,JS通过脚本控制每次显示的数据量
- 减少请求次数
- 减少用户分页点击时等待时间
- 服务器数据分页:服务器在获取数据时,只获取当前用户需要页面的数据
- 服务器端实现分页,通常是通过数据库的limit来实现
limit 0,3; # 显示前3条
limit 3,6; # 显示第二个3条
- 分页的效果通常是浏览器上给用户提供一排页码点击链接,用户点击哪个就访问对应页面的数据
<div class="page">
<a href="#">首页</a>
<a href="#">上一页</a>
<a href="#">1</a>
<a href="#">2</a>
<a href="#" class='current'>3</a>
<a href="#">4</a>
<a href="#">5</a>
<a href="#">下一页</a>
<a href="#">末页</a>
</div>
步骤
1、确定分页模式(通常使用数据库分页)
2、确定分页效果:参照京东分页逻辑
- 有上一页和下一页
- 如果已经是第一页:那么上一页不可用(或者没有)
- 如果已经是最后一页:那么下一页不可用(或者没有)
- 一共最多显示7个可点击数字页面
- 如果总页数小于等于7页:显示所有页码:1,2,3,4,5,6,7
- 如果总页数大于7页,显示当前页码左右连贯5页(左右各两页)
- 当前页码小于等于5:显示前7页,最后增加一个
...
表示有更多页码:1,2,3,4,5,6,7,… - 当前页码大于5页:显示前2页(1和2),然后跟
...
,然后显示当前页连贯5页:1,2,…- 如果当前页码已经属于最后3页内,显示最后5页数据:1,2,…,6,7,8,9,10
- 如果当前页码小于最后3页,那么最后增加一个
...
表示有更多页码:1,2,…,5,6,7,8,9,…
- 当前页码小于等于5:显示前7页,最后增加一个
3、确定分页链接方式
- 前端设计者已经设计好,针对设计好的进行动态化即可
- 前端没有提供,一般提供一个ul列表+a标签实现
4、在后台实现分页点击的字符串逻辑
5、在前端页面分页处显示后台设计的分页逻辑
示例
1、使用京东分页逻辑实现分页,使用前端设计好的a标签形式设计分页字符串
# 在所有数据分页都是请求index.php,所以需要在index.php开始处增加页码获取信息(包含每页访问的数量定义)
$page = $_GET['page'] ?? 1;
$pagecount = 4;
# 获取满足条件的数据的总记录数(在获取列表之前:因为不需要获取全部数据了)
$count_sql = 'select count(*) as total from news';
$res = read($conn,$count_sql,$error); # 执行
$count = $res['total'] ?? 0; # 取出记录(如果没有那就是0)
$pages = ceil($count / $pagecount); # 总页数
# 计算页码数据:使用limit限制
$offset = ($page - 1) * $pagecount;
$limit = " limit $offset,$pagecount";
# 拼凑原来获取数据的SQL,使得数据分页效果实现
# 连接查询之后,系统会默认按照连接条件进行升序排序,需要调整为新闻id升序排序
$sql = "select n.*,a.name from news n left join author a on n.a_id = a.id order by n.id " . $limit;
# 产生分页链接信息
$pageinfo = '';
# 首页
$pageinfo .= "<a href='index.php?page=1'>首页</a>";
# 判定是否需要上一页
if($page != 1) {
$prev = $page - 1;
$pageinfo .= "<a href='index.php?page={$prev}'>上一页</a>";
}
# 拼凑数字逻辑部分:以页码总数先划分
if($pages <= 7){
# 显示所有页码,也不需要...
for($i = 1;$i <= $pages;$i++){
# 判定当前页码是否被选中:增加样式
if($page == $i) $pageinfo .= "<a class='current' href='index.php?page={$i}'>{$i}</a>";
else $pageinfo .= "<a href='index.php?page={$i}'>{$i}</a>";
}
}else{
# 当前页码在前5页:显示前7页,外加...
if($page <= 5){
for($i = 1;$i <= 7;$i++){
# 判定当前页是否被选中:选中需要增加css样式
if($page == $i) $pageinfo .= "<a class='current' href='index.php?page={$i}'>{$i}</a>";
else $pageinfo .= "<a href='index.php?page={$i}'>{$i}</a>";
}
# 追加...
$pageinfo .= "<a href ='javascript:return false;' οnclick='return false;'>...</a>";
}else{
# 当前页码大于5:显示前2页和...
$pageinfo .= "<a href='index.php?page=1'>1</a>";
$pageinfo .= "<a href='index.php?page=2'>2</a>";
$pageinfo .= "<a href ='javascript:return false;' οnclick='return false;'>...</a>";
# 判定当前页码是否已经到达最后三页:不需要后序...
if($page > $pages - 3){
# 显示最后5页
for($i = $pages - 4;$i <= $pages;$i++){
# 判定当前页是否被选中:选中需要增加css样式
if($page == $i) $pageinfo .= "<a class='current' href='index.php?page={$i}'>{$i}</a>";
else $pageinfo .= "<a href='index.php?page={$i}'>{$i}</a>";
}
}else{
# 显示中间5页,并追加...
for($i = $page - 2;$i <= $page + 2;$i++){
# 判定当前页是否被选中:选中需要增加css样式
if($page == $i) $pageinfo .= "<a class='current' href='index.php?page={$i}'>{$i}</a>";
else $pageinfo .= "<a href='index.php?page={$i}'>{$i}</a>";
}
# 追加...
$pageinfo .= "<a href ='javascript:return false;' οnclick='return false;'>...</a>";
}
}
}
# 判定是否需要增加下一页
if($page != $pages){
$next = $page + 1;
$pageinfo .= "<a href='index.php?page={$next}'>下一页</a>";
}
# 末页
$pageinfo .= "<a href='index.php?page={$pages}'>末页</a>";
2、在模板上显示计算好的分页链接,代替原来的a标签分页
<!-- 分页 -->
<div class="page">
<?php echo $pageinfo;?>
</div>
小结
1、分页后台数据筛选分为两个核心部分
- 数据分页:利用limit实现数据的分页获取
- 逻辑分页:利用逻辑部分实现分页链接,让用户可以访问不同分页数据
9、项目完善和总结
1、项目完善:各类链接地址修改
2、项目总结
- 前端提供好静态页面
- 根据静态页设计好数据库
- PHP进行逻辑处理
- 数据加工
- 数据库操作(增删改查)
- 数据显示