:::

5. 資料的讀取、編輯修改及刪除

一、Smarty 顯示所有讀出的資料

  1. 顯示所有欄位並增加編輯鈕:
    {foreach $content as $row}
      <tr>
          <td>{$row.done}</td>
          <td>{$row.title}</td>
          <td>{$row.end}</td>
          <td>{$row.priority}</td>
          <td>{$row.assign}</td>
          <td>{$row.create_time}</td>
          <td>
            <a href="{$action}?op=post_form&sn={$row.sn}" class="btn btn-warning" title="編輯""><i class="fas fa-pencil-alt"></i> 編輯</a>
          </td>
      </tr>
    {/foreach}
  2. 使用標籤判斷是否完成:
    <td class="text-end">
      {if $row.done}
          <span class="badge bg-success "><i class="fas fa-check"></i></span>
      {else}
          <span class="badge bg-danger"><i class="fas fa-times-circle"></i></span>
      {/if}
    </td>

二、編輯(更新)資料

  1. 編輯(更新)資料的SQL語法:
    update 資料表 set 欄位1=值1,欄位2=值2,... [where 篩選條件] [limit 筆數]
  2. 一定要有where,否則的話,會所有欄位全部被更新!
  3. 編輯功能的步驟
    • 按下編輯連結時,將欲修改的資料流水號傳給程式(請用get方式傳遞參數)。
      <a href="{$action}?op=post_form&sn={$row.sn}" class="btn btn-warning" title="編輯""><i class="fas fa-pencil-alt"></i> 編輯</a>
    • 程式接收後,判斷若有接收到流水號,則為編輯模式,否則為新增模式。
      // 表單函數
      function post_form()
      {
          global $db, $smarty;
      
          if (isset($_GET['sn'])) {
              // 過濾
              $sn = (int) $_GET['sn'];
              // 去資料庫撈一筆
              $sql    = "select * from `list` where `sn`='{$sn}'";
              $result = $db->query($sql);
      
              // 執行失敗秀出訊息
              if (!$result) {
                  throw new Exception($db->error);
              }
      
              // 讀出資料
              $content = $result->fetch_assoc();
              //過濾變數
              $content['title']      = filter_var($content['title'], FILTER_SANITIZE_SPECIAL_CHARS);
              $content['directions'] = htmlspecialchars($content['directions'], ENT_QUOTES);
              $content['priority']   = filter_var($content['priority'], FILTER_SANITIZE_SPECIAL_CHARS);
              $next_op = 'update';
          } else {
              // 加入預設值
              $content = [
                  'sn'         => '',
                  'title'      => '',
                  'directions' => '',
                  'end'        => date("Y-m-d", strtotime("+10 day")),
                  'priority'   => '中',
                  'assign'     => '',
                  'assign_arr' => [],
                  'done'       => 1,
              ];
              $next_op = 'add';
          }
      
          $smarty->assign('next_op', $next_op);
          $smarty->assign('content', $content);
      
      }
    • 複選框須使用PHP字串切割函數:explode('分割符號',字串變數);
      // 表單函數
      function post_form()
      {
          global $db, $smarty;
      
          /********** 省略*************/
          //複選框
          $content['assign_arr']  = explode(";", $assign);
      
      }
      • 同時修改樣板檔 post_form.tpl
        <div class="col-sm-10 pt-2">
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="checkbox" id="assign1" name="assign[]" value="李大頭" {if in_array('李大頭',$content.assign_arr)}checked{/if} />
              <label class="form-check-label" for="assign">李大頭</label>
            </div>
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="checkbox" id="assign2" name="assign[]" value="吳大大" {if in_array('吳大大',$content.assign_arr)}checked{/if} />
              <label class="form-check-label" for="assign">吳大大</label>
            </div>
            <div class="form-check form-check-inline">
              <input class="form-check-input" type="checkbox" id="assign3" name="assign[]" value="郭大大" {if in_array('郭大大',$content.assign_arr)}checked{/if}/>
              <label class="form-check-label" for="assign">郭大大</label>
            </div>
        </div>
        
    • 用隱藏欄位來存放模式狀態,以利送出時程式判斷該新增或更新,name通常為next_op,記得加入 sn 編號。
      <input type="hidden" name="sn" value="{$content.sn}">
    • 執行更新動作
      • 新增一組case 'update' :
        case 'update':
            $sn = update();
            header("location: index.php?sn={$sn}");
            exit;
      • 執行 update()
        //更新清單
        function update()
        {
            global $db;
            //過濾變數
            $sn          = (int) $_POST['sn'];
            $title       = $db->real_escape_string($_POST['title']);
            $directions  = $db->real_escape_string($_POST['directions']);
            $end         = $db->real_escape_string($_POST['end']);
            $priority    = $db->real_escape_string($_POST['priority']);
            $assign      = $db->real_escape_string(implode(';', $_POST['assign']));
            $done        = (int) $_POST['done'];
            $update_time = date('Y-m-d H:i:s');
        
            // 連線資料庫
            $sql = "UPDATE `list` SET
            `title`='{$title}',
            `directions`='{$directions}',
            `end`='{$end}',
            `priority`='{$priority}',
            `assign`='{$assign}',
            `done`='{$done}',
            `update_time`='{$update_time}'
            WHERE `sn`= '$sn'";
            // die($sql);
            if (!$db->query($sql)) {
                throw new Exception($db->error);
            }
        
            return $sn;
        }

