Correcting teacher:PHPz
Correction status:qualified
Teacher's comments:
<!-- 作业内容:1请建立数据表并填充多条数据,完成原生分页。2.文件上传后端要做哪些拦截?3.事件委托实战:完成链式数据库查询构造器。 -->
<?php
// 连接数据库
require 'connect.php';
// 1. 当前的页数/页码
$page = $_GET['p'] ?? 1;
// 2. 每页显示的记录数量
$num = 8;
// 3. 总页数
$sql = "SELECT CEIL(COUNT(`pid`)/{$num}) AS `total` FROM `workplan0921`";
$pages = $pdo->query($sql)->fetch()['total'];
// 4. 偏移量
$offset = $num * ($page - 1);
// 5. 分页数据
$sql = "SELECT * FROM `workplan0921` LIMIT {$num} OFFSET {$offset}";
$plans = $pdo->query($sql)->fetchAll();
// print_r($plans);
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>分页显示工作计划</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
color: #555;
}
body {
display: flex;
flex-direction: column;
align-items: center;
}
/*表格样式*/
table {
width: 80%;
border: 1px solid;
border-collapse: collapse;
text-align: center;
}
table caption {
font-size: 1.2rem;
margin: 10px;
}
table td,
table th {
border: 1px solid;
padding: 5px;
}
table tr:hover {
background-color: #eee;
}
table thead tr:only-of-type {
background-color: lightblue;
}
table button {
width: 56px;
height: 26px;
}
table button:last-of-type {
color: red;
}
table button {
/* 光标呈现为指示链接的指针(一只手) */
cursor: pointer;
margin: 0 3px;
}
table button:first-of-type:hover {
background-color: red;
}
table button:last-of-type:hover {
background-color: yellow;
}
/*分页条样式*/
body > p {
display: flex;
}
p > a {
text-decoration: none;
color: #555;
border: 1px solid;
padding: 5px 10px;
margin: 10px 2px;
}
.active {
background-color: red;
color: white;
border: 1px solid red;
}
.show1, .show2 {
display: none;
}
</style>
</head>
<body>
<table>
<caption>重点工作计划进度明细</caption>
<thead>
<tr>
<th>STT</th>
<th>项目</th>
<th>计划</th>
<th>主责人</th>
<th>完成标准</th>
<th>开始时间</th>
<th>结束时间</th>
<th>完成时间</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<?php foreach ($plans as $plan) : ?>
<tr>
<td><?php echo $plan['stt'];?></td>
<td><?php echo $plan['project'];?></td>
<td><?php echo $plan['plan'];?></td>
<td><?php echo $plan['nguoiphtrach'];?></td>
<td><?php echo date('Y-m-d', $plan['starttime']) ?></td>
<td><?php echo date('Y-m-d', $plan['endtime']) ?></td>
<td><?php echo date('Y-m-d', $plan['timehoanthanh']) ?></td>
<td><?php echo $plan['ghichu'];?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<!--分页-->
<p>
<!--设置省略-->
<?php
// 1. 分页条显示7个页码
$showPages = 7;
// 2. 分页条的起始页码
$startPage = 1;
// 3. 分页条的终止页码
$endPage = $pages; // 当前总页数:
// 4. 分页条的偏移量: (当前分页条显示的页码数 - 1) / 2
$offsetPage = ($showPages -1) / 2; // 3
// 只有当前分页条数量 < 总页数, 才有必要显示出省略标记
if ($showPages < $pages) {
// 如果当前页 > 偏移量 + 1 , 应该显示...
if ($page > $offsetPage + 1) {
$startOmit = '...';
}
// 将当前分页条页码重置
if ($page > $offsetPage) {
$startPage = $page - $offsetPage;
$endPage = $page + $offsetPage;
if ($endPage > $pages) {$endPage = $pages;}
} else {
$startPage = 1;
$endPage = $showPages;
}
// 如果当前页 + 偏移量 > 总页数
if ($page + $offsetPage > $pages) {
// 原理, 就是向当前页前面进行借位
// 此时, 新的起点 = 当前位置 - (当前页 + 偏移量 - 原始位置)
$startPage = $startPage - ($page + $offsetPage - $endPage);
}
if ($showPages < $pages && $page + $offsetPage < $pages) $endOmit = '...';
}
?>
<?php
// 设置当在第一页和最后一页时不显示首页、上一页 或 尾页 下一页
$show1 = ($page == 1) ? 'show1' :null;
$show2 = ($page == $pages) ? 'show2' :null;
?>
<!--首页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=1' ?>" class="<?php echo $show1; ?>">首页</a>
<!--上一页-->
<?php
$prev = $page - 1;
// 如果已经第1页,则定在第1页
if ($page == 1) $prev = 1;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p =' .$prev ?>" class="<?php echo $show1; ?>">上一页</a>
<!--省略-->
<?php if (isset($startOmit)) : ?> <a href="#"><?php echo $startOmit ?></a> <?php endif ?>
<?php for ($i = $startPage; $i <= $endPage; $i++) : ?>
<?php
$jump = sprintf('%s?p=%s', $_SERVER['PHP_SELF'], $i);
$active = ($i == $page) ? 'active' :null;
?>
<a href="<?php echo $jump ?>" class="<?php echo $active ?>"><?php echo $i ?></a>
<?php endfor; ?>
<!--省略-->
<?php if (isset($endOmit)) : ?> <a href="#"><?php echo $endOmit ?></a> <?php endif ?>
<!--下一页-->
<?php
$next = $page + 1;
// 如果已经最后一页,则定在最后一页
if ($page == $pages) $next = $pages;
?>
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' .$next ?>" class="<?php echo $show2; ?>">下一页</a>
<!--尾页-->
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' .$pages ?>" class="<?php echo $show2; ?>">尾页</a>
</p>
<!--跳转指定页-->
<form name="form" method="get" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<input name="p" type="number" size="3" min="1" max="<?php echo $pages; ?>">
<input type="submit" value="跳转">
<a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' .$_GET['p'] ?>"></a>
</form>
<script>
function delet(id){
if(confirm("是否删除?")){
return "location.href='handle.php?action=delet&id=<?php echo $plans['id'] ?>";
}
return false;
}
</script>
</body>
</html>
1、判断文件是否上传成功
switch ($error):
case 0:
echo '<p style="color:green">文件上传成功</p> ';
break;
case 1:
echo '<p style="color:red">文件超过`php.ini`中`upload_max_filesize`值</p>';
break;
case 2:
echo '<p style="color:red">文件大小超过表单中`MAX_FILE_SIZE`指定的值</p>';
break;
case 3:
echo '<p style="color:red">文件只有部分被上传</p>';
break;
case 4:
echo '<p style="color:red">没有文件被上传</p>';
break;
case 6:
echo '<p style="color:red">找不到临时文件夹</p>';
break;
case 6:
echo '<p style="color:red">文件写入失败</p>';
break;
default:
echo '<p style="color:red">系统错误</p>';
break;
endswitch;
2、检查文件格式
$exts = ['png', 'jpg', 'jpeg', 'wbmp', 'gif'];
if (!in_array($ext, $exts)) {
echo '非法的文件类型';
}
3、检查大小
is_uploaded_file()
| 用来检测文件是否是通过 http post 方法上传的,而不是系统上的一个文件。作用是防止潜在攻击者通过问题脚本访问并非用于交互的文件4、处理文件名问题
if ($error == 0) {
//移动暂存区的图片到服务器指定的文件目录
$des = 'storage/';
if (!file_exists($des)) {
mkdir($des, 0777, true);
}
// 为了确保同一秒钟两个用户上传的图片名称相同情况下,文件都能上传成功
$arr = explode('.', $originalFilename);
$ext = end($arr); //后缀
$prefix = array_shift($arr);
$newName = date('YmdHms', time()) . md5($prefix) . time() . '.' . $ext;
move_uploaded_file($tmp_name, $des . $newName);
}
<?php
/**
* 事件委托 请求委托 访问类中不存在的成远方法,会被魔术方法拦截,将请求重定向给或者委托给别的对象成员方法类处理。
* 委托是指一个对象转发或者委托一个请求给另一个对象,被委托的一方替原先对象处理请求。
* 委托比继承更加灵活 父类与子类的关系是固定的,只能单继承,但是请求可以委托给多个对象
*/
// 被委托的类 数据库查询构造器
class Query
{
//创建pdo对象的唯一实例
private static $db;
protected $table;
protected $select;
protected $limit;
// private私有的 阻止此类在外部进行实例化
private function __construct(){
}
static function connect($dsn, $user, $pwd){
if (is_null(static::$db)) {
static::$db = new pdo($dsn, $user, $pwd);
}
// return static::$db;
// 返回query实例
return new static;
}
public function table($table){
$this->table = $table;
return $this; //返回本对象 为了实现链式调用
}
public function where($field, $chart = '=', $value){
$this->where = $field .' ' .$chart .' ' .$value;
return $this;
}
public function select(...$select){
foreach ($select as $val){
$field .= $val .', ';
}
$this->select = rtrim($field,',');
return $this;
}
public function limit($limit){
$this->limit = $limit;
return $this;
}
public function getSql(){
echo sprintf('SELECT %s FROM %s LIMIT %d ', $this->select == '' ? '*' : $this->select, $this->table, $this->limit);
}
public function first(){
return static::$db->query($this->getSql())->fetch(PDO::FETCH_ASSOC);
}
}
// 委托方
class DB
{
static function __callStatic($name, $arguments){
$dsn = 'mysql:host=localhost;dbname=yllblroot;charset=utf8;port=3306';
$user = 'root';
$pwd = 'root';
// 获取到被委托的类Query实例
$q = Query::connect($dsn, $user, $pwd);
return call_user_func([$q, $name], ...$arguments);
}
}
// 客户端代码
$res = DB::table('workplan0921')->limit(20)->first();
var_dump($res);