一、結構規劃
二、後台樣板
<{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}>
三、後台選單
<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
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<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>
五、多行表單
<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
<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
<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>
<!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>
<?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
################################# # 更新資料 # ################################# function op_update($sn = "") { global $mysqli; if (!$sn) { redirect_header("index.php", 3000, "更新記錄錯誤!!"); } #資料過濾 $_POST['sn'] = intval($_POST['sn']); $_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']); #圖示、摘要與內容存成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 = "update `creative_nav` set `title` = '{$_POST['title']}' , `target` = '{$_POST['target']}', `enable` = '{$_POST['enable']}', `url` = '{$_POST['url']}', `sort` = '{$_POST['sort']}', `content` = '{$_POST['content']}' where sn='{$_POST['sn']}'"; $mysqli->query($sql) or die(printf("Error: %s <br>" . $sql, $mysqli->sqlstate)); return $sn; }
十、撈出單筆資料
######################################## #取得單筆記錄 ######################################## 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); }
十二、修改樣板
<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>