# 快速入門(十):命令行工具
`ThinkPHP5.0`開始增加了一個命令行工具`think`,并且內置了一些指令,可以幫助開發者在開發或者運維階段執行一些指令,本章我們來了解下命令行工具的使用和指令開發。
- - [查看指令](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u67E5u770Bu6307u4EE4)
- [生成模塊](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u751Fu6210u6A21u5757)
- [生成文件](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u751Fu6210u6587u4EF6)
- [生成類庫映射文件](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u751Fu6210u7C7Bu5E93u6620u5C04u6587u4EF6)
- [生成路由緩存文件](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u751Fu6210u8DEFu7531u7F13u5B58u6587u4EF6)
- [指令擴展示例](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u6307u4EE4u6269u5C55u793Au4F8B)
- [命令行調試](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u547Du4EE4u884Cu8C03u8BD5)
- [命令行顏色支持](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u547Du4EE4u884Cu989Cu8272u652Fu6301)
- [調用命令](http://www.hmoore.net/thinkphp/thinkphp5_quickstart/176628#u8C03u7528u547Du4EE4)
## 查看指令
> 命令行工具需要在命令行下面執行,請先確保你的`php.exe`已經加入了系統環境變量。
應用的命令行入口文件是應用根目錄的`think`文件,其內容如下:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 定義項目路徑</span>
define(<span class="hljs-string">'APP_PATH'</span>, <span class="hljs-string">'./application/'</span>);
<span class="hljs-comment">// 加載框架命令行引導文件</span><span class="hljs-keyword">require</span> <span class="hljs-string">'./thinkphp/console.php'</span>;
```
```
> 你也可以自定義`think`文件,更改應用目錄。
要執行命令,首先進入命令行,并切換當前目錄到應用的根目錄(也就是`think`文件所在目錄)下面,執行:
```
<pre class="calibre18">
```
<span class="hljs-title">php</span> think
```
```
會顯示當前支持的所有指令:
```
<pre class="calibre18">
```
>php think
Think Console version <span class="hljs-number">0.1</span><span class="hljs-regexp">Usage</span>:
command [options] [arguments]
<span class="hljs-regexp">Options</span>:
-h, --help Display <span class="hljs-keyword">this</span> help message
-V, --version Display <span class="hljs-keyword">this</span> <span class="hljs-number">console</span> version
-q, --quiet Do <span class="hljs-keyword">not</span> output any message
--ansi Force ANSI output
--<span class="hljs-number">no</span>-ansi Disable ANSI output
-n, --<span class="hljs-number">no</span>-interaction Do <span class="hljs-keyword">not</span> ask any interactive question
-v|vv|vvv, --verbose Increase the verbosity <span class="hljs-keyword">of</span> <span class="hljs-regexp">messages</span>: <span class="hljs-number">1</span> <span class="hljs-keyword">for</span> normal output, <span class="hljs-number">2</span> <span class="hljs-keyword">for</span> more verbose output <span class="hljs-keyword">and</span> <span class="hljs-number">3</span> <span class="hljs-keyword">for</span> debug
Available <span class="hljs-regexp">commands</span>:
build Build Application Dirs
help Displays help <span class="hljs-keyword">for</span> a command
list Lists commands
make
<span class="hljs-regexp">make</span>:controller Create a <span class="hljs-keyword">new</span> controller <span class="hljs-operator"><span class="hljs-keyword">class</span></span><span class="hljs-regexp">make</span>:model Create a <span class="hljs-keyword">new</span> model <span class="hljs-operator"><span class="hljs-keyword">class</span></span>
optimize
<span class="hljs-regexp">optimize</span>:autoload Optimizes PSR0 <span class="hljs-keyword">and</span> PSR4 packages to be loaded with classmaps too, good <span class="hljs-keyword">for</span> production.
```
```
> #### 注意
>
> - - - - - -
>
> 在win10的周年版中運行會出現亂碼,請使用`PowerShell`運行。
使用
```
<pre class="calibre18">
```
>php think <span class="hljs-keyword">list</span>
```
```
可以獲得相同的結果。
如果輸入一個不存在的指令,系統會自動搜索相關的指令并提示,例如:
```
<pre class="calibre18">
```
>php think <span class="hljs-number">make</span>
```
```
會顯示

## 生成模塊
下面我們給應用生成一個新的模塊`test`,首先需要在`application`目錄下面創建一個`build.php`定義文件,文件內容如下:
```
<pre class="calibre18">
```
<span class="hljs-keyword">return</span> [
<span class="hljs-comment">// 定義test模塊的自動生成</span><span class="hljs-string">'test'</span> => [
<span class="hljs-string">'__dir__'</span> => [<span class="hljs-string">'controller'</span>, <span class="hljs-string">'model'</span>, <span class="hljs-string">'view'</span>],
<span class="hljs-string">'controller'</span> => [<span class="hljs-string">'User'</span>, <span class="hljs-string">'UserType'</span>],
<span class="hljs-string">'model'</span> => [<span class="hljs-string">'User'</span>, <span class="hljs-string">'UserType'</span>],
<span class="hljs-string">'view'</span> => [<span class="hljs-string">'index/index'</span>, <span class="hljs-string">'index/test'</span>],
],
];
```
```
然后在命令行下面,執行:
```
<pre class="calibre18">
```
>php think build
Successed
```
```
如果顯示Successed則表示生成成功。
> 注意,命令行指令是區分大小寫的,所以如果執行
>
> ```
> <pre class="calibre25">
> ```
> >php think Build
> ```
>
> ```
>
> 會報錯。
我們可以看到`application`目錄下面已經生成了一個`test`模塊目錄,包括下面的子目錄及文件:
```
<pre class="calibre18">
```
<span class="hljs-regexp">test</span>
├─<span class="hljs-regexp">controller</span>
│ ├─<span class="hljs-regexp">Index</span><span class="hljs-regexp">.php</span>
│ ├─<span class="hljs-regexp">User</span><span class="hljs-regexp">.php</span>
│ └─<span class="hljs-regexp">UserType</span><span class="hljs-regexp">.php</span>
├─<span class="hljs-regexp">model</span>
│ ├─<span class="hljs-regexp">User</span><span class="hljs-regexp">.php</span>
│ └─<span class="hljs-regexp">UserType</span><span class="hljs-regexp">.php</span>
├─<span class="hljs-regexp">view</span>
│ └─<span class="hljs-regexp">index</span>
│ ├─<span class="hljs-regexp">index</span><span class="hljs-regexp">.html</span>
│ └─<span class="hljs-regexp">test</span><span class="hljs-regexp">.html</span>
├─<span class="hljs-regexp">common</span><span class="hljs-regexp">.php</span>
└─<span class="hljs-regexp">config</span><span class="hljs-regexp">.php</span>
```
```
接下來,我們可以訪問
```
<pre class="calibre18">
```
<span class="hljs-string">http:</span>
<span class="hljs-comment">//tp5.com/test/</span>
```
```
會顯示:

