案例:音乐列表

一、思路分析

  • 绝大多数情况下,编写的应用功能都是围绕着某种类型的数据做增改删改查,对于增删改查的数据一般是结构相同的多条数据(可以认为是一个数组,数组中的元素都具有相同的属性结构),并且可以持久化(长久保存)
  • 由于存放的数据有着复杂的结构,所以采用json存放数据

二、功能实现

  • 服务端开发领域所谓的渲染指的是经过程序执行得到最终的HTML字符串这个过程

  • 数据存储(json格式)

[
    {"id":"100","title":"起风了","artist":"辣椒","images":["uploads/1.jpg"],"source":"uploads/1.MP3"}, 
    {"id":"101","title":"青鸟","artist":"火影","images":["uploads/1.jpg"],"source":"uploads/1.MP3"}, 
    {"id":"102","title":"千年之恋","artist":"FIR","images":["uploads/1.jpg"],"source":"uploads/1.MP3"}, 
    {"id":"103","title":"七月七日晴","artist":"慧欣","images":["uploads/1.jpg"],"source":"uploads/1.MP3"},  
    {"id":"104","title":"风云决","artist":"任贤齐","images":["uploads/1.jpg"],"source":"uploads/1.MP3"} 
 ]
  • 列表数据展示(展示类)

   ①文件读取

    ②json反序列化:json_decode,如果希望以关联数组的方式而非对象的方式操作数据,可以将json_decode的第二个参数设为true

  ③数组遍历foreach

  ④PHP与HTML混编

<?php
    //获取文件中记录的数据,展示到表格中(动态生成表格的HTML标签)
    $json=file_get_contents('data.json');
    //$content=>json格式的字符串,把json格式的字符串转换为对象的过程叫做反序列化
    //json_decode默认反序列化时把json中的对象转换为PHP中stdClss类型的对象
    $data=json_decode($json,true);
    //print_r($data);
    /*这里是设置了json_decode第二个参数为true的时候的输出是一个数组,默认输出的是对象
    Array (
        [0] => Array ( [id] => 100 [title] => 起风了 [artist] => 辣椒 [images] => 1.jpg [source] => 1.MP3 )
        [1] => Array ( [id] => 101 [title] => 青鸟 [artist] => 火影 [images] => 2.jpg [source] => 2.MP3 ) 
        [2] => Array ( [id] => 102 [title] => 千年之恋 [artist] => FIR [images] => 3.jpg [source] => 3.MP3 )
        [3] => Array ( [id] => 103 [title] => 七月七日晴 [artist] => 慧欣 [images] => 4.jpg [source] => 4.MP3 )
        [4] => Array ( [id] => 104 [title] => 风云决 [artist] => 任贤齐 [images] => 5.jpg [source] => 5.MP3 )
    )
    */
    if(!$data){
        //json格式不正确
        exit('数据文件异常');
    }
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>音乐列表</title>
    <link rel="stylesheet" href="bootstrap.css">
