1. 程式人生 > >從ThinkPHP3.2.3到ThinkPHP5.0過渡筆記

從ThinkPHP3.2.3到ThinkPHP5.0過渡筆記

用tp3.2.3做了不少專案,但是畢竟要與時代接軌,學習一些新的框架,從tp5開始!

以下記錄一些學習中遇到的問題及解決辦法,還有tp3.2和tp5.0的一些區別,適合給用過tp3沒用過tp5的童鞋做個參考。

隨著學習不斷更新......

+++++++++++++++++++++++分割線總是要有的+++++++++++++++++++++++

首先到tp官網下載了一個最新的ThinkPHP5.0.22完整版:

直接扔到了伺服器上,解壓後目錄結構如下:

目錄結構整體與tp3.2大同小異,資料夾首字母小寫了,應用入口檔案 在根目錄下 public/index.php

,官方文件對public資料夾定義為WEB部署目錄(對外訪問目錄):

配置伺服器域名解析的時候需要把專案根目錄指向/public:

<VirtualHost *:80>
    ServerAdmin [email protected]
    DocumentRoot /var/www/tp/public
    ServerName tp.oyhdo.com
    ServerAlias  tp.oyhdo.com
    DirectoryIndex index.php index.html index.htm    
</VirtualHost>

根目錄下 application/config.php 

為應用(公共)配置檔案,設定一些常用的配置,以下簡稱為“配置檔案”:

訪問網址如下:

訪問tp.oyhdo.com等同於訪問tp.oyhdo.com/index.php/index/Index/index(預設不區分大小寫)

即預設模組index,預設控制器Index,預設操作index

配置檔案修改分別為default_moduledefault_controllerdefault_action

如果需要強制區分url大小寫,修改 url_convert 為false:

配置檔案中設定 app_debug 為true,開啟應用除錯模式,以便開發除錯:

【隱藏url中的index.php入口檔案】

以Apache伺服器為例,首先確認Apache配置檔案httpd.conf中開啟了mod_rewrite.so模組:

然後把所有【AllowOverride】設為All:

 最後修改根目錄下 public/.htaccess 檔案內容為:

<IfModule mod_rewrite.c>
    Options +FollowSymlinks -Multiviews
    RewriteEngine on

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
</IfModule>

去掉index.php也可訪問:

【隱藏前臺url模組名】 

把index模組作為前臺,在前臺新建了一個User控制器:

<?php
namespace app\index\controller;

class User
{
    public function user()
    {
        return '這是User控制器的user操作';
    }
}

 正常需要這樣訪問User控制器的user操作:

 為了前臺url顯示簡潔一些,要去掉模組名index,然後就崩了:

如果只有一個模組,可以在 /application/common.php 中新增:

// 綁定當前訪問到index模組
define('BIND_MODULE','index');

親測訪問成功:

但是專案通常會有前後臺的區分,至少兩個模組, 用上面的方法繫結index模組後,再訪問其它模組就會報錯:

(新建了一個admin模組作為後臺)

<?php
namespace app\admin\controller;

class Index
{
    public function index()
    {
        return '這是後臺首頁';
    }
}

 

對於多模組的情況,可以在 /application/route.php 中繫結預設模組路由(去掉上面的單模組繫結):

use think\Route;
Route::bind('index');

前臺訪問成功:

 然後在/public/下新建一個入口檔案admin.php,繫結後臺模組admin,來訪問後臺:

<?php
// [ 應用入口檔案 ]
namespace think;
// 定義應用目錄
define('APP_PATH', __DIR__ . '/../application/');
// 載入框架引導檔案
require __DIR__ . '/../thinkphp/base.php';
// 綁定當前入口檔案到admin模組
Route::bind('admin');
// 關閉admin模組的路由
App::route(false);
// 執行應用
App::run()->send();

後臺訪問成功:

(修改後臺地址只需修改這個檔名即可)
 

【返回資料】

配置檔案中預設輸出型別 default_return_type 為html:

 直接列印輸出字串、陣列,沒什麼特殊:

public function index()
{
    $str = 'hello,world!';
    $arr = array('state'=>1,'msg'=>'success');

    //列印字串
    echo $str;

    //列印陣列
    var_dump($arr);
}

返回json格式資料:

public function index()
{
   $arr = array('state'=>1,'msg'=>'success');
   return json($arr);
   
   //返回其它狀態碼或響應頭資訊
   //return json($arr, 201, ['Cache-control' => 'no-cache,must-revalidate']);

   //xml格式
   //return xml($arr);
}

(對於只做API開發的情況,可以設定default_return_type為json,直接return $arr即可返回json格式資料)
 

【渲染模板、分配資料】

如圖建立檢視層,index.html作為前臺首頁(內容為“這是首頁”):

