<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                我以自己的oneblog體驗了一下tp5 beta 版的使用,寫下最小修改的升級方式。 # 目的 告訴大家如何去移植舊項目到新版tp5 beta中去。以及可能遇到的問題,和老楊是怎么解決的。 # 前提 做正確的移植之前,我們得熟讀一下本手冊,這樣才能少走彎路。 # 幾個巨大的變化 ## 命名規范 一開始說是PSR0 后來大家協作時說規范是PSR2, 有人建議Sublime 裝一個phpfmt 插件,可是我裝了提示php版本低于5.6 用不了。不折騰了。 建議大家看看之前的命名規范章節。 主要是命名空間,目錄和文件名小寫,分割用_,但是類名要大寫首字母駝峰式。開始老楊也不理解,為什么類名不也小寫。后來一想,類名一小寫。就難和文件和目錄區分開了。 ## 配置不合并 以往我們記得有個Common模塊, 里面有公共函數、公共配置,然后其他模塊的會先加載這個配置和函數然后去跟當前模塊的合并。現在不行了。現在的公共配置不放在Common里,放在application APP_PATH根目錄下。什么config.php、database.php、common.php啦。后來問老大那現在的Common 干嘛用,他說放公共的類,比如公共的model、behavior ## Traits 新框架用了php5.4開始添加的Traits功能,老楊看了下,就是用于多繼承的,使得代碼更精簡,比方 原來我們有高級模型、視圖模型,然后,我們一個類既有視圖模型、又有高級模型的功能,要實現這樣的怎么辦,定義一個第三方模型,復制這兩個模型里的代碼。。 現在有了Traits,我們可以 通過use 關鍵字,將Traits 實現的功能,直接在模型里 復用一下。框架新增了T函數是為了兼容php5.4版本的,5.5的可以直接引用。 因此,老大在架構上把一些常用的自動完成、高級模型給分離開到traits目錄里去了,這帶來了一些不便。后面我會講如何去使用,達到以前的效果。 ## 調試 以前的調試工具條被舍棄了,換成了專門調試api的不影響頁面輸出的SocketLog工具。當然也不說不能用,只是有一些不便:依賴網絡、空值不輸出。 ## 耦合低了,很多東西獨立開來了,比如視圖 以前我們控制器里可以直接display、error、succes。現在必須依賴視圖類,因為老大認為面向api的框架,很少需要視圖。當然如果能用視圖的話,原先的視圖功能還是完整的,只不過使用上不方便。 # 移植的步驟 ## 入口+框架 首先去<https://github.com/top-think/think> git 工具下載一份 beta版 tp5。 放入自己的環境里去。 然后修改入口文件,改為以下的: ~~~ <?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- // | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <liu21st@gmail.com> // +---------------------------------------------------------------------- // 應用入口文件 // 定義項目路徑 define('APP_PATH', './application/'); define('ONETHINK_ADDON_PATH', './addons/'); // 開啟調試模式 define('APP_DEBUG', true); define('APP_HOOK', true); define('SLOG_ON', true); // define('BIND_MODULE','home'); // define('BIND_CONTROLLER','index'); // 加載框架引導文件 require './thinkphp/start.php'; ~~~ ## 自動生成 默認的示列應用APP_PATH下帶了一個build.php 自動生成配置文件,我們可以修改一下,用于生成自己以前項目的目錄結構,不過有點繁瑣。 比方老楊以前的tp3.2的application下的結構是這樣子的: ![](https://box.kancloud.cn/2015-12-19_5674d7727cf1b.png) 添加自動完成時,一個模塊一個模塊的加。然后依次是模塊對應的子目錄`__dir__`、`__file__`、controller、model、view 之類的子目錄。比如老楊的admin模塊: ~~~ 'admin' => [ '__file__' => [], '__dir__' => ['controller', 'view'], 'controller' => ['Addons', 'Article', 'Cate', 'Common', 'Config', 'System', 'Theme', 'User'], 'view' => ['addons/index', 'article/add', 'cate/add', 'config/index', 'public/base', 'system/index', 'tags/index', 'theme/index', 'user/index'], ], ~~~ 因為模塊里的視圖模板文件太多了,一個個手寫很累,所以老楊只寫了一個控制器里的一個模板,生成好后,手動復制過來整個目錄的模板即可(因為模板一般都小寫的,不用改文件名)。 自動生成控制器和模型的目的是節省時間,因為變化太大了:沒有.class.php后綴,首字母要小寫,對應命名空間也變了。能偷懶為什么不用呢。其實如果針對移植升級,可以寫一個小腳本,掃描舊目錄去生成對應新版的。 PS:sublime 對于rename這件事有個bug,就是如果有的目錄或者文件更改大小寫,然后這個目錄和文件就打不開了。即使用菜單的刷新功能更也沒用。只能手動關閉整個項目,再重新打開st。老楊發現重命名時先改小寫的,同時多加一個s后 先重命名一次,然后在去掉s 百分百不會觸發bug。 PS:自動生成每次訪問都會生成,如果你后來想刪除某些文件了。記得把自動生成的也改一下,要是node 可以用gulp之類的watch 一下。php 還是人工吧。 完整的oneblog 生成: ~~~ return [ // 生成運行時目錄 'runtime' => [ '__dir__' => ['cache', 'log', 'temp'], ], 'admin' => [ '__file__' => [], '__dir__' => ['controller', 'view'], 'controller' => ['Addons', 'Article', 'Cate', 'Common', 'Config', 'System', 'Theme', 'User'], 'view' => ['addons/index', 'article/add', 'cate/add', 'config/index', 'public/base', 'system/index', 'tags/index', 'theme/index', 'user/index'], ], 'common'=>[ '__file__' => [], '__dir__' => ['behavior', 'controller', 'model', 'api'], 'controller' => ['Addon'], 'model' => ['Addons', 'Article', 'Cate', 'Config', 'File', 'Hooks', 'Picture', 'Tree', 'Url'], ], 'home'=>[ '__file__' => ['config.php', 'common.php'], '__dir__' => ['widget', 'controller', 'view'], 'controller' => ['Addons', 'Api', 'Error', 'Index'], 'view' => ['index/index', 'widget/archive'], 'widget' =>['Common'] ], // 。。。 其他更多的模塊定義 ]; ~~~ ## 更新數據庫配置、slog和其他配置 首先數據庫的配置獨立出來再APP_PATH下的database.php。記得新版 咱數組用[] 來寫,多精簡。 然后就是老幾項了。hostname、username、password 之類的。 slog 的配置: ~~~ 'slog' => [ 'enable' => true, //是否記錄日志的開關 'host' => '111.202.76.133', //是否顯示利于優化的參數,如果允許時間,消耗內存等 'optimize' => true, 'show_included_files' => true, 'error_handler' => true, //日志強制記錄到配置的client_id 'force_client_id' => 'XXX', //限制允許讀取日志的client_id 'allow_client_ids' => ['XXX'], ], ~~~ 新版的配置文件中鍵名都是小寫。老的用來寫舊版的和自定義配置吧。 注意的是入口要定義 SLOG_ON 常量為true才起作用,老楊也是追了源碼才知道的。 其他配置項,可以參考框架的convention.php文件 ![](https://box.kancloud.cn/2015-12-19_5674d77296a1f.png) 有對應的注釋。 PS:有的類的構造方法里的配置,需要寫在對應的命名空間里,如 ![](https://box.kancloud.cn/2015-12-19_5674d773443eb.png) template的配置,并不是不可變,而是要 ~~~ 'template'=>[ 'compile_type'=>'sae' ] ~~~ 這樣去改變,老楊也是測試sae試出來的。 ## 移植模塊目錄里的函數、配置、tags 公共函數移出來,對應模塊的函數復制到對應模塊的common.php中,配置也是對應的config.php tags.php也是,只不過現在沒有多余的Common和Config目錄了,都是單文件。 ## 將視圖復制過來,修復命名上的錯誤 將對應的模塊的view目錄復制過來。基本上就能用了,但是注意一件事,include 和 extend 的name 對應的路徑,只支持控制器/模板名了,且區分大小寫。因此Public/Common 和public::common都是不對的。必須public/common 等搞定視圖輸出,時測試一些用法。老楊測試出include 屬性變量沒解析對和switch的 case 多層嵌套有問題,當然已經修復了,你們可以測測看有什么不兼容的。去提issue。 ## 局部訪問 測試bug 差異化 控制器的一些方法、框架函數之類的。 常見單字母函數,框架還是留了可以兼容。如D('Article') 會找當前模塊的,找不到去找common/model下的article.php就是Article類。 # 遇到的問題 ## 公共模塊的配置不合并了? 參見上面的介紹,位置變了。 ## 視圖里一些方法不見了 為了能更好的測試,及系統流程的變化,現在tp的控制器必須有返回值。(特殊方法除外)。 返回給Response類(去thinkphp\libary\think下找), 所以官方的例子是 new \think\View 自己fetch 自己return。 后來群友提出來以前方便的succes和error 自動判斷ajax 不見。我覺得每次自己實例化視圖類很麻煩,老大就用Traits支持了 controller類里 的視圖替換字符串變了fetch、show、assign 方法: ![](https://box.kancloud.cn/2015-12-19_5674d7745495e.png) 因此我們只需要有視圖的控制器繼承 \think\controller類就行了和之前一樣的assign、show、及拋棄display 用 fetch 替代。return 模板字符串。 ## 配置精簡了 大家看convention.php 文件就知道配置少了很多了。因為很多行為也沒了。 ## 分頁類沒有了 為了內核的精簡,老大沒有加,老楊手動移植了一個放到org和ot里 ot 自定義了樣式。其他的類你看著放吧! ## $this->redirect 沒了 去response類看看 可以`\think\response::redirect` ## 模型默認很多快捷操作沒有了? 這個很頭痛,比方說以前M('article')->count()、 M('Article')->getField 和getFieldBy 都不能用了。 現在只能 D后用,然后在對應的模型里,使用 traits。 如 ~~~ <?php namespace common\model; T('model/adv'); T('model/auto'); class Article extends \think\Model{ use \traits\model\adv; use \traits\model\auto; public function _initialize(){ /* 自動驗證規則 */ $this->validate = array( array('name', '/^[a-zA-Z]\w{0,39}$/', '文檔標識不合法', self::VALUE_VALIDATE, 'regex', self::MODEL_BOTH), array('name', '', '標識已經存在', self::VALUE_VALIDATE,'unique'), array('title', 'require', '標題不能為空', self::MUST_VALIDATE, 'regex', self::MODEL_BOTH), array('title', '1,80', '標題長度不能超過80個字符', self::MUST_VALIDATE, 'length', self::MODEL_BOTH), array('description', '1,140', '簡介長度不能超過140個字符', self::VALUE_VALIDATE, 'length', self::MODEL_BOTH), array('cate_id', 'require', '分類不能為空', self::MUST_VALIDATE , 'regex', self::MODEL_INSERT), array('cate_id', 'require', '分類不能為空', self::EXISTS_VALIDATE , 'regex', self::MODEL_UPDATE), ); /* 自動完成規則 */ $this->auto = array( array('uid', 'is_login', self::MODEL_INSERT, 'function'), array('title', 'htmlspecialchars', self::MODEL_BOTH, 'function'), array('content', 'base_encode', self::MODEL_BOTH, 'callback'), array('description', 'htmlspecialchars', self::MODEL_BOTH, 'function'), array('link_id', 'getLink', self::MODEL_BOTH, 'callback'), array('view', 0, self::MODEL_INSERT, 'string'), array('comment', 0, self::MODEL_INSERT, 'string'), array('create_time', 'getCreateTime', self::MODEL_BOTH,'callback'), array('update_time', NOW_TIME, self::MODEL_BOTH, 'string'), array('status', '1', self::MODEL_INSERT, 'string'), ); } ~~~ 有自動完成和自動驗證的用 traits/auto。 有after 后置操作,和快捷操作的 用 traits/adv。 發現自己的查詢不支持了,先去 traits/model 里找找。 因此有時為了一個簡單的復雜查詢得建一個簡單模型: 如user ~~~ <?php namespace common\model; T('model/adv'); class User extends \Think\Model{ use \traits\model\adv; } ~~~ 注意的是新版的 auto 和 valiate 不帶_ 了,我的做法是 _initialize 方法里 屬性賦值或者直接= 以前的數組。 ## 模板路徑替換不能用了? 因為新版 現在沒有任何內置行為。 開始我是移植舊的ContentReplace行為。`parse_str` 這個配置。 配置里將以前的TPML_PARSE_STRING 替換成這個鍵名即可。 值的注意的是 以前3.2版 dispatch 里定義的很多常量沒了, `__ROOT__` 之類的,我挑了3個常用的 `__ROOT__`、`__APP__`、`__SELF__` ~~~ if (!IS_CLI) { // 當前文件名 if (!defined('_PHP_FILE_')) { if (IS_CGI) { //CGI/FASTCGI模式下 $_temp = explode('.php', $_SERVER['PHP_SELF']); define('_PHP_FILE_', rtrim(str_replace($_SERVER['HTTP_HOST'], '', $_temp[0] . '.php'), '/')); } else { define('_PHP_FILE_', rtrim($_SERVER['SCRIPT_NAME'], '/')); } } if (!defined('__ROOT__')) { $_root = rtrim(dirname(_PHP_FILE_), '/'); define('__ROOT__', (($_root == '/' || $_root == '\\') ? '' : $_root)); } define('PHP_FILE', _PHP_FILE_); } if(!defined('__APP__')) define('__APP__', strip_tags(PHP_FILE)); // URL常量 if(!defined('__SELF__')) define('__SELF__', strip_tags($_SERVER[C('URL_REQUEST_URI')])); ~~~ 將舊版的移植到 config.php return 上面。本來是想放common.php公共函數里的,結果不起作用。 ## 插件不能用了? 由于oneblog 移植了ot的插件機制,所以也得研究一下了。 插件依賴鉤子,所以入口要定義HOOK_ON 常量。 然后頭疼的就是命名空間了。 3.2的插件目錄結構和文件名: ![](https://box.kancloud.cn/2015-12-19_5674d7751592f.png) 5.0 的: ![](https://box.kancloud.cn/2015-12-19_5674d77523cc2.png) 就是插件目錄小寫了,后綴變了。目錄名也變了,然后類名不變。 以前一個控制器是BookMark/BookMark 現在變成了 book_mark/BookMark!!! 然后咱找個地方定義插件目錄常量 入口: `define('ONETHINK_ADDON_PATH', './addons/');` 添加命名空間: Think\Loader::addNamespace('addons', ONETHINK_ADDON_PATH); 公共函數里添加命名空間印射目錄。 然后修改common/behavior/init_hook.php 初始化鉤子行為 ~~~ <?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK IT ] // +---------------------------------------------------------------------- // | Copyright (c) 2006-2013 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <liu21st@gmail.com> // +---------------------------------------------------------------------- namespace common\behavior; use think\Hook; use think\Loader; defined('THINK_PATH') or exit(); // 初始化鉤子信息 class InitHook{ // 行為擴展的執行入口必須是run public function run(&$content) { if (isset($_GET['m']) && $_GET['m'] === 'Install') return; // $data = null; $data = S('hooks'); if (!$data) { $hooks = D('Hooks')->getField('name,addons'); foreach ($hooks as $hook => $value) { if ($value) { $map['status'] = 1; $names = explode(',', $value); $map['name'] = array('IN', $names); $data = D('Addons')->where($map)->getField('id,name'); if ($data) { $addons = array_intersect($names, $data); foreach ($addons as $key => $value) { $dir = Loader::parseName(lcfirst($value)); $path = "./addons/{$dir}/".Loader::parseName(lcfirst($value)).".php"; $value = "addons\\{$dir}\\{$value}"; $path = realpath($path); $addons[$key] = $value; Loader::addMap($value, $path); } Hook::add($hook, $addons); } } } S('hooks', Hook::get()); } else { Hook::import($data, false); } } } ~~~ 里面Loader::addMap 可是我實踐出來的,開始以為定義了命名空間能自已找到類,結果得添加alias。 然后就是公共tags里添加行為: ~~~ <?php return [ 'app_init' => ['common\\behavior\\InitHook'], ]; ~~~ 這里寫的都是命名空間規則,而不是路徑。 common/controller/addon.php 插件定義抽象類修改,改getName 獲取路徑等方法,改著改著就成了這樣: ~~~ <?php namespace common\controller; /** * 插件類 * @author yangweijie <yangweijiester@gmail.com> */ abstract class Addon extends \think\controller{ /** * 視圖實例對象 * @var view * @access protected */ protected $view = null; /** * $info = array( * 'name'=>'Editor', * 'title'=>'編輯器', * 'description'=>'用于增強整站長文本的輸入和顯示', * 'status'=>1, * 'author'=>'thinkphp', * 'version'=>'0.1' * ) */ public $info = array(); public $addon_path = ''; public $config_file = ''; public $custom_config = ''; public $admin_list = array(); public $custom_adminlist = ''; public $access_url = array(); public function __construct() { $this->addon_path = ONETHINK_ADDON_PATH . lcfirst($this->getName()) . '/'; $parse_str = C('parse_str'); $parse_str['__ADDONROOT__'] = __ROOT__ . '/addons/' . $this->getName(); C('parse_str', $parse_str); if (is_file($this->addon_path . 'config.php')) { $this->config_file = $this->addon_path . 'config.php'; } } /** * 模板主題設置 * @access protected * @param string $theme 模版主題 * @return Action */ final protected function theme($theme) { $this->view->theme($theme); return $this; } final protected function addon_path(){ return ONETHINK_ADDON_PATH . lcfirst($this->getName()) . '/'; } //顯示方法 final protected function display($template = '') { if (!is_file($template)) { $template = $this->addon_path() . $template . '.html'; if (!is_file($template)) { throw new \Exception("模板不存在:$template"); } } $html = $this->fetch($template); return $html; } /** * 獲取插件目錄或名稱 * @param $type 0 - dir 1- name */ final public function getName($type = 0) { $class = get_class($this); $class = str_replace("addons\\", '', $class); $class_arr = explode('\\', $class); return $class_arr[$type]; } final public function checkInfo() { $info_check_keys = array('name', 'title', 'description', 'status', 'author', 'version'); foreach ($info_check_keys as $value) { if (!array_key_exists($value, $this->info)) return FALSE; } return TRUE; } /** * 獲取插件的配置數組 */ final public function getConfig($name = '') { static $_config = array(); if (empty($name)) { $name = $this->getName(1); } if (isset($_config[$name])) { return $_config[$name]; } $config = array(); $map['name'] = $name; $map['status'] = 1; $config = D('Addons')->where($map)->getField('config'); if ($config) { $config = json_decode($config, true); return $config; } else if(!empty($this->config_file)){ $temp_arr = include $this->config_file; foreach ($temp_arr as $key => $value) { if ($value['type'] == 'group') { foreach ($value['options'] as $gkey => $gvalue) { foreach ($gvalue['options'] as $ikey => $ivalue) { $config[$ikey] = $ivalue['value']; } } } else { $config[$key] = $temp_arr[$key]['value']; } } $_config[$name] = $config; return $config; }else{ return []; } } //必須實現安裝 abstract public function install(); //必須卸載插件方法 abstract public function uninstall(); } ~~~ 后來就是改后臺相關的類。主要改了顯示的地方,config方法和controller的沖突了換成conf。后面框架會去掉這個方法。 home 和admin 插件控制器執行方法: ~~~ <?php namespace home\controller; class Addons extends \think\controller{ protected $addons = null; public function execute($_addons = null, $_controller = null, $_action = null){ $dir = \think\Loader::parseName($_addons, 0); $_controller = \think\Loader::parseName($_controller,1); $parse_str = C('parse_str'); $parse_str['__ADDONROOT__'] = __ROOT__ . "/addons/{$dir}"; C('parse_str', $parse_str); if(!empty($_addons) && !empty($_controller) && !empty($_action)){ $addons = A("addons\\$dir/$dir")->$_action(); return $addons; } else { return $this->error('沒有指定插件名稱,控制器或操作!'); } } public function display($tpl = ''){ if (!is_file($tpl)) { $tpl = $this->addon_path() . $tpl . '.html'; if (!is_file($tpl)) { throw new \Exception("模板不存在:$tpl"); } } $html = $this->fetch($tpl); return $html; } public function success($msg = '', $data = '', $url = '', $wait = 3){ \think\Response::success($msg, $data, $url, $wait); } public function error($msg = '', $data = '', $url = '', $wait = 3){ \think\Response::error($msg, $data, $url, $wait); } } ~~~ PS:后臺插件快速創建的還么改,大家可以自己參考類修改一下,因為這只是老楊自己的移植,并不是官方tp5 以后的插件架構。 值得注意的是插件模板的顯示輸出不要exit 也不要return 回給Hook::listen 里,因為, 一個鉤子有多個插件,插件執行不一定都是返回模板。 所以,如果你要顯示什么 請 @print($this->display('single')) 這樣去寫。 ## SAE上如何使用 think/model/sae 里的配置,要加入convetion.php里的部分配置。 如果你只是但應用,數據庫就在當前應用,不需要建議database.php去配置數據庫,如果是跨應用的,就要將來源引用的配置 常量 dump出來寫死在項目公共數據庫配置里。 然后是初始化一些服務 用于緩存的 memcache服務,用于文件上傳的storage、注意sae的特性,不可寫。 配置重定向要改 config.yaml 其他基本上沒遇到問題。 # 嘗試一下吧~ 更多的以最新框架源碼為準,只要沒發布,每天更新倉庫后自己手動覆蓋已經保存svn或git的本地庫,看看變化,自己的hack是否要去除了。 下載地址<http://git.oschina.net/yangweijie/oneblog/tree/5.0beta/> 自己克隆了 切換分支后看readme。 嘗鮮就得會折騰。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看