</head>
<body>
   <div class="container mt-5">
       <h1 class="display-3">音乐列表</h1>
       <hr>
       <a href="add.php" class="btn btn-primary">添加</a>
       <table class="table table-bordered table-striped table-hover">
          <thead class="thead-dark">
              <tr>
                  <th class="text-center">标题</th>
                  <th class="text-center">歌手</th>
                  <th class="text-center">海报</th>
                  <th class="text-center">音乐</th>
                  <th class="text-center">操作</th>
              </tr>
          </thead>
          <tbody class="text-center">
                <?php foreach($data as $item): ?>
                <!-- $item 返回的是数组:
                Array ( [id] => 100 [title] => 起风了 [artist] => 辣椒 [images] => 1.jpg [source] => 1.MP3 ) 
                Array ( [id] => 101 [title] => 青鸟 [artist] => 火影 [images] => 2.jpg [source] => 2.MP3 ) 
                Array ( [id] => 102 [title] => 千年之恋 [artist] => FIR [images] => 3.jpg [source] => 3.MP3 ) 
                Array ( [id] => 103 [title] => 七月七日晴 [artist] => 慧欣 [images] => 4.jpg [source] => 4.MP3 ) 
                Array ( [id] => 104 [title] => 风云决 [artist] => 任贤齐 [images] => 5.jpg [source] => 5.MP3 )
                -->
                <tr>
                    <!-- => 是数组成员访问符号,-> 是对象成员访问符号 -->
                    <td class="align-middle"><?php echo $item['title']; ?></td>
                    <td class="align-middle"><?php echo $item['artist']; ?></td>
                    <!-- 可能会需要上传多个图片(json数据里应该对应的使用数组存储图片),此时应该遍历images, -->
                    <td class="align-middle">
                        <?php foreach($item['images'] as $src):?>
                            <img src="<?php echo $src;?>" alt="">
                        <?php endforeach ?>
                    </td>
                    <td class="align-middle"><audio src="<?php echo $item['source']; ?>" controls></audio></td>
                    <td class="align-middle">
                        <!-- 删除数据使用超链接的方法,利用问号后面的参数传值 -->
                        <a class="btn brn-danger btn_sm" href="delete.php?id=<?php echo $item['id'];?>">删除</a>
                    </td>
                </tr>  
              <?php endforeach ?>
          </tbody>
       </table>
   </div>
</body>
</html>

  • 新增数据(表单类)

  ①表单使用

  ②服务端表单校验并提示错误消息:empty判断一个成员是否没定义或者值为false(可以隐式转换为false)

  ③输出文件:文件数量,文件种类,如果要考虑文件重名的情况,可以给上传的文件重新命名

  ④单文件域多文件上传:name一定可以[ ]结尾,服务端会接收到一个数据

  ⑤json序列化

  ⑥文件写入

<?php
    //将用户提交过来的数据保存到data.json数据文件中(三部曲:接收并校验--->持久化--->响应)
    function add(){
        //定义一个空数组,用来装数据
        $data=array();
        //1.文本框校验
        if(empty($_POST['title'])){
            $GLOBALS['error_message']='请输入标题';
            return;
        }
        if(empty($_POST['artist'])){
            $GLOBALS['error_message']='请输入歌手';
            return;
        }
        $data['id']=uniqid();
        $data['title']=$_POST['title'];
        $data['artist']=$_POST['artist'];
        //2.上传文件校验
        //2.1图片上传文件校验(处理多个图片上传)
        if(empty($_FILES['images'])){
            //客户端提交的表单中没有images文件域(用户误删)
            $GLOBALS['error_message']='请正常使用表单';
            return;
        }
        $images=$_FILES['images'];
        $data['images']=array();
        //判断用户是否选择了文件
        for($i=0;$i<count($images['name']);$i++){
            //$images['error']=>[0,0,0...]
            if($images['error'][$i]!== UPLOAD_ERR_OK){
                $GLOBALS['error_message']='上传海报文件失败1';
                return;
            }
            //校验文图片的大小
            if($images['size'][$i]>20*1024*1024){
                $GLOBALS['error_message']='图片文件过大';
                return;
            }
            //校验类型
            //$images['type']=>['image/png','image/jpeg',....]还可以使用in_array的方法
            if(strpos($images['type'][$i],'image/')!==0){
                $GLOBALS['error_message']='这是不支持的音乐格式';
                return;
            }
            //图片文件已经上传成功,但是还在临时目录里
            //一般会将上传的文件重命名
            $dest='uploads/' . uniqid() . $images['name'][$i];
            if(!move_uploaded_file($images['tmp_name'][$i],$dest)){
                $GLOBALS['error_message']='上传海报文件失败2';
                return;
            }
            $data['images'][]=$dest;
        }
        //2.2音乐文件校验
        if(empty($_FILES['source'])){
            //客户端提交的表单中没有source文件域
            $GLOBALS['error_message']='请正常使用表单';
            return;
        }
        $source=$_FILES['source'];
        //判断用户是否选择了文件
        if($source['error']!== UPLOAD_ERR_OK){
            $GLOBALS['error_message']='上传音乐文件失败1';
            return;
        }
        //校验文件的大小
        if($source['size']>10*1024*1024){
            $GLOBALS['error_message']='音乐文件过大';
            return;
        }
        if($source['size']<1*1024*1024){
            $GLOBALS['error_message']='音乐文件过小';
            return;
        }
        //校验类型
        $source_allowed_types=array('audio/mp3','audio/wma');
        if(!in_array($source['type'],$source_allowed_types)){
            $GLOBALS['error_message']='这是不支持的音乐格式';
            return;
        }
        //移动:音乐文件已经上传成功,但是还在临时目录里
        //一般会将上传的文件重命名
        $target='uploads/' . uniqid(). '-' .$source['name'];
        if(!move_uploaded_file($source['tmp_name'],$target)){
            $GLOBALS['error_message']='上传音乐失败2';
            return;
        }
        //3.将数据装起来:此时上传和移动都已经完成
        $data['source']=$target;
        //4.将数据加入到原有的数据中
        $json=file_get_contents('data.json');
        $old=json_decode($json,true);
        array_push($old,$data);
        $new_json=json_encode($old);
        file_put_contents('data.json',$new_json);
        // 5.跳转回列表页
       header('Location: list.php');
    }
    if($_SERVER['REQUEST_METHOD']==='POST'){
        add();
    }
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>添加音乐</title>
    <link rel="stylesheet" href="bootstrap.css">
