一、思路分析
- 绝大多数情况下,编写的应用功能都是围绕着某种类型的数据做增改删改查,对于增删改查的数据一般是结构相同的多条数据(可以认为是一个数组,数组中的元素都具有相同的属性结构),并且可以持久化(长久保存)
- 由于存放的数据有着复杂的结构,所以采用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'); } ?>
-
总的文件列表情况