移植 Laravel 核心組件:如何給 TP3.1 用上 IoC 容器 (一)

單位的主項目是用ThinkPHP 3.1 開發的. 功能越來越跟不上發展 , 而老代碼迭代的難度又很大 . 重構已經提上了日程, 但拋下主營業務來重構是不實際的 . 所以目前的思路是 , 將原有功能拆分成一個個獨立的組件 , 脫離ThinkPHP 3.1 運行, 未來再移植到新架構裏.

用慣了Laravel的人 , 自然很快想到了引入Laravel的IoC容器 . 它有以下好處:

  • 可以用來管理各種複雜的依賴關係
  • 方便引入第三方依賴包
  • 可以面向接口來規範重構
  • 利於迭代,一組依賴中,舊的實例可以逐個改成新的實例,而不影響調用
  • 可以用facade爲功能模塊提供簡潔的Api接口
  • 未來可直接引入laravel的 隊列, 事件, EloquentORM 等核心機制

那麼在ThinkPHP引入IoC , 需要幾步呢?如下:

  1. 確保ThinkPHP 3.1 項目運行在 php 5.4 以上環境中
  2. 給ThinkPHP 3.1 引入Composer
  3. 獨立出Laravel的Container組件
  4. 爲擴展功能設計架構
  5. 創建引入ThinkPHP的引導文件

一. 給ThinkPHP 3.1 引入Composer

時至今日 , ThinkPHP自身的autoload管理功能已經非常老舊了 , 有這幾個關鍵的痛點:

  • 沒有命名空間,大量關鍵類同名
  • 引入外部庫還要用令人費解的import()方法
  • 生成autoload的代碼位置 , 在設計理念上有錯

靠ThinkPHP去管理各種現代依賴 , 基本是不可能完成的任務 . 這時Composer就大顯身手了.

我們可以在任意文件夾創建 Composer.json 文件 , 然後按自己的設想任意構建擴展.
運行composer install指令後,composer就自動爲我們下載了所有依賴,並生成了 vendor/autoload.php 文件.

瞥一眼vendor/autoload.php 文件,會發現它其實就幹了兩件事 :

  1. 引入了 vendor/composer/ClassLoader.php,這裏註冊了各種 Autoload 機制的引用文件方法
  2. 引入了按composer.json文件定義的classmap,files,psr-0,psr-4等規範 , 生成的類名路徑映射關係文件.

所以我們只要把 vendor/autoload.php 在ThinkPHP項目中require 進來, 就可以隨心所欲使用任何自定義類和擴展,再不要受TP3.1規範的約束了.

問題是autoload.php要在哪裏引入比較合適呢? 經過反覆測試,還是在Public/index.php 中引入較好:

/**
 * 系統調試設置
 * 項目正式部署後請設置爲false
 */
define ( 'APP_DEBUG', true );
define ( 'APP_PATH', realpath(dirname(__FILE__) ."/../") ."/" );
define ( 'WEB_PATH', realpath(dirname(__FILE__)) ."/" );
/**
 * 引入核心入口
 * ThinkPHP亦可移動到WEB以外的目錄
 */

//------------!!!在這裏引入Composer的autoload!!------------//
require '../../Extends/vendor/autoload.php';
require '../ThinkPHP/ThinkPHP.php';

這是因爲ThinkPHP有非常糟糕的引導機制:

index.php  --require--> ThinkPHP.php --require--> Common/runtime.php

這個過程是單線的,穿插大量必要的宏定義,和大量的if邏輯.
最關鍵的啓動代碼 Think::Start(); 卻在 runtime.php 最後一行執行.

這好比把衣服褲子鞋子做成了一件連體服.想要加一根腰帶,要麼脫光,要麼剪開衣服.與其在劈頭蓋臉的if else中找剪裁點,還是選擇脫光吧.

下一節聊聊如何把Laravel的Container組件獨立出來

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章