網站程式設計-PHP
一、結構規劃
- 資料表:creative_nav
 - 關鍵字:icon_home
 - 後台程式名稱:admin/icon.php
 - 後台樣板:templates/admin/tpl/admin_icon.html
 
二、後台樣板
- templates/admin/theme.html
	
        <{if $WEB.file_name =="index.php"}>
          <{include file="tpl/admin_index.html"}>
        <{elseif $WEB.file_name =="icon.php"}>
          <{include file="tpl/admin_icon.html"}>
        <{/if}>
	
 
三、後台選單
- templates/admin/tpl/admin_nav.html
	
            <ul class="dropdown-menu dropdown-user">
                <li><a href="index.php"><i class="fa fa-user fa-fw"></i> 選單管理</a>
                </li>
                <li><a href="icon.php"><i class="fa fa-gear fa-fw"></i> 圖示管理</a>
                </li>
                <li class="divider"></li>
                <li><a href="../admin.php?op=op_logout"><i class="fa fa-sign-out fa-fw"></i> 登出</a>
                </li>
            </ul>
	
 
四、fontawwsome iconpicker
- 官網:https://itsjavi.com/fontawesome-iconpicker/
 - 安裝:
參考網站:http://github.ugm.com.tw/soft/templates/op_form.html
引入「font-awesome.min.css」
引入「fontawesome-iconpicker.min.css」
引入「fontawesome-iconpicker.min.js」
調用插件
更換jquery <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
程式碼 templates/admin/tpl/admin_icon.html <div class="row"> <link href="<{$themeUrl}>/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet"> <link rel="stylesheet" type="text/css" href="<{$smarty.const.WEB_URL}>/class/fontawesome-iconpicker/css/fontawesome-iconpicker.min.css"> <script type="text/javascript" src="<{$smarty.const.WEB_URL}>/class/fontawesome-iconpicker/js/fontawesome-iconpicker.min.js"></script> <script type='text/javascript'> $(document).ready(function(){ $('.icp').iconpicker(); }); </script> <div class="col-md-3"> <div class="form-group"> <label>圖示</label> <div class="input-group"> <input name="icon" id="icon" data-placement="bottomRight" class="form-control icp icp-auto" value="fa-archive" type="text" /> <span class="input-group-addon"></span> </div> </div> </div> </div> 
五、多行表單
- 參考網站:http://github.ugm.com.tw/soft/templates/op_form.html <div class="row"> <div class="col-md-12"> <div class="form-group"> <label>摘要</label> <textarea name="summary" id="summary" class="form-control" rows="3" placeholder="摘要"></textarea> </div> </div> </div>
 
六、網頁編輯器 CKEDITOR
- 官網:http://ckeditor.com
 - 下載Standard Package:http://ckeditor.com/download
 - 將下載檔案解壓縮至 class/
 - 引入js
 - 調用插件
 - 程式碼 templates/admin/tpl/admin_icon.html
	
        <div class="row">
          <script type="text/javascript" src="<{$smarty.const.WEB_URL}>/class/ckeditor/ckeditor.js"></script>
          <script>
            $(function() {
              CKEDITOR.replace('content');
            });
          </script>
          <div class="col-md-12">
            <div class="form-group">
              <label>內容</label>
              <textarea name="content" id="content" class="form-control" rows="5" placeholder="內容"></textarea>
            </div>
          </div>          
        </div>
	
 
七、將elFinder整合至CKEDITOR
- 官網:https://studio-42.github.io/elFinder/
 - 將下載檔案解壓縮至 class/elFinder
 - 引入elFinder
	
          <script>
            $(function() {
              CKEDITOR.replace('content', {
                language : 'zh' ,
                contentsCss : ['<{$themeUrl}>/vendor/bootstrap/css/bootstrap.min.css'],
                filebrowserBrowseUrl : '<{$smarty.const.WEB_URL}>/class/elFinder/elfinder.html'
              } );
            });
          </script>
	
 - 修改 class/elFinder/elfinder.html
	
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>elFinder 2.1.x source version with PHP connector</title>
		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2" />
		<!-- jQuery and jQuery UI (REQUIRED) -->
		<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
		<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
		<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
		<!-- elFinder CSS (REQUIRED) -->
		<link rel="stylesheet" type="text/css" href="css/elfinder.min.css">
		<link rel="stylesheet" type="text/css" href="css/theme.css">
		<!-- elFinder JS (REQUIRED) -->
		<script src="js/elfinder.min.js"></script>
		<!-- GoogleDocs Quicklook plugin for GoogleDrive Volume (OPTIONAL) -->
		<!--<script src="js/extras/quicklook.googledocs.js"></script>-->
        <!-- elFinder translation (OPTIONAL) -->
        <script src="js/i18n/elfinder.zh_TW.js"></script>
        <!-- elFinder initialization (REQUIRED) -->
        <script type="text/javascript" charset="utf-8">
            // Helper function to get parameters from the query string.
            function getUrlParam(paramName) {
                var reParam = new RegExp('(?:[\?&]|&)' + paramName + '=([^&]+)', 'i') ;
                var match = window.location.search.match(reParam) ;
                return (match && match.length > 1) ? match[1] : '' ;
            }
            $().ready(function() {
                var funcNum = getUrlParam('CKEditorFuncNum');
                var elf = $('#elfinder').elfinder({
                    url : 'php/connector.minimal.php',
                    lang: 'zh_TW',                    // language (OPTIONAL)
                    getFileCallback : function(file) {
                        window.opener.CKEDITOR.tools.callFunction(funcNum, file.url);
                        window.close();
                    },
                    resizable: false
                }).elfinder('instance');
            });
        </script>
	</head>
	<body>
		<!-- Element where elFinder will be created (REQUIRED) -->
		<div id="elfinder"></div>
	</body>