我們在`build.php`文件中并沒有定義`Index`控制器,但仍然生成了一個默認的`Index`控制器文件以及歡迎頁面,這是為了避免模塊訪問出錯。
## 生成文件
還可以用`make`指令單獨生成某個應用類庫文件,例如:
```
<pre class="calibre18">
```
php think make:controller <span class="hljs-number">test</span>/B<span class="hljs-number">log</span>
```
```
會自動為test模塊生成一個 Blog控制器文件。
> 注意,默認生成的控制器類是屬于資源控制器,并且繼承了\\think\\Controller。
如果希望生成一個空的控制器,可以使用
```
<pre class="calibre18">
```
php think make:controller <span class="hljs-number">test</span>/B<span class="hljs-number">log</span> --plain
```
```
又或者生成一個模型文件
```
<pre class="calibre18">
```
php think make:model <span class="hljs-number">test</span>/B<span class="hljs-number">log</span>
```
```
## 生成類庫映射文件
在生成類庫文件之后,我們強烈建議使用命令行生成類庫映射文件,可以提高自動加載的性能,用法如下:
```
<pre class="calibre18">
```
>php think optimize:<span class="hljs-number">autoload</span>
```
```
執行完畢,會在`RUNTIME_PATH`目錄下面生成一個`classmap.php`文件,包括了系統和應用的所有類庫文件的映射列表。
## 生成路由緩存文件
如果你的應用定義了大量的路由規則,那么建議在實際部署后生成路由緩存文件,可以免去路由注冊的開銷,從而改善路由的檢測效率,用法如下:
```
<pre class="calibre18">
```
>php think <span class="hljs-string">optimize:</span>route
```
```
執行完畢,會在`RUNTIME_PATH`目錄下面生成一個`route.php`文件,包括了應用的所有路由規則定義列表。
> #### 注意
>
> - - - - - -
>
> 路由緩存文件只會緩存在application/route.php文件中配置和動態注冊的路由規則,因此請確保你沒有在其它的文件中進行路由的注冊。
## 指令擴展示例
命令行的作用遠不止生成文件這么簡單,同時應用也可以很方便的擴展自己的指令,我們來擴展一個用于清理緩存目錄的指令`clear`。
> #### 注意
>
> - - - - - -
>
> 最新版本已經內置`clear`指令了,下面的示例可以直接使用內置的`clear`指令進行學習和測試。
首先,我們創建一個指令類 `app\console\Clear`,內容如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">console</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">console</span>\<span class="hljs-title">command</span>\<span class="hljs-title">Command</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">console</span>\<span class="hljs-title">Input</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">console</span>\<span class="hljs-title">input</span>\<span class="hljs-title">Option</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">console</span>\<span class="hljs-title">Output</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Clear</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Command</span></span>{
<span class="hljs-keyword">protected</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">configure</span><span class="hljs-number">()</span></span>{
<span class="hljs-comment">// 指令配置</span><span class="hljs-regexp">$this</span>
->setName(<span class="hljs-string">'clear'</span>)
->addOption(<span class="hljs-string">'path'</span>, <span class="hljs-string">'d'</span>, Option::VALUE_OPTIONAL, <span class="hljs-string">'path to clear'</span>, <span class="hljs-keyword">null</span>)
->setDescription(<span class="hljs-string">'Clear runtime file'</span>);
}
<span class="hljs-keyword">protected</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">execute</span><span class="hljs-number">(Input <span class="hljs-regexp">$input</span>, Output <span class="hljs-regexp">$output</span>)</span></span>{
<span class="hljs-regexp">$path</span> = <span class="hljs-regexp">$input</span>->getOption(<span class="hljs-string">'path'</span>) ?: RUNTIME_PATH;
<span class="hljs-regexp">$files</span> = scandir(<span class="hljs-regexp">$path</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$files</span>) {
<span class="hljs-keyword">foreach</span> (<span class="hljs-regexp">$files</span> <span class="hljs-keyword">as</span> <span class="hljs-regexp">$file</span>) {
<span class="hljs-keyword">if</span> (<span class="hljs-string">'.'</span> != <span class="hljs-regexp">$file</span> && <span class="hljs-string">'..'</span> != <span class="hljs-regexp">$file</span> && is_dir(<span class="hljs-regexp">$path</span> . <span class="hljs-regexp">$file</span>)) {
array_map(<span class="hljs-string">'unlink'</span>, glob(<span class="hljs-regexp">$path</span> . <span class="hljs-regexp">$file</span> . <span class="hljs-string">'/*.*'</span>));
} <span class="hljs-keyword">elseif</span> (is_file(<span class="hljs-regexp">$path</span> . <span class="hljs-regexp">$file</span>)) {
unlink(<span class="hljs-regexp">$path</span> . <span class="hljs-regexp">$file</span>);
}
}
}
<span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"Clear Successed"</span>);
}
}</span>
```
```
> 一個合法的指令類,沒有固定的目錄和命名空間要求,但必須繼承`think\console\command\Command`或者其子類,并且定義`configure`和`execute`兩個方法。
然后,在application目錄下面的`command.php`(如果不存在則創建)文件中添加如下內容:
```
<pre class="calibre18">
```
<span class="hljs-number">return</span> [
<span class="hljs-string">'\app\console\Clear'</span>,
];
```
```
表示給應用增加一個命令行`Clear`指令,我們可以用`list`指令來驗證是否已經成功注冊`Clear`指令:
```
<pre class="calibre18">
```
>php think <span class="hljs-keyword">list</span>
```
```
運行后如果看到

