• 【千纸诗书】—— PHP/MySQL二手书网站后台开发之知识点记录


    前言:使用PHP和MySQL开发后台管理系统的过程中,发现有一些通用的【套路小Tip】,这里集中记录一下。结合工作中ing的后台业务,我逐渐体会到:除了技术知识外、能使用户体验好的“使用流程设计”积累也十分重要╭( ・ㅂ・)و ̑̑    

    项目github地址:https://github.com/66Web/php_book_store,欢迎Star。  


     一、知识点记录

    1、数据库的表名和列名

    • 绝对不要和数据库的关键字相同  order  order by   
    • 订单表-indent   分类表-class(数据库中没有class关键词)
    • 数据库中   凡是数字  INT FLOAT   一定要UNSIGNED   有负数的不能加UNSIGNED
    • 数据库插入时间   使用时间戳   UNIX_TIMESTAMP

    2、后台用户模块

    • 修改页面change.php:必须要id  隐藏域,带过去id
      <input  type="hidden"  name="id"  value='<?php echo $row['id'] ?>' />  
    • 因为update.php中的update语句中where id= ?才可以形成完整语句
    • 图书模块change.php  id  img 两个隐藏域 方便update.php中图片缩放处理和删除原图

    3、_top 是指向:上一级目录

    <p><a href="logout.php" target='_top'>|-退出系统</a></p>

    4、disabled 禁用username提交,不能修改

    <p>管理员名:</p>
    <p><input type="text" name='username' value='<?php echo $row['username']?>' disabled></p>
    

    5、后台修改、删除  

    • 能通过带参数id等实现,就不要查数据库,不灵活,能不查就不查。 

    6、Select选项‘修改’时显示原选项

    <p>类别:</p>
    <p>
        <select name="class_id">
        <?php
            $sqlClass="select * from class";      //创建sql语句
            $rstClass=mysql_query($sqlClass);     //发送sql语句
            while($rowClass=mysql_fetch_assoc($rstClass)){      //读取并判断mysql服务器返回结果  
                if($rowClass['id'] == $rowBook['class_id']){    //rowClass的id 与传过来的rowCook的class_id相同时,选中 加selected
                    echo "<option value='{$rowClass['id']}' selected>{$rowClass['name']}</option>";
                }else{
                    echo "<option value='{$rowClass['id']}'>{$rowClass['name']}</option>";
                }
            }
         ?>
        </select>
    </p>  

    7、后台书的模块,delete.php

    $file="../../public/uploads/{$img}";  //定义图片文件路径
    $file2="../../public/uploads/thumb_{$img}" //定义缩略图文件路径
    
    //删除图片 删除文件用unlink()
    unlink($file);
    unlink($file2);

    8、传文件函数

    • move_uploaded_file($src,$dst) 上传成功返回true 否则false
    1. 第一个参数:$src 上传文件的临时文件名
    2. 第二个参数:$dst 上传后保存的新的路径和名称
      $ext = array_pop(explode('.',$name));
      $dst = '../../public/uploads/'.time().mt_rand().'.'.$ext;//指定地址,并随机生成新文件名
      
      // array_pop() 函数删除数组中的最后一个元素 
      // explode('.',$name) 字符串分割函数获得文件扩展名.jpg等
      
      $src = $_FILES['img']['tmp_name']; //文件上传时在临时目录中被保存成一个临时文件的文件名
      $name = $_FILES['img']['name']; //上传文件的文件名
    • 为了让前台效率不下降,进行图片缩放
    1. 等比例计算真实目标资源的宽和高 (算法难度)
      //判断 原图x/目标x   >  原图y/目标y   以大的比例结果为准
      
      1000/500    500/500
      2            1
    2. 等比例计算真实目标资源的宽和高 如果结果为小数,缩放能小不能大,用floor
      $img = basename($dst);   //获得目录下的文件名a.jpg

    9、PHP中exit; 可以阻止脚本,不用通篇注释。

    10、图书模块update.php

    $imgerror=$_FILES['img']['error'];    //文件上传错误信息
    
    //图片上传--先上传新图,后删除原图,上传失败不删原图
    if($imgerror === 0){

    11、多表查询

    • 三表查询    后台评论模块index.php
      $sql="select comment.*,user.username,book.name 
            from comment,user,book 
            where comment.user_id=user.id and comment.book_id=book.id";
      $rst=mysql_query($sql);
    • 两表查询    后台书模块index.php
      $sql="select book.*,class.name cname from book,class where book.class_id=class.id";
      $rst=mysql_query($sql);

    12、后台评论模块index.php

    • 双引号不能解析函数,要拿出来date(),拼接
      echo "<td>".date('Y-m-d',$row['time'])."</td>";

    13、在页面里面流通的get  post中的数据都变成字符串了

    • 不存在数字类型,所以不能用=== ,要用==
      if($row['id']==1){
          //编号为1 的删除按钮的a链接,禁用--<a href='javascript:'></a>,改背景色为灰色
          echo "<td><a href='javascript:' style='background:#888'>删除</a></td>"; 
      }else{
          echo "<td><a href='delete.php?id={$row["id"]}'>删除</a></td>";
      }  

    14、后台广告模块

    • 一般广告的位置position 按从上往下,然后从左往右 0~8
    • 为了不暴露admin,后台广告(图书等)图片上传路径 放在前后台公共 public的文件夹 

    15、订单模块

    • 订单模块是电商网站后台错误率最高的地方,一定要检查无误。
    • 同一时间下的订单,订单号和时间一致,分组聚合,合并查看
    1. 按订单号分组聚合group  by  indent.code
    • 两表查询:
      $sql="select indent.price,indent.num,book.name,book.img 
               from indent,book 
               where  indent.book_id=book.id and indent.code='{$code}'";
      $rst=mysql_query($sql);
      

      订单编号code是varchar类型,要加单引号:失误率极高!

      indent.code='{$code}'  
    • 报错,排错方法
    1. 打印出$sql语句
    2. 把打印出的sql语句在mysql中执行,报出具体错误
      echo $sql;
      exit;
      
    • 加载出缩略图 thumb_{}

      echo "<td><img src='../../public/uploads/thumb_{$row['img']}' width='50px'></td>";
    • 输出合计

      echo "<td>".$row['price']*$row['num']."</td>";

    16、后台权限把控:后台每一个页面都要写(或模块化引入)

    • 否则,毫无安全可言!
      <?php
          session_start();
      
          if(!$_SESSION['userid']){
             echo "<script>location='login.php'</script>";
             exit;     //防止程序在跳转之前,突然的,执行下去下面的代码了
          }
      ?>

    17、session数组:将数据存放在服务器中

    • 开启session
      session_start();
    • 设置session
      $_SESSION['username']='user1';
      $_SESSION['user_id']='15';
    • 删除session
    1. 开启session
      session_start();
    2. 清空session数组
      $_SESSION=array();
    3. 删除客户端的cookie文件
      setcookie('PHPSESSID','',time()-1,'/');
    4. 删除服务器上PHPSESSID所对应的session文件
      session_destroy();

    18、退出后台登录

    <?php
       session_start();
    
       $_SESSION = array();     //清空session数组
       session_destroy();       //删除服务器上PHPSESSID所对应的session文件
       setcookie('PHPSESSID','',time()-3600,'/');       //删除客户端的cookie文件
    
       echo '<script>location="login.php"</script>';
    ?> 

    19、前台广告  动态放置

    • index.php:从广告表中查到所有数据,放入一个二维数组中;为了与位置一一对应,将位置设置为数组下标
      <?php
         include '../public/common/conn.php';
      
         $sqlAdvert = "select * from advert";
         $rstAdvert = mysql_query($sqlAdvert);
         while($rowAdvert=mysql_fetch_assoc($rstAdvert){
               $rowAds[$rowAdvert['pos']]=$rowAdvert;
         }
      ?>
          <div class="ads">
                <img src="../public/upadverts/<?php echo $rowAds[0]['img']?>" alt="">
          </div>

    20、网站下不要用绝对路径,这样文件名改动会出问题

    • header.php:explode('/',$path);  //截取字符串函数
      <?php
          $path = $_SERVER['PHP_SELF'];
          $arr = explode('/',$path);
          $root = '/'.$arr[1];   //获取根目录
      ?>
      
      <a href="">
          <img src="<?php echo $root?>/home/public/img/logo.png" alt="">
      </a>

    21、首页 重复加载的相似度很高的【楼层、数据块】都要通过  php循环加载

    1. 前台页面中写sql语句一般都带一个表名,因为一个页面要查很多不同的表
    2. 在select查找时,order by rand() limit 4 随机取4个
      <?php
         $sqlClass = "select * from class order by id limit 2";
         $rstClass = mysql_query($sqlClass);
         $f = 1;
         while($rowClass=mysql_fetch_assoc($rstClass)){
      ?>
      <!--楼层开始-->
         …… …… ……
         <?php
             $sqlBook = "select book.* from book,class where book.class_id = class.id and class.id = 
                             {$rowClass['id']} and book.shelf=1 order by book.id limit 4";
             $rstBook = mysql_query($sqlBook);
             while($rowBook = mysql_fetch_assoc($rstBook)){
         ?>
         <!--楼层数据块开始-->
               …… …… ……
         <!--楼层数据块结束-->
      <?php
          }
         }
      ?>
      <!--楼层结束-->  

    22、前台页面中 动态循环添加数据

    • 第一步:先查数据表
      $id=$_GET['class_id'];
      $sqlClass="select * from class where id = {$id} ";
      $rstClass=mysql_query($sqlClass);
    • 第二步:如果抓取一行->数组[下标]
      $rowClass=mysql_fetch_assoc($rstClass);
    1. 如果抓取多行->while循环
      while($rowClass=mysql_fetch_assoc($rstClass)){
         …… ……
      }
    2. 需要数据处:
      <?php echo $rowClass['name']?>

    23、打印  查看:查到的数据结果

    <?php
        …… ……
        while($rowClass=mysql_fetch_assoc($rstClass)){
             echo '<pre>';
             print_r($rowClass);
             echo '</pre>';
        }
    ?>

    24、前台不同页面之间 跳转 通过a链接传递参数,查表,得到想要的结果

    • book.php 中  分类>>类别名称  需要传一个class_id
      <span><a href='class.php?class_id=<?php echo $class_id?>'>分类</a> » <?php echo $rowClass['name']?></span>
    • 分类页面 图书分页显示部分   第一页/上一页/下一页/尾页   传两个值 :pageclass_id
      if($page>=1 && $totalpage>1){
          echo "<a href=?page=1&class_id={$rowClass['id']}>第一页  </a>";
      }

    25、header.php 中控制登录、注册、切换用户名

    • 用session判断,前面需要开session_start();  只能放在第一行,前面不允许有任何输出
    1. 但是,header.php是被包含的页面,其它页面前面会有输出
    2. 所以,heder.php里不能加session_start();   要在加的页面里加
      <?php
         if(!$_SESSION['home_username']){
            echo "<a href='{$root}/home/login.php'>登录</a>";
         }else{
            echo "  <a href='{$root}/home/person/index.php'>欢迎
                    {$_SESSION['home_username']}登录</a>  <a href='{$root}/home/logout.php'>退出</a>";
         }
      ?>
    3. 重新打开浏览器,会有undefined:用@解决
      @$_SESSION['home_username'];   

    26、个人中心 左右结构页面

    • 第一种:复杂式
    1. 左侧 不同的栏目给不同的参数
    2. 右侧 给一个switch,根据左侧给的不同参数,发生不同的变化
    3. 优点:只需写一个页面
    4. 缺点:共用的php里易写乱,易出错
    • 第二种:简单式(
    1. 复制页面,写好一个,复制给不同的页面,然后用链接跳转。
    • 易错:echo " ";  里原本html里面的双引号,都要改为单引号

    27、通过session方法开发购物车,用户关闭浏览器后,自动清空购物车

    • 点击【加入购物车】
    1. 先要跳转到 cart/insert.php 添加进购物车
    2. 确定后,才跳转到 index.php 查看购物车
    • 用户选择  →  加入购物车 后,如果最后没有购买,结账  → 用户关闭浏览器后,自动清空购物车
    1. 浏览器关闭后,session数组立刻清空,session自动过期
    2. PHPSESSID 保存在浏览器 cookie中
    • 购物车核心原理:数组改造,大数组里面放小数组   insert.php
      session_start();
      
      $id = $_GET['id'];
      $sql = "select * from book where id = {$id}";
      $rst = mysql_query($sql);
      $row = mysql_fetch_assoc($rst);
      
      $_SESSION['books'][$id]=$row;   //用id限制同一图书只能加一个,然后在购物车页面中进行加减数量
      
      //在图书信息的子数组中临时加一个num 默认1, 方便index.php中使用变量 <?php echo $book['num']?>
      $_SESSION['books'][$id]['num']=1;
    • 跳转到 index.php 查看
      echo '<script>location="index.php"</script>';
      

      有了数组,就不用while了,用foreach遍历数组  index.php

      <?php
          foreach($_SESSION['books'] as $book){
      ?>
          …… ……
      <?php
          }
      ?>
    • 删除购物车图书  delete.php
      // 在session中找到 删除 
      unset($_SESSION['books'][$id]);
    • 清空购物车图书
       $_SESSION['books']=array(); 
      

      不可以unset,那样会把 $_SESSION['books']删掉  

    • 购物车计算总额
      $tot = 0
      

      遍历后(foreach 或 while循环)

      $tot += $row['price']*$row['num']; 
    • 购物车图书数量加减:add.php 、cut.php
      $_SESSION['books'][$id]['num']++;
      $_SESSION['books'][$id]['num']--;
      

      限制数量 加→不能多于库存  减→不能少于1个

      if($_SESSION['books'][$id]['num']<1){
         $_SESSION['books'][$id]['num'] = 1;
      }
      if($_SESSION['books'][$id]['num'] > $_SESSION['books'][$id]['stock']){
         $_SESSION['books'][$id]['num'] = $_SESSION['books'][$id]['stock'];
      }

    28、购物车的  联系方式、提交订单

    • 个人中心的所有页面,都要 提示 先登录,才可以看到
      <!--判断用户是否登录 session-->
      <?php
          if($_SESSION['home_username']){
      ?> 
          ……
      <?php
         }
      ?>
    • 用户在【不关闭浏览器】情况下
    1. 退出登录 → 保留session中购物车的数组内容
    2. 实现换个账号结算购物车交换数组内容(购物车内容不变)
      $arr=$_SESSION['books'];
      
      $_SESSION = array(); //清空session数组
      
      $_SESSION['books']=$arr;

    29、登录后不仅要在session中放入username ,一般还要放入userid

    • 使用userid进行判断,获取数据
    • 方便后面在 【用户个人信息】(等其它只有用户自己可看到的页面)中 获取 userid
      $_SESSION['home_userid'] = $row['id'];
      
      $user_id = $_SESSION['home_userid'];
      $sql = "select * from touch where user_id = {$user_id}";
      $rst = mysql_query($sql);

    30、在各个 后台数据管理模块中 修改都要有一个隐藏域 传id

    31、购物车生成订单

    • 需要form表单传一个touch的id,其余的图书信息都在购物车的session数组中存放,可直接取
    • 核心要点:借用session技术跨页面 ↑ 
    • 注意:一定要把 form表单 放在table的外面,因为一些浏览器会不支持table里面放form,只支持form里面放table
    • 生成 订单号 为确保唯一性:随机数 加 时间戳
      $code =time().mt_rand();
      $code =microtime(true).time().mt_rand();   //microtime(true)微秒
      $code =time().mt_rand().mt_rand(1,10);
      $code =time().mt_rand().range('a','z'); 

    32、购物车 提交订单之后,要做两件事

    • 第一:库存减去 数量
    • 第二:购物车清空
    • book.php:加入购物车之前 要判断一下 库存stock至少等于1

    33、提交订单的用户,只有在 ‘已确认’状态下,才可以评论

    34、在CSS样式表里,用class类

    • 最好不用id 标签
    • 因为 class 类 优点:唯一的能用,不唯一的也能用

    二、运行效果图

    1、注册功能

    注册界面
     
     错误提示
    通过提示

    2、二手书搜索功能

     高级搜索成功界面
     
     搜索失败提示

    3、二手书发布功能

     用户发布二手书界面
     
     用户发布二手书成功

    4、二手书购买与评论功能

     加入购物车界面
     
     购物车界面
     提交订单成功
     
     未确认时查看订单界面
     
     未确认时查看订单详情界面
     
     确认时查看订单详情界面
     确认后撰写评论
     
     评论成功

    注:转载请注明出处 

  • 相关阅读:
    oracle 日期函数
    SharpDevelop学习笔记(5)—— AddIns系统详解
    C#3.0 为我们带来什么(2) —— 自动属性
    SharpDevelop学习笔记(6)—— AddIn构建指南
    SharpDevelp2.0学习笔记(1)——SharpDevelp简单介绍
    对象数组根据某属性列的灵活排序
    SharpDevelop学习笔记(4)——SharpDevelop的核心
    也谈2007
    SharpDevelop学习笔记(2)——体系结构
    C#3.0 为我们带来什么(1) —— LINQ之Lambda
  • 原文地址:https://www.cnblogs.com/ljq66/p/10753355.html
Copyright © 2020-2023  润新知