</html>
	
 - 修改 class/elFinder/php/connector.minimal.php
	
<?php
error_reporting(0); // Set E_ALL for debuging
include_once "../../../head.php";
include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'elFinderConnector.class.php';
include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'elFinder.class.php';
include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'elFinderVolumeDriver.class.php';
include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'elFinderVolumeLocalFileSystem.class.php';
// Required for MySQL storage connector
// include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elFinderVolumeMySQL.class.php';
// Required for FTP connector support
// include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elFinderVolumeFTP.class.php';
// ===============================================
/**
 * # Dropbox volume driver need `composer require dropbox-php/dropbox-php:dev-master@dev`
 *  OR "dropbox-php's Dropbox" and "PHP OAuth extension" or "PEAR's HTTP_OAUTH package"
 * * dropbox-php: http://www.dropbox-php.com/
 * * PHP OAuth extension: http://pecl.php.net/package/oauth
 * * PEAR's HTTP_OAUTH package: http://pear.php.net/package/http_oauth
 *  * HTTP_OAUTH package require HTTP_Request2 and Net_URL2
 */
// // Required for Dropbox.com connector support
// // On composer
// require 'vendor/autoload.php';
// elFinder::$netDrivers['dropbox'] = 'Dropbox';
// // OR on pear
// include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elFinderVolumeDropbox.class.php';
// // Dropbox driver need next two settings. You can get at https://www.dropbox.com/developers
// define('ELFINDER_DROPBOX_CONSUMERKEY',    '');
// define('ELFINDER_DROPBOX_CONSUMERSECRET', '');
// define('ELFINDER_DROPBOX_META_CACHE_PATH',''); // optional for `options['metaCachePath']`
// ===============================================
// // Required for Google Drive network mount
// // Installation by composer
// // `composer require nao-pon/flysystem-google-drive:~1.1 google/apiclient:~2.0@rc nao-pon/elfinder-flysystem-driver-ext`
// // composer autoload
// require 'vendor/autoload.php';
// // Enable network mount
// elFinder::$netDrivers['googledrive'] = 'FlysystemGoogleDriveNetmount';
// // GoogleDrive Netmount driver need next two settings. You can get at https://console.developers.google.com
// // AND reuire regist redirect url to "YOUR_CONNECTOR_URL?cmd=netmount&protocol=googledrive&host=1"
// define('ELFINDER_GOOGLEDRIVE_CLIENTID',     '');
// define('ELFINDER_GOOGLEDRIVE_CLIENTSECRET', '');
// ===============================================
/**
 * Simple function to demonstrate how to control file access using "accessControl" callback.
 * This method will disable accessing files/folders starting from '.' (dot)
 *
 * @param  string  $attr  attribute name (read|write|locked|hidden)
 * @param  string  $path  file path relative to volume root directory started with directory separator
 * @return bool|null
 **/
function access($attr, $path, $data, $volume) {
	return strpos(basename($path), '.') === 0// if file/folder begins with '.' (dot)
	 ? !($attr == 'read' || $attr == 'write') // set read+write to false, other (locked+hidden) set to true
	 : null; // else elFinder decide it itself
}
// Documentation for connector options:
// https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options
$opts = array(
	// 'debug' => true,
	'roots' => array(
		array(
			'driver' => 'LocalFileSystem', // driver for accessing file system (REQUIRED)
			'path' => WEB_PATH . "/uploads/", // path to files (REQUIRED)
			'URL' => WEB_URL . "/uploads/", // URL to files (REQUIRED)
			'uploadDeny' => array('all'), // All Mimetypes not allowed to upload
			'uploadAllow' => array('image', 'text/plain'), // Mimetype `image` and `text/plain` allowed to upload
			'uploadOrder' => array('deny', 'allow'), // allowed Mimetype `image` and `text/plain` only
			'accessControl' => 'access', // disable and hide dot starting files (OPTIONAL)
		),
	),
);
// run elFinder
$connector = new elFinderConnector(new elFinder($opts));
$connector->run();
	
 
八、op_insert
 
