手把手帶你建立一個 Laravel CRUD 程式碼生成器
讓我們來看看如何在 Laravel 中建立自己的 CRUD 生成器,來提升我們的工作效率。
通常情況下,一旦決定使用控制器提供的架構方案,你需要一個生成器,以便將來不會被重寫。
你可以從 這裡 獲取到原始碼。
第 1 步 --- 建立專案
建立一個新的 Laravel 專案:
composer create-project laravel/laravel Contest
第 2 步--- 啟動
將你的 Laravel 應用程式連線到資料庫並啟動伺服器。
第 3 步--- 使用命令生成
下面我們開始研究 CRUD 生成器的命令。
建立一個 CRUD 生成器命令:
php artisan make: command CrudGenerator
如果你執行:
php artisan
你應該有一個新的命令可用:
command:name Command description
當然,該命令還沒有設定,這就是為什麼你看到一個預設的名稱和說明。
在我們處理命令之前,如果你願意,我們需要一些存根或藍圖。
第 4 步---stub 模板
複製下面的程式碼到 resources/stubs
目錄。
stubs
目錄預設是不存在的,所以請確認你首先建立了它。並且,請用後面的名字命名這些檔案:Controller.stub
,Model.stub
和 Request.stub
正如你在下面所看到的,這些 stub 模板檔案裡有一些佔位符,我們稍後會用真實資料來替換它們。
Controller.stub
<?php
namespace App\Http\Controllers;
use App\Http\Requests\{{modelName}}Request;
use App\{{modelName}};
class {{modelName}}Controller extends Controller
{
public function index()
{
${{modelNamePluralLowerCase}} = { {modelName}}::latest()->get();
return response()->json(${{modelNamePluralLowerCase}});
}
public function store({{modelName}}Request $request)
{
${{modelNameSingularLowerCase}} = {{modelName}}::create($request->all());
return response()->json(${{modelNameSingularLowerCase}}, 201);
}
public function show($id)
{
${{modelNameSingularLowerCase}} = {{modelName}}::findOrFail($id);
return response()->json(${{modelNameSingularLowerCase}});
}
public function update({{modelName}}Request $request, $id)
{
${{modelNameSingularLowerCase}} = {{modelName}}::findOrFail($id);
${{modelNameSingularLowerCase}}->update($request->all());
return response()->json(${{modelNameSingularLowerCase}}, 200);
}
public function destroy($id)
{
{{modelName}}::destroy($id);
return response()->json(null, 204);
}
}
Model.stub
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class {{modelName}} extends Model
{
protected $guarded = ['id'];
}
Request.stub
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class {{modelName}}Request extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [];
}
}
你的 resources
目錄看起來應該像下面這樣:
第 5 步 --- 實現程式碼生成器
現在讓我們來實現第 3 步所建立的控制檯命令。
在 app/Console/Commands
資料夾找到 CrudGenerator.php
修改命令標誌和描述,如下:
protected $signature = 'crud:generator
{name : Class (singular) for example User}';
protected $description = 'Create CRUD operations';
描述要簡潔、明瞭。
至於命令標誌,可以根據個人喜好命名,就是後面我們要呼叫的 artisan 命令,如下:
php artisan crud:generator Car
接下來建立一個方法用來獲取樁程式碼。
protected function getStub($type)
{
return file_get_contents(resource_path("stubs/$type.stub"));
}
getStub 方法只是簡單的返回我們需要的樁程式碼內容。
下面,我們來看看怎樣使用 resources/stubs
資料夾下的 stub 模板來建立模型。
protected function model($name)
{
$modelTemplate = str_replace(
['{{modelName}}'],
[$name],
$this->getStub('Model')
);
file_put_contents(app_path("/{$name}.php"), $modelTemplate);
}
從程式碼可以看到,model
方法需要一個 name
引數,它由我們在 artisan 命令裡傳入。
看看 $modelTemplate
屬性。我們使用 str_replace
函式把 Model.stub
檔案裡的佔位符替換為我們期望的值。
基本上,在Model.stub
檔案裡,我們用$name
替換了{{modelName}}
。請記住,在我們的例子中,$name
的值是 Car。
你可以開啟Model.stub
檔案檢查一下,所有的{{modelName}}
都被替換為了 Car。
file_put_contents
函式再次使用了$name
建立了一個新檔案,因此它被命名為Car.php
。並且,我們給這個檔案傳入內容,這些內容是從$modelTemplate
屬性獲取的。$modelTemplate
屬性值是Model.stub
檔案的內容,只是所有的佔位符均被替換了。
同樣的事情還發生在controller
和request
方法裡。因此,我將這兩個方法的內容貼上在這裡。
protected function controller($name)
{
$controllerTemplate = str_replace(
[
'{{modelName}}',
'{{modelNamePluralLowerCase}}',
'{{modelNameSingularLowerCase}}'
],
[
$name,
strtolower(str_plural($name)),
strtolower($name)
],
$this->getStub('Controller')
);
file_put_contents(app_path("/Http/Controllers/{$name}Controller.php"), $controllerTemplate);
}
protected function request($name)
{
$requestTemplate = str_replace(
['{{modelName}}'],
[$name],
$this->getStub('Request')
);
if(!file_exists($path = app_path('/Http/Requests')))
mkdir($path, 0777, true);
file_put_contents(app_path("/Http/Requests/{$name}Request.php"), $requestTemplate);
}
好極了,現在我們來看受保護方法handle
。
在 handle() 方法裡,我們只需要呼叫剛剛定義好的那些方法。
public function handle()
{
$name = $this->argument('name');
$this->controller($name);
$this->model($name);
$this->request($name);
File::append(base_path('routes/api.php'), 'Route::resource(\'' . str_plural(strtolower($name)) . "', '{$name}Controller');");
}
很顯然,我們需要獲得使用者使用命令傳遞過來的引數值,在這個例子中這個引數值將永遠都是 Car ,接下來呼叫上面幾段裡面的解釋過的三個函式,最後在 rotues/api.php
檔案中追加一個資源路由。
第 6 步 --- 執行控制檯命令
現在讓我們去嘗試執行一下我們已經寫好的控制檯命令。
開啟一個終端控制檯並在終端輸入如下命令:
php artisan crud:generator Car
現在,你應該可以得到三個可用的檔案,一個是 app/
資料夾下 Model 層的 Car.php ,第二個是 app/Http/Controllers
資料夾下 Controller 層的 CarController.php ,第三個是 app/Http/Requests
資料夾的 CarRequest.php 檔案。
你可以看到,這個控制檯命令建立不了表的遷移檔案。由於這篇文章要發到 Medium 上,我們要讓它更簡單易懂,所以,接下來我們利用 Laravel 框架已經封裝好的控制檯命令去快速建立 cars 的表的遷移檔案。
php artisan make:migration create_cars_table --create=cars
修改 app/database/migrations
的 cars 的表格遷移檔案裡的 up 方法為下面的內容:
public function up()
{
Schema::create('cars', function (Blueprint $table) {
$table->increments('id');
$table->string('model');
$table->integer('year');
$table->timestamps();
});
}
接下來執行以下命令來應用遷移:
php artisan migrate
第 7 步 --測試用控制檯命令生成的 CRUD
在這個步驟中,我將會使用 postman 工具來進行測試。
儲存
顯示
顯示指定資料
更新
刪除
總結
在你的專案中,你現在已經擁有了一個 CRUD 程式碼生成器。假如你看不慣 resources/stubs
資料夾下的檔案,你可以點進去,然後修改這些檔案。
一般來說, 你只需要通過一個簡潔的控制檯命令來建立一些簡單的 CRUD 程式碼,而不用花費 10 到 15 分鐘甚至更多的時間去建立它。很酷的一件事情,是不是?
因為這篇文章已經收到了很多好評,所以我這陣子打算把這個 CRUD 程式碼生成器改寫成一個完整的 PHP 包!
敬請期待 & 快樂編碼!