tp3渲染模板直接在控制器裡$this->display(),tp5並不支援。

tp5渲染模板,在控制器中繼承think\Controller類,使用 return $this->fetch() 或者使用助手函式 return view()

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
    public function index()
    {
        return $this->fetch();
        //return view();
    }
}

tp5分配資料的方式依舊使用 $this->assign()

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
    public function index()
    {
    	$name = 'lws';
        $this->assign('name',$name);
        return $this->fetch();
    }
}

index.html頁面讀取資料:

{$name}

(修改模板引擎標籤 配置檔案【tpl_begin】、【tpl_end】)


【繼承父類控制器】

寫一個栗子,新建一個Base控制器作為父類控制器,Index控制器繼承Base控制器

在父類控制器中初始化分配資料,子類控制器渲染模板:

Base.php:

<?php
namespace app\index\controller;
use think\Controller;
class Base extends Controller
{    
    //初始化方法
    public function _initialize()
    {	
    	$haha = '快下班了';
        $this->assign('haha',$haha);
    }
}

Index.php:

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Base
{
    public function index()
    {
        return $this->fetch();
    }
}

index.html:

{$haha}

(與tp3.2相比,父類控制器不能是Public控制器) 


【配置引數】

tp3.2裡面使用C方法設定、獲取配置引數

tp5使用助手函式 config() 設定、獲取配置引數:

//配置一個引數
config('name','lws');

//批量配置引數
config([
    'info'=>['sex'=>'nan','aihao'=>'nv']
]);

//獲取一個配置引數
echo config('name');

//獲取一組配置引數
dump(config('info'));

//獲取一個二級配置引數
echo config('info.sex');

【get傳參】

tp5廢除了url/引數名1/引數值1/引數名2/引數值2......這樣的方式傳參,還是老老實實用url?引數名1=引數值1&引數名2=引數值2......這樣傳吧。

控制器裡列印$_GET:

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
    public function index()
    {
        $getdate = $_GET;
        dump($getdate);	
    }
}

 這樣是不對滴:

這樣就好使:

【安全獲取變數】 

tp3.2可以使用I方法安全獲取get、post等系統輸入變數

tp5中使用助手函式 input()

//獲取get變數
$data1 = input('get.name');

//獲取post變數
$data2 = input('post.name');

//獲取當前請求變數
$data3 = input('param.name');

//獲取request變數
$data4 = input('request.name');

//獲取cookie變數
$data5 = input('cookie.name');

//獲取session變數
$data6 = input('session.name');

//獲取上傳檔案資訊
$data7 = input('file.image');

(注意:獲取的資料為陣列,要加上 /a 修飾符才能獲取到)

$arr = input('post.arr/a');

可以在配置檔案中設定全域性過濾方法:

// 預設全域性過濾方法 用逗號分隔多個
'default_filter'         => 'htmlspecialchars',

【資料庫操作】

tp5的資料庫配置檔案在根目錄 /application/database.php:(也可在模組下單獨配置)

連線資料庫:tp3.2支援M方法連線資料庫,tp5使用 Db類 或 助手函式db()

查詢資料:依舊使用 find()select() 方法,查詢一個欄位使用 value() 方法代替getField()

//查詢一條
$artinfo = db('article')->find();

//查詢全部
$artinfo = db('article')->select();

//查詢一個欄位
$artinfo = db('article')->value('article_title');

新增資料:tp3.2使用add(),tp5使用 insert():返回插入條數  或  save():返回id

//新增一條資料
$data['article_title'] = 'PHP是世界上最好的語言';
$data['article_content'] = '如題';
db('article')->insert($data);
//或 db('article')->save($data);
//新增多條資料
$data = [
    ['article_title' => '標題1', 'article_content' => '內容1'],
    ['article_title' => '標題2', 'article_content' => '內容2'],
    ['article_title' => '標題3', 'article_content' => '內容3']
];
db('article')->insertAll($data);

修改資料:tp3.2使用save(),tp5使用 update()

//修改資料
$whe['article_id'] = 1;
$data['article_title'] = '修改後的標題';
db('article')->where($whe)->update($data);

刪除資料:沒錯還是 delete()

//刪除資料
$whe['article_id'] = 1;
db('article')->where($whe)->delete();

db()助手使用起來比較方便,但每次都會重新連線資料庫,因此應當儘量避免多次呼叫,建議還是使用Db類操作資料庫。

Db類操作原生SQL:

<?php
namespace app\index\controller;
use think\Db;
class Index {
    public function index() {
        // 插入記錄
        $res = Db::execute('insert into lws_article (title ,content) values ("標題", "內容")');
	
        // 刪除資料
        $res = Db::execute('delete from lws_article where art_id = 1 ');

        // 更新記錄
        $res = Db::execute('update lws_article set title = "修改標題" where art_id = 1 ');

        // 查詢資料
        $res = Db::query('select * from lws_article where art_id = 1');

        // 顯示資料庫列表
        $res = Db::query('show tables from blog');

        // 清空資料表
        $res = Db::execute('TRUNCATE table lws_article');
    }
}