三、顯示單筆資料

  1. 建立 find_one()。
    // 列出單筆資料
    function find_one($sn)
    {
        global $db;
        // 去資料庫撈一筆
        $sql    = "select * from `list` where `sn`='{$sn}'";
        $result = $db->query($sql);
    
        // 執行失敗秀出訊息
        if (!$result) {
            throw new Exception($db->error);
        }
        // 讀出資料
        $content = $result->fetch_assoc();
        //過濾變數
        $content['title']      = filter_var($content['title'], FILTER_SANITIZE_SPECIAL_CHARS);
        $content['directions'] = htmlspecialchars($content['directions'], ENT_QUOTES);
        $content['priority']   = filter_var($content['priority'], FILTER_SANITIZE_SPECIAL_CHARS);
        $content['assign_arr'] = explode(";", $content['assign']);
        return $content;
    }
  2. 修改表單函數。
    // 表單函數
    function post_form()
    {
        global $db, $smarty;
    
        if (isset($_GET['sn'])) {
            // 過濾
            $sn      = (int) $_GET['sn'];
            $content = find_one($sn);
            $next_op = 'update';
        } else {
            /****省略**/        
        }
    
        $smarty->assign('next_op', $next_op);
        $smarty->assign('content', $content);
    
    }
  3. 流程加入編號判斷
    //index.php
    /********************流程判斷*********************/
    // 變數過濾
    /****省略******/
    $sn = isset($_REQUEST['sn']) ? (int) $_REQUEST['sn'] : "";
    switch ($op) {
        /****省略******/
    
        default:
            if (empty($sn)) {
                //列出所有事項
                list_all();
            } else {
                $content = find_one($sn);
                $smarty->assign('content', $content);
                $op      = 'show_one';
            }
            break;
    }
  4. templates/index.tpl
    {elseif $op=='show_one'}
            {include file="show_one.tpl"}
  5. templates/show_one.tpl
    <div class="container">
      <div class="jumbotron">
        <h2 class="text-center"><a href="{$action}"><i class="fa fa-reply"></i> {$content.title}</a></h2>
    
        <div class="alert alert-warning text-end">
          是否完成:
          {if $content.done}
              <span class="badge bg-success text-center"><i class="fas fa-check"></i></span>
          {else}
              <span class="badge bg-danger text-center"><i class="fas fa-times-circle"></i></span>
          {/if}
        </div>
    
        <div class="row">
            <label class="col-sm-3 text-end">
                描述
            </label>
            <div class="col-sm-9">
                {$content.directions|nl2br}
            </div>
        </div>
    
        <div class="row">
          <label class="col-sm-3 text-end">
            到期日
          </label>
          <div class="col-sm-9">
              {$content.end}
          </div>
        </div>
    
        <div class="row">
          <label class="col-sm-3 text-end">
            優先順序
          </label>
          <div class="col-sm-9">
              {$content.priority}
          </div>
        </div>
    
        <div class="row">
          <label class="col-sm-3 text-end">
            指派對象
          </label>
          <div class="col-sm-9">
              {$content.assign}
          </div>
        </div>
    
        <div class="row">
          <label class="col-sm-3 text-end">
            建立時間
          </label>
          <div class="col-sm-9">
              {$content.create_time}
          </div>
        </div>
    
        <div class="row">
          <label class="col-sm-3 text-end">
            最後更新時間
          </label>
          <div class="col-sm-9">
              {$content.update_time}
          </div>
        </div>
    
        <div class="text-end">
          <a href="{$action}?op=post_form&sn={$content.sn}" class="btn btn-warning">編輯</a>
          <a href="{$action}" class="btn btn-success">回首頁</a>
      </div>
      </div>
    </div>
    

四、刪除事項

  1. 加入刪除按鈕
    • 修改  templates\index.tpl,在編輯隔壁加入刪除功能
      <a href="{$action}?op=delete&sn={$row.sn}" class="btn btn-danger"  title="刪除"><i class="fas fa-times-circle"></i> 刪除</a>
    • 在單一事項頁面也記得加,修改  templates\show_one.tpl,一樣加在編輯的隔壁
      <a href="{$action}?op=delete&sn={$content.sn}" class="btn btn-danger">刪除</a>
  2. 加入刪除流程:修改 index.php 的流程,加入一組刪除的流程
    //刪除資料
    case 'delete':
            del($sn);
            header("location: index.php");
            exit;
  3. 刪除的SQL語法:
    delete from `資料表名稱` [where 篩選條件] [limit 筆數]
  4. 新增刪除函數:加入del()
    function del($sn)
    {
        global $db;
    
        $sql = "DELETE FROM `list` WHERE `sn`='{$sn}'";
        if (!$db->query($sql)) {
            throw new Exception($db->error);
        }
    }