表示指令注冊成功,接下來可以測試下該指令:
```
<pre class="calibre18">
```
>php think clear
Clear Successed
```
```
> 該指令并不會刪除目錄,僅僅刪除目錄下面(包括子目錄)的文件。
`clear`指令還定義了一個`--path`參數用于指定目錄,下面是一個指定目錄刪除文件的用法,我們僅僅需要刪除日志文件:
```
<pre class="calibre18">
```
>php think clear --path d:\www\tp5\runtime\<span class="hljs-number">log</span>\
Clear Successed
```
```
`--path`參數還有一個簡化用法`-d`
```
<pre class="calibre18">
```
>php think clear <span class="hljs-operator">-d</span> d:\www\tp5\runtime\<span class="hljs-number">log</span>\
Clear Successed
```
```
## 命令行調試
命令行一旦執行錯誤,只能看到簡單的錯誤信息,如果需要調試詳細的Trace信息,可以使用 `-v` 參數來顯示,例如:
假設Clear指令文件中使用了一個未定義的變量`pathp`,那么我們可以使用
```
<pre class="calibre18">
```
>php think clear
```
```
會顯示如下錯誤:

我們需要查看具體的Trace信息,可以使用
```
<pre class="calibre18">
```
>php think clear -v
```
```
會看到類似下面的錯誤信息:

## 命令行顏色支持
為了讓命令行工具更加有趣,`think`命令行支持顏色輸出,并且內置了幾種顏色樣式,還可以自己自定義顏色樣式輸出。
> #### windows下面命令行顏色輸出支持需要`windows 10.0.10580`以上版本支持
我們添加一個`color`指令用于演示顏色輸出效果,代碼如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">console</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">console</span>\<span class="hljs-title">command</span>\<span class="hljs-title">Command</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">console</span>\<span class="hljs-title">Input</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">console</span>\<span class="hljs-title">Output</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">console</span>\<span class="hljs-title">output</span>\<span class="hljs-title">formatter</span>\<span class="hljs-title">Style</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Color</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Command</span></span>{
<span class="hljs-keyword">protected</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">configure</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$this</span>
->setName(<span class="hljs-string">'color'</span>)
->setDescription(<span class="hljs-string">'Show Color text'</span>);
}
<span class="hljs-keyword">protected</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">execute</span><span class="hljs-number">(Input <span class="hljs-regexp">$input</span>, Output <span class="hljs-regexp">$output</span>)</span></span>{
<span class="hljs-comment">// 輸出info樣式</span><span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"<info>this is info</info>"</span>);
<span class="hljs-comment">// 輸出error樣式</span><span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"<error>this is error</error>"</span>);
<span class="hljs-comment">// 輸出comment樣式</span><span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"<comment>this is comment</comment>"</span>);
<span class="hljs-comment">// 輸出question樣式</span><span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"<question>this is question</question>"</span>);
<span class="hljs-comment">// 輸出highlight樣式</span><span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"<highlight>this is highlight</highlight>"</span>);
<span class="hljs-comment">// 輸出warning樣式</span><span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"<warning>this is warning</warning>"</span>);
<span class="hljs-comment">// 輸出混合樣式</span><span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"this is <info>info</info>, this is <error>error</error>,this is <comment>comment</comment>,this is <question>question</question>,this is <highlight>highlight</highlight>, this is <warning>warning</warning>"</span>);
<span class="hljs-comment">// 自定義輸出樣式</span><span class="hljs-regexp">$output</span>->getFormatter()->setStyle(<span class="hljs-string">'custom'</span>, <span class="hljs-keyword">new</span> Style(<span class="hljs-string">'black'</span>, <span class="hljs-string">'white'</span>));
<span class="hljs-regexp">$output</span>->writeln(<span class="hljs-string">"<custom>this is style</custom>"</span>);
}
}</span>
```
```
`command.php`定義修改如下:
```
<pre class="calibre18">
```
<span class="hljs-number">return</span> [
<span class="hljs-string">'\app\console\Clear'</span>,
<span class="hljs-string">'\app\console\Color'</span>,
];
```
```
然后執行下面的指令:
```
<pre class="calibre18">
```
>php think color
```
```
運行后就可以看到:

