ThinkPHP
5.1
從2018年初釋出到現在,一路小步快跑,快速疊代的同時也更新了大量的新特性。
那麼到底是否值得更新到新版呢?如果你還在糾結選用5.0的商城系統還是選用thinkphp 5.1的系統,本文就和大家分享下值得更新到 5.1
的18個理由。
-
1、快速啟動測試伺服器:直接跨過門檻學架構
2、對象容器引入和依賴注入改進:實用高逼格
3、增加門面對象:類的小助理
4、路由更對象化:又雙叒叕提速?
5、注解路由:定義路由新姿勢
6、跨域請求更簡單:漂洋過域來看你
7、引入中間件支援:分工更明确
8、搜尋器:查詢利器化繁為簡
9、生成器:緩解大資料查詢的記憶體開銷
10、資料集增強:用過都說好
11、JSON字段查詢:就是如此簡單
12、動态定義擷取器:Db類也可以用擷取器
13、數組對象查詢:既有情懷又夠貼心
14、查詢為空的改進:懶人真多
15、Swoole/Workerman支援:如虎添翼
16、驗證類改進:對象化定義驗證規則
17、配置和路由定義獨立目錄:地位提升
18、改進的日志支援:更好用了呗
總結:更新無悔,再戰五百年
1、快速啟動測試伺服器:直接跨過門檻學架構
新手伺服器環境不會搭?
pathinfo
不支援?告别這些煩惱吧,
5.1
内置了一個快速啟動測試伺服器的指令,你隻需要在指令行下切換到項目根目錄下面輸入:
php think run
即可在
localhost:8000
啟動一個測試伺服器,而無需任何其它的WEB伺服器環境,告别新手搭建環境各種問題的困惑。
相比較而言,在
5.0
中,必須使用
php -S localhost:8000 public/router.php
當然,該指令也支援指定端口和位址(域名),下面就是指定通過
tp.com
(需要自己添加host)域名的80端口通路。
php think run -H tp.com -p 80
2、對象容器引入和依賴注入改進:實用高逼格
5.1
正式引入了對象容器,可以更友善的快速存取對象和管理依賴注入。這是
5.1
基礎架構的一大調整,5.0沒有容器的概念,所有的依賴對象都在請求對象中,依賴注入雖有支援但不夠規範也不通用化。有了容器對象,所有的依賴對象都可以在容器裡面進行統一的執行個體化或者綁定,需要的時候可以直接拿出來,對于解耦和減少直接依賴很有幫助。
5.1
的應用類
think\App
本身就是容器,同時還充當了容器的管理對象,你不需要直接操作容器類就能對容器中的對象執行個體進行存取。而App類通常是在入口檔案中執行個體化的,也就是說在App類執行個體化的同時,這個容器對象就已經準備好了。
而App類本身也提供了門面方式的靜态調用,是以,你可以像下面一樣友善調用。
use think\facade\App;
// 綁定對象執行個體到容器
App::bindTo('myClass',$obj);
// 為了避免容器過大 通常隻是綁定一個類而不是對象
App::bindTo('myClass','namespace\ClassName');
// 快速擷取對象執行個體
$obj = App::make('myClass');
// 無需綁定操作即可擷取對象執行個體
$obj = App::make('namespace\ClassName');
容器對象中的執行個體預設都是單例的,如果你需要擷取新的對象執行個體,可以在make的時候指定總是重新執行個體化
// 建立一個新的對象執行個體
$obj = App::make('namespace\ClassName',true);
// 如果需要執行個體化的時候傳入參數,則使用
$obj = App::make('namespace\ClassName', ['name' => 'think'], true);
當然,這個隻是容器内部的調用機制,實際到應用層面,大多數時候容器對象執行個體的擷取是在依賴注入的時候自動完成的,是以你可能根本不需要用到上面的代碼或者說關心容器的存在。下面就是一個典型的依賴注入的例子:
<?php
namespace app\index\controller
use namespace\ClassName;
class My
{
// 調用test操作方法的時候會自動從容器中擷取ClassName對象執行個體
public function test(ClassName $class){
// 調用對象的方法或者擷取屬性
$class->fun();
}
}
ThinkPHP
5.1
沒有服務提供者的概念,如果你需要對容器中的對象進行自定義執行個體化,可以在你的對象中添加
__make
靜态方法來完成。
use think\App;
class ClassName
{
/**
* 名稱
* @var string
*/
protected $name;
/**
* 構造方法
* @access public
*/
public function __construct($name = '')
{
$this->name = $name;
}
public static function __make(App $app)
{
$name = $app['config']->get('app_name');
return new static($name);
}
}
現在當你在操作方法中依賴注入ClassName對象(或者通過容器的make方法擷取對象執行個體)的時候,就會自動調用
__make
方法進行自定義執行個體化。
正因為容器的引入,使得 5.1
的依賴注入得以更加完善,并且支援了更多的依賴注入的場景,包括控制器架構函數,操作方法,事件響應,路由定義,模型事件等等。
3、增加門面對象:類的小助理
5.1
的核心類基本上都改造成了動态類,對需要提供靜态調用的類則改為提供門面對象支援,好處是可以更好的支援單元測試,由于容器的支援而使得門面對象天生具有單例的特性。
但因為用法的改變同時也讓門面變成了更新到
5.0
最大的障礙,因為你不得不調整類庫的引入。
5.1
很典型的
5.0
中經常使用的
Route
類、
Session
類在
5.1
中類的方法本身沒有變化,隻是不再是原來的
think\Route
和
think\Session
靜态類,必須改成門面靜态代理類:
use think\facade\Route;
use think\facade\Session;
Route::rule('hello/:name','index/hello');
Session::get('user_name');
和依賴注入一樣,通過門面對象操作的時候會自動擷取容器中的對象執行個體(如果不存在的話則會自動執行個體化),是以你不用關心對象是如何執行個體化的。你操作
think\facade\Route
就和操作
think\Route
類是一個效果(除了使用的是靜态方法之外)。門面對象唯一的不足是對IDE的自動提示不夠,但可以通過給門面類添加注釋解決,系統内置的門面類均有自動提示。
4、路由更對象化:又雙叒叕提速?
5.1
的路由基本上完全重構了,但最大程度的保留(或者說相容)了
5.0
的用法,把原本的一個
Route
類拆分成獨立的多個職責明确的類庫,并且優化了路由比對的算法,而且支援路由解析的緩存,極大提升了路由的性能。
路由規則的變量用法改進
路由定義方面主要對域名路由和路由分組的功能進行了強化,以及路由規則的更靈活定義。
之前的路由規則中變量分兩種,普通變量群組合變量定義,新版把這兩種合二為一了(也就是說兩種變量沒有任何差別,僅僅是表現方式不同,而且是出于相容考慮)。你現在完全可以在路由規則中以任何方式定義路由變量。
例如你可以使用下面的路由規則而不用管目前的URL分隔符是什麼:
Route::rule('item/:name_:id', 'order/index');
Route::rule('product-<category>:name', 'product/item');
另外,新版路由定義兩種變量方式
:name
和
<name>
可以混合使用,但建議統一使用
<name>
,在性能上略有優勢(實際上,最終解析的時候系統會統一解析成後者)。
路由比對算法改進
路由檢測其實是最耗性能的,尤其是路由比對這塊,因為基本上都是采用的正則比對。在
5.0
版本之前,如果定義了100個路由,那麼最後的那個路由規則可能需要周遊100次才能正确比對到路由,而且每個路由規則中的路由變量都是單獨比對的,是以這個路由比對的性能開銷是随着路由定義的數量指數上升的。
5.1
版本系統對路由的比對這塊進行了算法優化,靈感來自于
fastRoute
。基本思想是分兩個步驟優化(思想其實很容易懂,但技術層面比較複雜,是以想了解怎麼實作的話還是仔細看代碼吧~本文隻闡述思想)。
第一個步驟是對單個路由規則的比對算法進行調整,不按照變量進行多次比對,而是把路由變量的正則合并到一起,然後整個路由規則隻比對一次(如果這個路由規則都是靜态的,那麼基本上不需要正則比對,采用的是更快的非正則檢測方式)。這個是新版預設就開啟的,相比較之前的版本,性能已經提升明顯。
但路由的性能提速遠非如此簡單,第二個步驟的優化政策是如果目前比對的路由分組下面有多個路由規則(确切的說是滿足目前請求類型的),則把這些滿足條件的路由規則合并成一個正規表達式進行路由比對。如果你的路由分組下面有100個滿足條件的路由規則,如果要通路最後的路由規則,之前的方式可能需要周遊100次,而新版隻需要進行一次比對。就算加上路由規則的合并開銷,仍然是值得的。
而且新版路由支援開啟路由緩存(僅在部署模式下有效),在定義了大量的路由規則之後,開啟該緩存可以明顯提升路由解析性能,而且路由規則越多越明顯。
由于更加對象化,新版的路由更建議采用方法定義,
5.0
的路由參數在
5.1
中都可以用鍊式方法設定,還可以享受IDE的自動提示功能。
// 給路由規則添加參數
Route::get('hello/:name','index/hello')
->ext('html')
->ajax()
->https()
->domain('thinkphp.cn');
新版一個很有用的參數是可以用
filter
方法檢測目前請求的參數是否比對
// 給路由規則添加參數
Route::get('hello/:name','index/hello')
// 隻有目前請求的type參數為vip的時候才比對路由
->filter('type', 'vip');
5、注解路由:定義路由新姿勢
5.1支援注解路由,可以在你的控制器檔案中通過注解的方式快速定義路由,在調試模式下實時生效,在部署模式下則需要運作一下指令生成注解路由。注解路由可以和路由定義檔案同時定義,并且注解路由優先。
開啟注解路由後,你隻需要直接在控制器類的方法注釋中定義(通常稱之為注解路由),例如:
<?php
namespace app\index\controller;
class Index
{
/**
* @param string $name 資料名稱
* @return mixed
* @route('hello/:name')
*/
public function hello($name)
{
return 'hello,'.$name;
}
}
就相當于注冊了一條下面的路由規則
Route::rule('hello/:name','index/hello');
預設注冊的路由規則是支援所有的請求,如果需要指定請求類型,可以在第二個參數中指定請求類型:
<?php
namespace app\index\controller;
class Index
{
/**
* @param string $name 資料名稱
* @return mixed
* @route('hello/:name','get')
*/
public function hello($name)
{
return 'hello,'.$name;
}
}
相當于注冊了一條下面的路由規則
Route::get('hello/:name','index/hello');
如果有路由參數和變量規則需要定義,可以直接在後面添加方法,例如:
<?php
namespace app\index\controller;
class Index
{
/**
* @param string $name 資料名稱
* @route('hello/:name','get')
* ->https()
* ->pattern(['name' => '\w+'])
*
* @return mixed
*/
public function hello($name)
{
return 'hello,'.$name;
}
}
就相當于注冊了一條下面的路由規則
Route::get('hello/:name','index/hello')
->https()
->pattern(['name' => '\w+']);
如果是資源路由則更為簡單,在類的開頭注釋中添加注解就行了,例如:
<?php
namespace app\index\controller;
/**
* @route('blog')
*/
class Blog
{
public function index()
{
}
public function read($id)
{
}
public function edit($id)
{
}
}
就相當于注冊了一條下面的路由規則
Route::resource('blog','blog');
6、跨域請求更簡單:漂洋過域來看你
如果某個路由或者分組需要支援跨域請求,可以使用
Route::get('new/:id', 'News/read')
->ext('html')
->allowCrossDomain();
跨域請求一般會發送一條的請求,一旦設定了跨域請求的話,不需要自己定義
OPTIONS
請求的路由,系統會自動加上。
OPTIONS
跨域請求系統會預設帶上一些Header,包括:
Access-Control-Allow-Origin:*
Access-Control-Allow-Methods:GET, POST, PATCH, PUT, DELETE
Access-Control-Allow-Headers:Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With
你可以添加或者更改Header資訊,使用
Route::get('new/:id', 'News/read')
->ext('html')
->header('Access-Control-Allow-Origin','thinkphp.cn')
->header('Access-Control-Allow-Credentials', 'true')
->allowCrossDomain();
7、引入中間件支援:分工更明确
5.1
正式引入中間件,包括路由中間件和控制器中間件。例如通過對路由分組或者路由單獨設定中間件,可以靈活的控制通路權限,并且把中間件的邏輯和你的控制器邏輯可以分離設計,最大程度的複用中間件。
中間件的執行是在控制器的操作方法執行前後(是以能替代之前的路由後置行為,控制器的初始化操作和前置操作行為,但不能替代所有的行為,這點一點要區厘清楚),是以包含前置中間件和後置中間件兩種類型,你可以根據需求定義不同的中間件。路由中間件其實就是在路由中定義好要執行哪個中間件,而控制器中間件是當你沒有使用路由的情況下,在控制器裡面直接定義要執行的中間件。
可以通過指令行快速生成一個中間件類,然後加上你的業務邏輯。
php think make:middleware CheckAuth
會自動生成一個
app\http\middleware\CheckAuth
的中間件類,然後修改
handle
方法代碼如下:
<?php
namespace app\http\middleware;
class CheckAuth
{
public function handle($request, \Closure $next)
{
echo 'before check<br/>';
$result = $next($request);
echo 'after check<br/>';
}
}
你可以在你的路由定義中指定中間件
Route::group('hello', function(){
// 定義分組路由
// 。。。
Route::get(':name', 'index/hello');
})->middleware('CheckAuth');
如果要指定多個中間件,可以使用數組的方式
Route::group('hello', function(){
// 定義分組路由
// 。。。
})->middleware(['CheckAuth', 'CheckName']);
當你沒有使用路由的情況下,可以在控制器裡面直接定義中間件,如下:
<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
protected $middleware = ['CheckAuth'];
public function index()
{
return 'index';
}
public function hello()
{
return 'hello';
}
}
如果你需要在中間件和控制器之間傳遞參數,可以通過給
Request
對象指派
<?php
namespace app\http\middleware;
class CheckAuth
{
public function handle($request, \Closure $next)
{
$request->auth = 'admin';
return $next($request);
}
}
注意,傳遞的變量名稱不要和 param
變量有沖突。
然後在控制器的方法裡面可以直接使用
public function index(Request $request)
{
return $request->auth; // admin
}
8、搜尋器:查詢利器化繁為簡
搜尋器功能對于規範和簡化資料的表單搜尋非常有效,甚至還能支援排序和多表查詢,讓你的控制器代碼減少到最低。
你不需要在控制器中或者模型的方法中使用大量繁瑣而且重複的查詢代碼,隻需要在模型類中添加類似下面的搜尋器方法,化繁為簡。
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
public function searchNameAttr($query, $value, $data)
{
$query->where('name','like', $value . '%');
}
public function searchCreateTimeAttr($query, $value, $data)
{
$query->whereBetweenTime('create_time', $value[0], $value[1]);
}
}
然後,我們可以使用下面的查詢
User::withSearch(['name','create_time'], [
'name' => 'think',
'create_time' => ['2018-8-1','2018-8-5'],
'status' => 1
])
->select();
自動會調用
name
和
create_time
字段對應的搜尋器方法完成查詢條件。
事實上,除了在搜尋器中使用查詢表達式外,還可以使用其它的任何查詢構造器以及鍊式操作。
例如,你需要通過表單定義的排序字段進行搜尋結果的排序,可以使用
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
public function searchNameAttr($query, $value, $data)
{
$query->where('name','like', $value . '%');
if (isset($data['sort'])) {
$query->order($data['sort']);
}
}
public function searchCreateTimeAttr($query, $value, $data)
{
$query->whereBetweenTime('create_time', $value[0], $value[1]);
}
}
然後,我們可以使用下面的查詢
User::withSearch(['name','create_time', 'status'], [
'name' => 'think',
'create_time' => ['2018-8-1','2018-8-5'],
'status' => 1,
'sort' => ['status'=>'desc'],
])
->select();
9、生成器:緩解大資料查詢的記憶體開銷
你可以在查詢的時候使用PHP的生成器特性,使用
cursor
查詢可以讓你在不耗費記憶體的情況下處理大量資料集結果。
$users = User::where('status', 1)->limit(10000)->curosr();
// users 是一個Generator對象
foreach($users as $user) {
// 對資料進行處理
// 。。。
}
如果不使用生成器對象,從資料庫裡面擷取1萬條資料就有可能讓記憶體暴增。
10、資料集增強:用過都說好
5.1
的模型查詢統一傳回模型對象或者包含模型的資料集對象,你可以和模型一樣操作資料集對象。并且改進了資料集對象對資料的處理能力。
其實資料集的用法和數組基本一樣,例如可以周遊和直接擷取某個元素。
// 模型查詢傳回資料集對象
$list = User::where('id', '>', 0)->select();
// 擷取資料集的數量
echo count($list);
// 直接擷取其中的某個元素
dump($list[0]);
// 周遊資料集對象
foreach ($list as $user) {
dump($user);
}
// 删除某個元素
unset($list[0]);
唯一的不同恐怕就是判斷資料集是否為空,不能直接使用
empty
判斷,而必須使用資料集對象的
isEmpty
方法判斷,例如:
$users = User::select();
if ($users->isEmpty()) {
echo '資料集為空';
}
不過通用的辦法是判斷下資料集的元素
$users = User::select();
if (count($users)==0) {
echo '資料集為空';
}
你可以使用模型的
hidden
/
visible
/
append
/
withAttr
方法進行資料集的輸出處理,例如:
// 模型查詢傳回資料集對象
$list = User::where('id', '>', 0)->select();
// 對輸出字段進行處理
$list->hidden(['password'])
->append(['status_text'])
->withAttr('name', function($value, $data) {
return strtolower($value);
});
dump($list);
如果需要對資料集的結果進行篩選和排序,可以使用
// 模型查詢傳回資料集對象
$list = User::where('status', 1)->select()
// 對資料集進行資料過濾以及排序
->where('name', 'think')
->where('score', '>', 80)
->order('create_time', 'desc');
dump($list);
還有大量的實用方法等你去挖掘~
11、JSON字段查詢:就是如此簡單
你可以像使用對象一樣來操作JSON字段,并且字段不必是JSON類型,支援varchar類型,隻要你存入的資料格式是JSON類型。
定義User模型類
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// 設定json類型字段
protected $json = ['info'];
}
定義後,寫入JSON資料。
$user = new User;
$user->name = 'thinkphp';
// 寫入JSON類型字段資料
$user->info = [
'email' => '[email protected]',
'nickname '=> '流年',
];
// 或者用對象方式
$info = new StdClass();
$info->email = '[email protected]';
$info->nickname = '流年';
$user->info = $info;
$user->save();
查詢JSON資料
$user = User::get(1);
echo $user->name; // thinkphp
echo $user->info->email; // [email protected]
echo $user->info->nickname; // 流年
查詢條件為JSON資料
$user = User::where('info->nickname','流年')->find();
echo $user->name; // thinkphp
echo $user->info->email; // [email protected]
echo $user->info->nickname; // 流年
支援設定模型的
JSON
資料傳回數組。
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// 設定json類型字段
protected $json = ['info'];
// 設定JSON資料傳回數組
protected $jsonAssoc = true;
}
設定後,查詢代碼調整為:
$user = User::get(1);
echo $user->name; // thinkphp
echo $user->info['email']; // [email protected]
echo $user->info['nickname']; // 流年
可以單獨設定JSON字段屬性的類型
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// 設定json類型字段
protected $json = ['info'];
// 設定JSON字段的類型
protected $jsonType = [
'user_id' => 'int'
];
}
沒有定義類型的屬性預設為字元串類型,是以字元串類型的屬性可以無需定義。
更新JSON資料也是類似
$user = User::get(1);
$user->name = 'kancloud';
$user->info->email = '[email protected]';
$user->info->nickname = 'kancloud';
$user->save();
12、動态定義擷取器:Db類也可以用擷取器
你可以不用在模型裡面定義擷取器方法,而是可以使用
withAttr
方法動态定義擷取器(而且适用于Db類的查詢結果)。
User::withAttr('name', function($value, $data) {
return strtolower($value);
})->select();
如果同時還在模型裡面定義了相同字段的擷取器,則動态擷取器優先,也就是可以臨時覆寫定義某個字段的擷取器。
支援對關聯模型的字段使用動态擷取器,例如:
User::with('profile')->withAttr('profile.name', function($value, $data) {
return strtolower($name);
})->select();
并且支援對
JSON
字段使用擷取器,例如在模型中定義了
JSON
字段的話:
<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
// 設定json類型字段
protected $json = ['info'];
}
可以使用下面的代碼定義JSON字段的擷取器。
User::withAttr('info.name', function($value, $data) {
return strtolower($name);
})->select();
可以在查詢之後使用
withAttr
方法。
User::select()->withAttr('name', function($value, $data) {
return strtolower($value);
});
Db類也可以支援擷取器定義。
Db::name('user')->withAttr('name', function($value, $data) {
return strtolower($value);
})->select();
上面的代碼,查詢的資料集資料中的
name
字段的值會統一進行小寫轉換。
支援對JSON字段定義擷取器。
$user = Db::name('user')
->json(['info'])
->withAttr('info.name', function($value, $data) {
return strtolower($value);
})->find(1);
dump($user);
查詢結果傳回的時候,會自動對
info
字段(
JSON
字段)的
name
屬性使用擷取器操作。
13、數組對象查詢:既有情懷又夠貼心
由于5.1的數組查詢方式改變導緻很多人不敢更新,對于習慣或者重度依賴5.0數組查詢條件的使用者來說,可以選擇數組對象查詢,該對象完成了普通數組方式查詢和系統的查詢表達式之間的橋接。
使用方法如下:
use think\db\Where;
// 這個數組條件用法完全和5.0一樣
// 差別隻是在傳入where方法的時候使用 new Where($map) 代替 $map
$map = [
'name' => ['like', 'thinkphp%'],
'title' => ['like', '%think%'],
'id' => ['>', 10],
'status' => 1,
];
// 或者先建立Where對象(數組查詢對象)
$where = new Where;
$where['id'] = ['in', [1, 2, 3]];
$where['title'] = ['like', '%php%'];
Db::table('think_user')
->where(new Where($map))
->whereOr($where->enclose())
->select();
enclose
方法表示該查詢條件兩邊會加上括号包起來。現在你可以毫不猶豫的更新到
5.1
版本而不用擔心花費大量時間重構你的查詢代碼了。
14、查詢為空的改進:懶人真多
很多新手都有一個困惑,使用find或者模型的get方法查詢的時候,都忽略要先判斷下資料是否存在,才能進行後續操作,現在友善了,你隻需要在查詢之前調用
allowEmpty
方法,或者直接使用
findOrEmpty
方法進行查詢,當查詢資料不存在的時候傳回空數組或者空的模型對象。
// 始終傳回一個User模型對象
$user = User::findOrEmpty(1024);
// 始終傳回數組,而不是null
$user = Db::name('user')->findOrEmpty(1024);
15、Swoole/Workerman支援:如虎添翼
5.1
核心調整後可以更簡單的支援
Swoole
,使用官方的擴充(
topthink/think-swoole
)的話,還可以直接通過指令行指令啟動
Swoole
服務,讓你的應用可以直接部署在
Swoole
上,進而帶來性能的再次提升。如果要在
5.0
上面支援這些,幾乎不可能或者會非常困難。
直接在指令行下啟動Swoole HTTP Server服務端。
php think swoole
啟動完成後,會在
0.0.0.0:9501
啟動一個HTTP Server,可以直接通路目前的應用。
swoole
的參數可以在應用配置目錄下的
swoole.php
裡面配置(具體參考配置檔案内容)。
如果需要使用守護程序方式運作,可以使用
php think swoole -d
支援
reload
/
stop
/
restart
等操作
php think swoole reload
并且可以支援檔案監控,項目代碼修改會自動
reload
服務,而無需手動重新開機,友善代碼調試。
如果你要啟動其它的服務(例如websocket服務),可以使用
php think swoole:server
會在
0.0.0.0:9508
啟動一個Websocket服務。
同樣通過
topthink/think-worker
擴充提供了對
workerman
和
GatewayWorker
的支援。
16、驗證類改進:對象化定義驗證規則
驗證規則的定義也可以告别數組方式,而改用對象化的方式,而且也新增了一些内置驗證規則。
$validate = new \think\Validate;
$validate->rule('age', 'number|between:1,120')
->rule([
'name' => 'require|max:25',
'email' => 'email'
]);
$data = [
'name' => 'thinkphp',
'email' => '[email protected]'
];
if (!$validate->check($data)) {
dump($validate->getError());
}
上面的寫法在5.1中可以改為對象化的方式
use think\validate\ValidateRule as Rule;
$validate = new \think\Validate;
$validate->rule('age', Rule::isNumber()->between([1,120]))
->rule([
'name' => Rule::isRequire()->max(25),
'email' => Rule::isEmail(),
]);
$data = [
'name' => 'thinkphp',
'email' => '[email protected]'
];
if (!$validate->check($data)) {
dump($validate->getError());
}
原來
5.0
的模型自動驗證已經取消了,必須改為控制器自動驗證或者使用路由驗證。總結一句話,驗證操作應該盡可能的提前。
17、配置和路由定義獨立目錄:地位提升
5.1
配置檔案和路由定義的目錄層級提升(在應用同級目錄),配置檔案支援統一管理,不用在各個子產品目錄下面尋找,但仍然支援在子產品的
config
目錄下面單獨定義,便于子產品化開發。
配置全部使用二級方式,每個配置檔案的檔案名就是一級配置名,清晰直覺,需要增加新的配置檔案直接放到配置目錄下即可,無需任何的擴充配置。如果你安裝了
Yaconf
擴充,那麼還支援使用
Yaconf
定義配置。
路由定義檔案則統一放到
route
目錄,支援分開多個檔案進行路由管理。
18、改進的日志支援:更好用了呗
5.1
的日志遵循
PSR-3
日志規範,相比較
5.0
版本,增加如下支援:
- 支援最大日志檔案數和自動清理;
- 支援單一日志檔案;
- 支援關閉目前日志寫入;
- 對指令行日志的更好支援;
- 日志可以支援JSON格式,便于各種日志分析工具,包括阿裡雲的日志管理工具。
總結:更新無悔,再戰五百年
其實上面提到的特性沒法完全涵蓋5.1的特性,尤其是路由、查詢以及模型這塊做了大量的細節改進,更多的
5.1
改進,我建議你參考下詳細的更新日志。
總結來說,版本比
5.1
版本更加規範和更接近現代化開發,是以如果你還在
5.0
和
5.0
之間猶豫不決的話,還是推薦更優秀的
5.1
版本。雖然
5.1
本身性能提升可能不至于很高,如果你大量使用路由的話,性能提升還是相當顯著的。而且益于對
5.1
和
Swoole
的支援,性能還可以提升一個層次,不過
Workerman
更新到
5.0
5.1
并不是無縫更新的,有一定工作量(官方提供了詳細的更新指導),但長期來說,這點成本仍然是值得的。最後,祝大家早日掌握5.1開發~
如果你還在選擇thinkphp 5.0的商城系統還是5.1的商城系統,我建議你還是選擇ThinkPHP 5.1架構的商淘多使用者商城系統吧。