送書!源碼解讀:php artisan serve

在學習 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 的內置服務器沒有太大的區別。



發佈了7 篇原創文章 · 獲贊 10 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章