## 調用命令
在代碼里面可以直接調用執行命令行的某個命令,例如:
```
<pre class="calibre18">
```
<span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Console</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Index</span></span>{
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span><span class="hljs-number">()</span></span>{
<span class="hljs-comment">// 調用命令行的指令</span><span class="hljs-regexp">$output</span> = Console::call(<span class="hljs-string">'make:model'</span>,[<span class="hljs-string">'index/Blog'</span>]);
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$output</span>->fetch();
}
}
```
```
> Console::call方法的第一個參數就是指令名稱,后面的第二個參數是一個數組,表示調用的參數。
> 如果我們要創建一個`demo`模塊的話,應該是:
>
> ```
> <pre class="calibre21">
> ```
> <span class="hljs-operator"><span class="hljs-title1">Console</span>:<span class="hljs-string">:<span class="hljs-function">call</span>(<span class="hljs-operator">'build'</span>,[<span class="hljs-operator">'--module'</span>, <span class="hljs-operator">'demo'</span>])</span></span>;
> ```
>
> ```
當訪問
```
<pre class="calibre18">
```
<span class="hljs-string">http:</span>
<span class="hljs-comment">//tp5.com </span>
```
```
頁面會輸出
```
<pre class="calibre18">
```
<span class="hljs-title">Model</span> created successfully.
```
```
可以在`application/index/model/`目錄下面發現已經生成了一個`Blog`模型文件。
當我們再次刷新頁面的話,會看到頁面輸出
```
<pre class="calibre18">
```
Model already <span class="hljs-keyword">exists</span>!
```
```
表示模型已經創建過了,無需再次創建。
> 使用`Console::call`方法調用指令執行不會看到最終的輸出結果,需要使用fetch方法獲取輸出信息,一旦發生錯誤,則會拋出異常。
- 脕茫隆壟脨貌脩脭
- 脕茫隆壟脨貌脩脭
- 脪祿隆壟祿霉麓隆
- 脪祿隆壟祿霉麓隆
- 露鎂隆壟URL潞脥脗路脫脡
- 露鎂隆壟URL潞脥脗路脫脡
- 脠媒隆壟脟毛脟貿潞脥脧矛脫婁
- 脠媒隆壟脟毛脟貿潞脥脧矛脫婁
- 脣脛隆壟脢媒戮脻驢芒
- 脣脛隆壟脢媒戮脻驢芒
- 脦氓隆壟虜茅脩爐脫茂脩脭
- 脦氓隆壟虜茅脩爐脫茂脩脭
- 脕霉隆壟脛攏脨脥潞脥鹿脴脕陋
- 攏簍1攏漏脛攏脨脥露簍脪氓
- 攏簍2攏漏祿霉麓隆虜脵脳梅
- 攏簍3攏漏露脕脠隆脝梅潞脥脨脼賂脛脝梅
- 攏簍4攏漏脌脿脨脥脳陋祿祿潞脥脳脭露爐脥錨魯脡
- 攏簍5攏漏虜茅脩爐路露脦摟
- 攏簍6攏漏脢盲脠毛潞脥脩茅脰隴
- 攏簍7攏漏鹿脴脕陋
- 攏簍8攏漏脛攏脨脥脢盲魯枚
- 脝脽隆壟脢脫脥錄潞脥脛攏擄氓
- 脝脽隆壟脢脫脥錄潞脥脛攏擄氓
- 擄脣隆壟碌梅脢脭潞脥脠脮脰戮
- 擄脣隆壟碌梅脢脭潞脥脠脮脰戮
- 戮脜隆壟API驢陋路壟
- 戮脜隆壟API驢陋路壟
- 脢廬隆壟脙眉脕卯脨脨鹿隴戮脽
- 脢廬隆壟脙眉脕卯脨脨鹿隴戮脽
- 脢廬脪祿隆壟脌漏脮鹿
- 脢廬脪祿隆壟脌漏脮鹿
- 脢廬露鎂隆壟脭脫脧卯
- Cookie
- Session
- 碌樓脭陋虜芒脢脭
- 脥錄脧帽麓婁脌鉚
- 脦脛錄鎂脡脧麓蘆
- 脩茅脰隴脗毛
- 賂陸脗錄
- A隆壟魯攏錄沒脦脢脤芒錄爐
- B隆壟3.2潞脥5.0脟酶鹵冒
- C隆壟脰煤脢脰潞爐脢媒
- 路盧脥芒脝陋攏潞脩摟脧擄ThinkPHP5碌脛脮媒脠路脳脣脢脝
- 路盧脥芒脝陋攏潞脩摟脧擄ThinkPHP5碌脛脮媒脠路脳脣脢脝