Db類操作查詢構造器:

<?php
namespace app\index\controller;
use think\Db;
class Index {
    public function index() {
	// 查詢資料(資料庫沒有配置表字首)
	$res = Db::table('lws_article')
	    ->where('art_id', 1)
	    ->select();

	//以下為資料庫配置了表字首	

	// 插入記錄
	$res = Db::name('article')
		->insert(['title' => '標題', 'content' => '內容']);

	// 更新記錄
	$res = Db::name('article')
		->where('art_id', 1)
		->update(['title' => "修改標題"]);

	// 查詢資料
	$res = Db::name('article')
		->where('art_id', 1)
		->select();

	// 刪除資料
	$res = Db::name('article')
		->where('art_id', 1)
		->delete();
    
        //鏈式操作舉例
        $artlist = Db::name('article')
	        ->where('is_del', 'N')
	        ->field('id,title,content')
	        ->order('post_time', 'desc')
	        ->limit(10)
	        ->select();
    }  
}

【切換資料庫】

首先在資料庫配置中配置多個數據庫:

// 資料庫配置1
'db1' => [
	// 資料庫型別
	'type' => 'mysql',
	// 伺服器地址
	'hostname' => '127.0.0.1',
	// 資料庫名
	'database' => 'blog1',
	// 資料庫使用者名稱
	'username' => 'root',
	// 資料庫密碼
	'password' => '123456',
	// 資料庫連線埠
	'hostport' => '',
	// 資料庫連線引數
	'params' => [],
	// 資料庫編碼預設採用utf8
	'charset' => 'utf8',
	// 資料庫表字首
	'prefix' => 'lws_',
],
// 資料庫配置2
'db2' => [
	// 資料庫型別
	'type' => 'mysql',
	// 伺服器地址
	'hostname' => '127.0.0.1',
	// 資料庫名
	'database' => 'blog2',
	// 資料庫使用者名稱
	'username' => 'root',
	// 資料庫密碼
	'password' => '',
	// 資料庫連線埠
	'hostport' => '',
	// 資料庫連線引數
	'params' => [],
	// 資料庫編碼預設採用utf8
	'charset' => 'utf8',
	// 資料庫表字首
	'prefix' => 'lws_',
],

使用connect方法切換資料庫:

<?php
namespace app\index\controller;
use think\Db;
class Index {
    public function index() {
        $db1 = Db::connect('db1');
        $db2 = Db::connect('db2');
        $db1->query('select * from lws_article where art_id = 1');
        $db2->query('select * from lws_article where art_id = 2');
    }
}

【系統常量】

tp5廢除了一大堆常量:

REQUEST_METHOD   IS_GET 
IS_POST          IS_PUT 
IS_DELETE        IS_AJAX 
__EXT__          COMMON_MODULE 
MODULE_NAME      CONTROLLER_NAME 
ACTION_NAME      APP_NAMESPACE 
APP_DEBUG        MODULE_PATH等

需要使用的常量可以自己定義,例如IS_GET、IS_POST

我在父類的初始化方法中定義了這兩個常量:

<?php
namespace app\index\controller;
use think\Controller;
class Base extends Controller
{
    public function _initialize()
    {	
    	define('IS_GET',request()->isGet());
        define('IS_POST',request()->isPost());
    }
}

然後在子類控制器中就可以使用這個常量做一些判斷:

<?php
namespace app\index\controller;
class Index extends Base
{
    public function index()
    {   
        if(IS_POST){
            echo 111;
        }else{
            echo 222;
        }
    }
}

【定義路由】

例如一篇部落格詳情頁,原來的網址為:http://oyhdo.com/home/article/detial?id=50,即home模組下的article控制器下的detial操作方法,傳遞引數id。

在路由配置檔案 application/route.php 中新增路由規則:

return [
    'article/:id' => 'home/article/detial',
];

或者使用 Route 類,效果一樣: 

use think\Route;
Route::rule('article/:id','home/article/detial');

定義路由規則之後訪問http://oyhdo.com/article/50即可


 【url分隔符的修改】

修改 application/config.php 中的 pathinfo_depr

// pathinfo分隔符
    'pathinfo_depr'          => '-',

訪問網址變為:http://oyhdo.com/article-50


【跳轉、重定向】

tp3裡面的正確跳轉:$this->success()、錯誤跳轉:$this->error()、重定向:$this->redirect(),在tp5裡面同樣適用(繼承\think\Controller)

tp5新增 redirect() 助手函式用於重定向:

return redirect('https://www.oyhdo.com');