基本概念#
將原始碼寫在.stub檔中,內容中如果有需要替換的則使用{{ }} 標記,例如 namespace {{ namespace }};
GeneratoreCommand會讀出.stub檔案將需要替換的文字替換完成後依照namespace寫入.php檔案
幾個需要理解的method與參數
首先參數的部分,固定第一個為name,也就是要產出的檔案名稱
php artisan GeneratorCommand {name}method: getStub()#
protected function getStub(): string需要return .stub檔案的路徑,如果.stub檔案在vendor資料夾中則可以透過上篇說明來取得package中的檔案
範例可以像這樣子,class中依照上一篇說明定義好get_file_path後,就可以找到指定的Vendor\package\路徑下的檔案了
如果是在同一個專案目錄中,則直接return專案中路徑即可
protected function getStub(): string
{
return $this->get_file_path("/http/Controllers");
}method: getDefaultNamespace()#
protected function getDefaultNamespace($rootNamespace): string需要return 產出php檔正確擺放位置的namespace,例如
protected function getDefaultNamespace($rootNamespace): string
{
return $rootNamespace . "\Http\\Controllers";
}這樣子就會把產出的php檔案放在app\Http\Controllers中
method: getNameInput()#
protected function getNameInput(): stringreturn值作為檔案的名稱,也就是return command第一個參數name就行了,通常會把class name做大駝峰處理,範例如下
protected function getNameInput(): string
{
return Str::studly(trim($this->argument('name')));
}method: buildClass()#
protected function buildClass($name): array|string如果產出的php檔沒有其他需要替換的標記,或者沒有其他邏輯需要處理是可以不必處理buildClass()這個method,這邊提供一個範例
把stub內容中多組tag紀錄在$this->replace_tags中,然後再buildClass method中替換掉他
protected function buildClass($name): array|string
{
$stub = $this->files->get($this->getStub());
$namespace = $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
$replacedStub = $namespace;
foreach ($this->replace_tags as $tag => $text){
$replacedStub = str_replace("{{ {$tag} }}", $text, $replacedStub);
}
return $replacedStub;
}method: handle()#
public function handle(): ?bool如果在產出檔案前,有需要對class的其他參數做調整,可以複寫handle() method,記得最後要return parent::handle()就好
例如像這樣
public function handle(): ?bool
{
#你想要的內容寫在這裡
return parent::handle(); // TODO: Change the autogenerated stub
}method: interact()#
protected function interact(InputInterface $input, OutputInterface $output)假設需要對輸入的參數做一些調整,可以透過複寫interact來達成,下面的範例處理了name參數,讓他變成首字大寫
/**
* Override
* 重新處理name參數
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
parent::interact($input, $output);
if ($input->hasArgument('name')) {
$name = implode('/',array_map('ucfirst',explode('/',$input->getArgument('name'))));
$input->setArgument('name',$name);
}
}最後提供一個完整範例#
將virtualorz\mysdk中的 Stuns/http/controllers.stub 生成 /app/Http/Controllers/CustomerController.php
#command.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\GeneratorCommand;
use Illuminate\Support\Str;
class MakeCustomerController extends GeneratorCommand
{
protected $name = 'make:my-controller';
protected $description = 'Create my controller class';
protected string $stub_path = 'http/ClassController';
protected string $target_path = '\Http\\Controllers';
protected array $replace_tags = ['use_string'=>'use App\Services\Config\ConfigService'];
protected function getStub(): string
{
return $this->get_file_path($this->stub_path);
}
protected function getDefaultNamespace($rootNamespace): string
{
return $rootNamespace . $this->target_path;
}
protected function getNameInput(): string
{
return Str::studly(trim($this->argument('name')));
}
protected function buildClass($name): array|string
{
$stub = $this->files->get($this->getStub());
$namespace = $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
$replacedStub = $namespace;
foreach ($this->replace_tags as $tag => $text){
$replacedStub = str_replace("{{ {$tag} }}", $text, $replacedStub);
}
return $replacedStub;
}
protected function get_file_path($path): string
{
$loader = $this->_getClassLoader();
$psr4 = $loader->getPrefixesPsr4();
$namespace = 'virtualorz\\mysdk\\';
$stubFilename = "Stubs/{$path}.stub"; // Stub 檔案名稱
$stub_path_location = '';
foreach ($psr4 as $prefix => $paths) {
if (str_starts_with($namespace, $prefix)) {
foreach ($paths as $path) { // 處理多個路徑
$relativePath = str_replace($prefix, '', $namespace);
$relativePath = str_replace('\\', '/', $relativePath);
$stubPath = $path . '/' . $relativePath . $stubFilename;
if (file_exists($stubPath)) {
$stub_path_location = $stubPath;
}
}
}
}
return $stub_path_location;
}
protected function _getClassLoader()
{
return require base_path('vendor/autoload.php');
}
}Controllers.stub
<?php
namespace {{ namespace }};
{{ use_string }}
class {{ class }} extends Controller
{
}值執行命令#
php artisan make:my-controller CustomerController