本篇文章給大家帶來了關于php的相關知識,其中主要總結了一些筆記知識點,包括了模型、系統服務、laket-admin項目等內容,下面一起來看一下,希望對大家有幫助。
推薦學習:《php》
安裝
記得加路徑 或者(全路徑)php (全路徑)composer.phar 命令 的方式運行。避免php版本問題==
要開啟多應用,必須使用 composer require topthink/think-multi-app 安裝多應用拓展!!
這中方式啟動的是php的內置服務器 所以如果nginx設置了這個端口號 啟動不起來 。
這個僅用于測試 平常還是用nginx的好。而且可以把目錄指定為public目錄,這樣直接 ip:1000 就能訪問到了 。但是會不會php使用info的時候 根目錄出錯?
立即學習“PHP免費學習筆記(深入)”;
另外安裝composer的時候 不要要從小皮面板安裝 坑貨······
【
且需要更改php命令行的版本 或者好像cURL -sS https://getcomposer.org/installer | php 這個命令改最后一個參數為安裝路徑就行?
然后php8.0要安裝zip拓展 直接小皮面板會報錯 要手動安裝 ==都是坑
】不用小皮就不會遇到這些問題!
大坑==
phpstudy 網站那 要關了open_dir 防止跨站攻擊的 不然設置public目錄為 網站根目錄后 就訪問不到外面的
如果php_ini中設置了 也關了 或者設置下正常目錄
nginx中 和fastcgi.conf里可能也有這個設置
然后 要開啟php的
display_Errors = On
display_startup_errors = On
默認是不開啟的==
這個 即使沒開 框架也能報錯 可能是因為設置了iniset的 但是框架要正常啟動了才有效。否則比如遇到的500錯誤 框架根本沒啟動起來 自然也就顯示不了報錯了
另外 如果是拷貝的文件 權限可能也要設置下 為755
env也要開啟debug
然后runtime目錄設置為777
基礎
錯誤顯示
除了上面的大坑外,一般是設置env
配置
[DATABASE]USERNAME = rootPASSWORD = 123456
use thinkfacadeEnvfunction(){// 獲取環境變量 如果不存在則使用默認值rootEnv::get('database.username', 'root');}
應用目錄
輸出
數組不能直接用return
控制器
兩個特殊的控制器
一. 基礎控制器
- 一般來說,創建控制器后,推薦繼承基礎控制器來獲得更多的方法;
- 基礎控制器僅僅提供了控制器驗證功能,并注入了thinkApp和thinkRequest;
- 這兩個對象后面會有章節詳細講解,下面我們繼承并簡單使用一下;
二. 空控制器
-
namespace?appcontroller; ?use?appBaseController; ?class?Test?extends?BaseController ?{ ?public?function?index() ?{ ?//返回實際路徑 ?return?$this->app->getBasePath(); ?//返回當前方法名 ?return?$this->request->action(); ?} ?}
- 在單應用模式下,我們可以給項目定義一個 Error 控制器類,來提醒錯誤;
-
class?Error ?{ ?public?function?index() ?{ ?return?‘當前控制器不存在!’; ?} ?}
模型
游標的意義
驗證器
使用
例如, 在 TP3 的時候, 可能是這樣判斷的:
$name = I('name', '');if (empty($name)) { // 拋出異常}
如果參數比較多的時候, 需要判斷的變量越多代碼量也隨著增加. 如果使用驗證器就會好很多.
驗證器的官方文檔: https://www.kancloud.cn/manual/thinkphp6_0/1037624
直接上代碼:
<?php namespace appapicontroller; use thinkfacadeValidate;use thinkRequest; class Auth{ public function index(Request $request) { $input = $request->post(); $validate = Validate::rule([ 'name|名稱' => 'require|max:25', 'email|郵箱' => 'require|email' ]); if (!$validate->check($input)) { return $validate->getError(); } }}
驗證的好處
主要是 重復使用 而且直接輸出錯誤信息 避免重復寫代碼
系統服務
使用系統服務有大大的好處和避免了直接修改類的壞處。從以上分析來看,個人覺得,使用系統服務,可以對一個類進行非入侵式的「配置」,如果哪天一個類的某些設定需要修改,我們不用直接修改這個類,只需要修改服務提供類就好了。對于擴展包來說,系統服務使其可以在擴展中靈活配置程序,達到開箱即用的效果。不過,有個缺點是系統服務類都要在程序初始化是進行實例化,如果一個系統的服務類很多,勢必影響程序的性能。
使用 thinkphp 開發網站,在沒有 thinkphp6 版本出來以前,常規的開發模式都是使用它自帶的多應用開發方式來進行項目開發。
多應用開發的一個好處就是開發方便和快速,只需要在thinkphp規定的app目錄建立一個目錄,比如 admin 目錄,然后在其內建立一個 controller 目錄就可以開始一個項目的基本開發了。
然而這樣開發只適合基于它本身的目錄進行開發,如果想要把項目做成一個包來開發和發布,這樣的方式明顯不行。
而這次,thinkphp6 引入了 Service 的概念,增加了項目轉移到包開發的可能性。
Service 的使用需要繼承 thinkService ,同時 Service 默認的 register 和 boot 這兩個方法是非必須的,就是說可以不用添加也是可以的。
但是,我們使用 Service 就是為了在項目啟動前添加自己的配置和注冊一些自己的東西,所以這兩個方法對項目開發來說,都利用起來是最好的方法。
register的使用
register 的加載要先于 boot 方法,也同時在系統里屬于提前注冊一些具體的配置及綁定類,所以在具體的項目開發中,也是推薦只做一些項目的配置。
Service 的引入會根據 thinkphp6 生成的 Services.php 緩存順序進行加載,所以在使用過程中需要注意當前的 Service 在緩存中屬于哪個位置,防止在注冊配置時候出現配置加載時出現不可知的問題。
boot 的使用
boot 通常是在 register 注冊完成后進行加載,boot 方法里推薦做一些對 register 注冊完成后的信息的補充處理。
thinkphp6 由于在 boot 前已做了系統配置的初始化操作,所以在這里處理一些數據庫操作也是沒有問題的。
Service 的其他方法
loadRoutesFrom :導入路由,傳入數據為匿名函數
registerRoutes :功能于 loadRoutesFrom 一樣
commands :導入腳本命令,傳入數據為數組或者單個腳本
使用 Service 的場景
如果你想要把一個項目獨立成一個包進行發布或者為 thinkphp6 提供擴展包。
如果只是單純的想做一個 app 項目,Service 估計不太適合你。
最后,Service 的具體實踐有沒有什么好的項目推薦啊,那當然有的,這里隆重推薦一個完全使用 Service 開發的項目:
laket-admin: https://github.com/deatil/laket-admin
laket-admin 使用 thinkphp6 的 Service 模式加單應用開發而成,避開了 thinkphp6 多應用下 url 出現的一些問題,對用戶端的 url 更加友好。
laket-admin項目的截圖
為什么halt
依賴注入與容器
依賴注入其實本質上是指對類的依賴通過構造器完成自動注入,例如在控制器架構方法和操作方法中一旦對參數進行對象類型約束則會自動觸發依賴注入,由于訪問控制器的參數都來自于URL請求,普通變量就是通過參數綁定自動獲取,對象變量則是通過依賴注入生成。
如何注入
首先是構造器注入
api/manager/TestMgr.php
namespace appapimanager;class TestMgr{ public string $name1 = 'a';}
api/controller/Test.php
class Test{ public function __construct(TestMgr $testMgr){ $this->testMgr=$testMgr; } public function index() { return $this->testMgr->name1; //輸出a //same as $a=new TestMgr();return $a->name; }
構造器方法注入的解析
如果換成我們手動調用的方式,那么正常的流程應該是
$testMgr = new TestMgr();//多出來了這一步 要先實例化TestMgr$test = new Test($testMgr);$test->index($testMgr);
然而 瀏覽器直接調用的方式是 ,因為 正常情況下 不可能我們接口調用 還去 先new一堆東西吧
$test = new Test();$test->index($testMgr);
但這樣肯定會報錯 因為 構造器有參數 但是你沒傳。所以我們不能直接這么寫,要寫成上面那種自動注入的參數的形式。而事實上 我們也可以通過invoke函數來完成遞歸實例化這一操作。
所以,相當于容器自動幫我們完成了這個操作。我們要做的 只是在方法的參數中寫需要的那個類的即可 不需要去手動去new底層的一堆對象
方法調用的方式
api/manager/TestMgr.php
namespace appapimanager;class TestMgr{ public string $name1 = 'a';}
api/controller/Test.php
namespace appapicontroller;use appapimanagerTestMgr;class Test{ public function index(TestMgr $testMgr) { return $testMgr->name1;//1 }}
invoke
//使用容器來實例化的話,可以自動進行依賴注入。invoke(類名)//某個方法依賴注入invoke(['類名','方法名'])
$bar = new Bar(); $foo = new Foo($bar);等價于$foo = invoke('Foo');
也支持對某個函數或者閉包使用依賴注入
$result = invoke(function(Bar $bar) { // ...});
上面的實現——-容器
什么是容器
ThinkPHP使用容器來更方便的管理【類依賴】及【運行依賴注入】
簡而言之,容器內部是通過反射類或閉包等來實現類的實例化(單例)。
容器并非只能用于依賴注入
//官方說明:容器中已經調用過的類會自動使用單例,除非你使用下面的方式強制重新實例化。
// 每次調用都會重新實例化->$cache = app(‘user’,true);
app助手函數
$arrayItem = app(‘orgutilsArrayItem’);
上述代碼會判斷在容器中是否存在這個單例,如果有就直接返回,沒有就幫我們自動創建一個這個類的單例然后返回。
比如:
echo app(‘user’)->name;
注釋:new是寫死的 而上面是字符串 可以動態解析的!!
app和invoke這兩個助手函數的區別
app 快速獲取容器中的實例 支持依賴注入
invoke 調用反射執行callable 支持依賴注入
bind
依賴注入的類統一由容器進行管理,大多數情況下是在自動綁定并且實例化的。不過你可以隨時進行手動綁定類到容器中(通常是在服務類的register方法中進行綁定),支持多種綁定方式。
bind就是給實例起一個別名 方便app快速調用
// 綁定類庫標識bind('user','appindexmodelUser');// 快速調用(自動實例化)echo app('user')->name;
更多bind的用法看手冊
ps:bind 實際上是$this->app->bind(‘thinkCache’, ‘appcommonCache’);的快捷調用
也叫助手函數
provider.php
一般來說,bind只能在定義的那個地方用,其他地方就用不了了。所以,為了其他地方也能用,我們將bind函數寫在provider.php文件中
容器的好處
容器:【“拿來即用”,不需要通過實例化,松耦,節約資源】
容器自動依賴注入
容器主要用于依賴注入,依賴注入會首先檢查容器中是否注冊過該對象實例,如果沒有就會自動實例化,然后自動注入
自定義實例化
其他
場景
支持使用依賴注入的場景包括(但不限于):
控制器架構方法;
控制器操作方法;
路由的閉包定義;
事件類的執行方法;
中間件的執行方法;
門面 face就大量使用了依賴注入
Facade 門面模式
看設計模式那個文檔。
tp中,說的直白一點,Facade功能可以讓類無需實例化而直接進行靜態方式調用。使用靜態方式調用非靜態方法時隱式的實例化了該類,無需額外的實例化工作(看最下面總結 因為要實例化的可能很多個)。
簡單來說 就是request實際上是用依賴注入的方式寫的,所以需要實例化一大堆。所以要么使用門面模式 要么使用自動依賴注入的方式調用!
facade目錄 和外面是對應的
推薦學習:《php》