在學習 Laravel 的時候,可能很多人接觸的第一個 artisan 的命令就是:php artisan serve,這樣我們就可以跑起第一個 Laravel 的應用。本文來嘗試解讀一下這個命令行的源碼。
代碼在哪
跟之前的源碼解讀文章一樣,我推薦大家可以使用編輯器的搜索功能,直接搜ServeCommand 就可以直接打開這個命令的源碼文件,位於 Illuminate\Foundation\Console\ServeCommand,像其他的 artisan 命令一樣,我們還是關注 fire() 方法:
public function fire(){
chdir($this->laravel->publicPath());
$this->line("
<info>Laravel development server started:</info>
<http://{$this->host()}:{$this->port()}>");
passthru($this->serverCommand());
}
第一步
首先使用 chdir() 將目錄改變至 public/ 目錄,這是根據 $this->laravel->publicPath() 代碼的 publicPath() 來的,這個方法的源碼位於 Illuminate\Foundation\Application 中:
public function publicPath(){
return $this->basePath.DIRECTORY_SEPARATOR.'public';
}
上面的 $this->basePath 就是項目的根目錄啦!
第二步
打印信息,這是通過 fire() 的第二行代碼實現的:
$this->line("
<info>Laravel development server started:</info>
<http://{$this->host()}:{$this->port()}>
");
具體效果就是這樣:
第三步
執行命令,這個命令是從 passthru($this->serverCommand()) 的原生函數 passthru() 來實現的,其中 $this->serverCommand() 負責返回一個可以執行的字符串命令,具體代碼就在同文件的 serverCommand() 中:
protected function serverCommand(){
return sprintf('%s -S %s:%s %s/server.php',
ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false)),
$this->host(),
$this->port(),
ProcessUtils::escapeArgument($this->laravel->basePath())
);
}
sprintf() 的四個字符串佔位符會被後面傳入的四個參數替換,最終打印出一個可以執行的 PHP 命令,其中這四個分別對應的是:
1.下面代碼返回 php 的可執行全路徑,
ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false))
2.下面代碼返回 host ,默認爲 127.0.0.1
$this->host()
這部分可以直接查看 host() 方法:
protected function host(){
return $this->input->getOption('host');
}
這樣看來,我們在使用 serve 命令的時候其實是可以傳入 host 參數的。
3.下面代碼返回 port ,跟 host 是一模一樣的:
$this->port()
代碼就在 port() 方法中,(使用 serve 命令的時候也是可以直接傳入端口號的!):
protected function port(){
return $this->input->getOption('port');
}
上面的 2 和 3 可以直接這樣考證 : 執行php artisan help serve
4.下面的代碼返回執行代碼的全路徑:
ProcessUtils::escapeArgument($this->laravel->basePath())
所以,最後 serverCommand() 返回的是什麼呢?我們可以直接打印看看:
打印的結果是:
這樣一看,php artisan serve 命令就是直接使用 php 執行 server.php 文件,這個文件就在項目的根目錄下,比如就是相當於我們直接在命令行執行下面這個命令:
php -S 127.0.0.1:8000 server.php
在這基礎上,記得指定 public/ 爲網站根目錄。
最後
php artisan serve 命令背後其實也就是使用了 php 去直接執行文件,跟我們在使用 php -S php -S 127.0.0.1:8000 PHP 的內置服務器沒有太大的區別。