</head>
<body>
    <div class="container py-5">
        <h1 class="display-4">添加新音乐</h1>
        <hr>
        <?php if(isset($error_message)):?>
            <div class="alert alert-danger" role="alert">
                <?php echo $error_message; ?>
            </div>
        <?php endif ?>
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data" autocomplete="off">
            <div class="form-group">
                <label for="title">标题</label>
                <input type="text" name="title" id="title" class="form-control">
            </div>
            <div class="form-group">
                <label for="artist">歌手</label>
                <input type="text" name="artist" id="artist" class="form-control">
            </div>
            <div class="form-group">
                <label for="images">海报</label>
                <!-- multiple可以让一个文件域多选 -->
                <!-- 保存多个文件,结合前面的CheckBox问题,可以在name属性值[] -->
                <input type="file" name="images[]" id="images" class="form-control" multiple accept="image/*">
            </div>
            <div class="form-group">
                <label for="source">音乐</label>
                <!-- accept可以设置  MIME Type/文件扩展名 -->
                <input type="file" name="source" id="source" class="form-control" accept="audio/*">
            </div>
            <button class="btn btn-block btn-primary" type="submit">保存</button>
        </form>
    </div>
</body>
</html>

  • 删除数据

  ①通过客户端在URL地址中的问号参数的不同来辨别要删除的数据
  ②接收URL中的不同ID
  ③找到要删除的数据
  ④从原数据中删除(执行到这,已经找到那条数据====$item=>要删除的数据)
  ⑤保存删除指定数据过后的内容
  ⑥跳转回到列表页
<?php
    //通过客户端在URL地址中的问号参数的不同来辨别要删除的数据
    //1.接收URL中的不同ID
    if(empty($_GET['id'])){
        //传入的参数为空
        exit('<h1>必须指定参数</h1>');
    }
    $id=$_GET['id'];
    //2.找到要删除的数据
    $data=json_decode(file_get_contents('data.json'),true);
    foreach($data as $item){
        //如果不是要找的数据,直接找下一条
        if($item['id']!==$id) continue;
        //3.从原数据中删除(执行到这,已经找到那条数据====$item=>要删除的数据)
        $index=array_search($item,$data);
        array_splice($data,$index,1);
        //4.保存删除指定数据过后的内容
        $json=json_encode($data);
        file_put_contents('data.json',$json);
        //5.跳转回到列表页
        header('Location: list.php');
    }
?>
  • 总的文件列表情况

三、效果展示

原文地址:https://www.cnblogs.com/EricZLin/p/9193009.html