10新闻管理系统

一、表单传值

学习目标:了解表单传值的作用和意义,掌握基础的表单传值的实现

  • 表单传值概念
  • 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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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,…

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进行逻辑处理
    • 数据加工
    • 数据库操作(增删改查)
    • 数据显示

猜你喜欢

转载自blog.csdn.net/weixin_45717158/article/details/112990003