參考:http://php.net/manual/en/function.json-encode.php
################################# # 新增資料 # ################################# function op_insert() { global $mysqli; //print_r($_POST);die(); #資料過濾 #http://php.net/manual/en/mysqli.real-escape-string.php $_POST['title'] = $mysqli->real_escape_string($_POST['title']); $_POST['target'] = intval($_POST['target']); $_POST['enable'] = intval($_POST['enable']); $_POST['sort'] = intval($_POST['sort']); $_POST['url'] = $mysqli->real_escape_string($_POST['url']); $_POST['kind'] = $mysqli->real_escape_string($_POST['kind']); #圖示、摘要與內容存成json $content['icon'] = $mysqli->real_escape_string($_POST['icon']); $content['summary'] = $mysqli->real_escape_string($_POST['summary']); $content['content'] = $mysqli->real_escape_string($_POST['content']); $_POST['content'] = json_encode($content, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE); $sql = "insert into `creative_nav` (`title`, `target`, `enable`, `sort`,`url`,`kind`,`content`) VALUES ('{$_POST['title']}', '{$_POST['target']}', '{$_POST['enable']}', '{$_POST['sort']}', '{$_POST['url']}', '{$_POST['kind']}', '{$_POST['content']}')"; //die($sql); $mysqli->query($sql) or die(printf("Error: %s <br>" . $sql, $mysqli->sqlstate)); $sn = $mysqli->insert_id; //傳回insert 指令所產生之流水號 return $sn; }
九、op_update
 
十、撈出單筆資料
- get_creative_nav
	
########################################
#取得單筆記錄
########################################
function get_creative_nav($sn = "") {
  global $mysqli;
  if (!$sn) {
    redirect_header("index.php", 3000, "查詢選單資料錯誤!!");
  }
 
  $sql = "select *
          from `creative_nav`
          where `sn`='{$sn}' and `kind`= 'icon_home'";
  $result = $mysqli->query($sql) or die(printf("Error: %s <br>" . $sql, $mysqli->sqlstate));
  $row = $result->fetch_assoc();
 
  #過濾撈出資料
  $row['sn'] = intval($row['sn']);
  //http://www.w3school.com.cn/php/func_string_htmlspecialchars.asp
  $row['title'] = htmlspecialchars($row['title'], ENT_QUOTES); // 轉換雙引號和單引號
  $row['url'] = htmlspecialchars($row['url'], ENT_QUOTES); // 轉換雙引號和單引號
  $row['sort'] = intval($row['sort']);
  $row['enable'] = intval($row['enable']);
  $row['target'] = intval($row['target']);
  $content = json_decode($row['content'], true); //(PHP 5 >= 5.2.0 true=>array 
  
  $row['icon'] = htmlspecialchars($content['icon'], ENT_QUOTES); // 轉換雙引號和單引號
  $row['summary'] = htmlspecialchars($content['summary'], ENT_QUOTES); // 轉換雙引號和單引號
  $row['content'] = htmlspecialchars($content['content'], ENT_QUOTES); // 轉換雙引號和單引號
 
  return $row;
}
	
 
十一、op_form
參考:http://php.net/manual/en/function.json-decode.php
################################# # 表單 # 選單關鍵字 icon_home ################################# function op_form($sn = "") { global $mysqli, $smarty; #取得預設值 if ($sn) { #編輯 $row = get_creative_nav($sn); //取得單筆記錄 $row['op'] = "op_update"; $row['form_title'] = "編輯選單"; } else { #新增 $row = array(); $row['op'] = "op_insert"; $row['form_title'] = "新增選單"; } #預設值設定 $row['sn'] = (isset($row['sn'])) ? $row['sn'] : ""; $row['title'] = (isset($row['title'])) ? $row['title'] : ""; $row['enable'] = (isset($row['enable'])) ? $row['enable'] : 1; $row['target'] = (isset($row['target'])) ? $row['target'] : 0; $row['url'] = (isset($row['url'])) ? $row['url'] : ""; $row['sort'] = (isset($row['sort'])) ? $row['sort'] : 0; $row['kind'] = (isset($row['kind'])) ? $row['kind'] : "icon_home"; $row['icon'] = (isset($row['icon'])) ? $row['icon'] : "fa-android"; $row['content'] = (isset($row['content'])) ? $row['content'] : ""; $row['summary'] = (isset($row['summary'])) ? $row['summary'] : ""; #把變數送至樣板 $smarty->assign("row", $row); }十二、修改樣板
- 用「新聞」取代「選單」在 icon.php 與 templates/admin/tpl/admin_icon.html
 - 「textarea」預設值
	
          <div class="col-md-12">
            <div class="form-group">
              <label>內容</label>
              <textarea name="content" id="content" class="form-control" rows="5" placeholder="內容"><{$row.content}></textarea>
            </div>
          </div>