# 開發自動化 ![](https://i.imgur.com/g6YLiPm.jpg) ## 自動產生程式碼 1. 下載接案環境快速生成器 [https://github.com/teed7334-restore/laravel-startup](https://github.com/teed7334-restore/laravel-startup) 2. 新增一個本教學所需之資料庫與使用者 ``` database: course username: course password: course ``` 3. 將資料庫設定寫入web/.env中 4. 按接案環境快速生成器之說明文件,生成前台與後台 5. 於./web底下新增一個draft.yaml檔案 ``` models: News: author: string:50 title: string:50 content: text controllers: News: index: query: order:created_at:DESC limit:10 render: news.index with:news add: render: news.add insert: validate: author, title, content save: news flash: news.id redirect: news.index detail: render: news.detail with:news edit: render: news.edit with:edit update: validate: news update: news flash: news.id redirect: news.index delete: delete: news redirect: news.index ``` 6. 透過Blueprint生成相關程式碼 ``` php artisan blueprint:build draft.yaml ``` 7. 確認產生的各檔案 ``` Created: - database/migrations/2020_05_11_160107_create_news_table.php - app/News.php - database/factories/NewsFactory.php - app/Http/Controllers/NewsController.php - app/Http/Requests/NewsInsertRequest.php - app/Http/Requests/NewsUpdateRequest.php - resources/views/news/index.blade.php - resources/views/news/add.blade.php - resources/views/news/detail.blade.php - resources/views/news/edit.blade.php - tests/Feature/Http/Controllers/NewsControllerTest.php Updated: - routes/web.php ``` 8. Blueprint 官方文件 [https://blueprint.laravelshift.com/docs/getting-started/](https://blueprint.laravelshift.com/docs/getting-started/) 9. 程式碼生成器雖然可以在新增時加速開發,但是過多的程式碼也會造成管理上的問題,所以在維護上面,我們要多運用好比Trait與Interface,來達到元件重複利用與組合使用的目的,好比我們可以參考Laravel的註冊流程 ``` <?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use App\User; use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; class RegisterController extends Controller { /* |-------------------------------------------------------------------------- | Register Controller |-------------------------------------------------------------------------- | | This controller handles the registration of new users as well as their | validation and creation. By default this controller uses a trait to | provide this functionality without requiring any additional code. | */ use RegistersUsers; /** * Where to redirect users after registration. * * @var string */ protected $redirectTo = RouteServiceProvider::HOME; /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest'); } /** * Get a validator for an incoming registration request. * * @param array $data * @return \Illuminate\Contracts\Validation\Validator */ protected function validator(array $data) { return Validator::make($data, [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); } /** * Create a new user instance after a valid registration. * * @param array $data * @return \App\User */ protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); } } ``` 10. 在上面的程式碼裡面,我們能找到的都只有protected的method而已,但是程式當中又有一行use吸引到了我們注意 ``` use RegistersUsers; ``` 11. 接下來我們找到RegisterUsers,其他相關的程式就通通都在該檔案裡面了 ``` <?php namespace Illuminate\Foundation\Auth; use Illuminate\Auth\Events\Registered; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Auth; trait RegistersUsers { use RedirectsUsers; /** * Show the application registration form. * * @return \Illuminate\Http\Response */ public function showRegistrationForm() { return view('auth.register'); } /** * Handle a registration request for the application. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function register(Request $request) { $this->validator($request->all())->validate(); event(new Registered($user = $this->create($request->all()))); $this->guard()->login($user); if ($response = $this->registered($request, $user)) { return $response; } return $request->wantsJson() ? new Response('', 201) : redirect($this->redirectPath()); } /** * Get the guard to be used during registration. * * @return \Illuminate\Contracts\Auth\StatefulGuard */ protected function guard() { return Auth::guard(); } /** * The user has been registered. * * @param \Illuminate\Http\Request $request * @param mixed $user * @return mixed */ protected function registered(Request $request, $user) { // } } ``` 12. 我們可以多採用Trait的方式,讓程式碼可以漸漸變的簡捷一些,甚至透過複寫來達到多型的目的 13. 而另一種方式是透過Interface規範物件的對外接口,並且在需要使用時才註入該物件 ``` <?php interface IPay { /** 整理付款資訊 */ public function pay(array $params) : RO /** 呼叫金流API */ public function callApi(array $params) : RO /** 供金流API回叫使用 */ public function callBack(array $params) : RO } ``` 14. 以上我們設定好了Interface的通用接口,而一般金流也大多是這三步驟,所以我們分別針對紅陽、藍新、綠界,依不同需求開發了三隻class ``` <?php class Pay { public $red; public $green; public $blue; public function __construct() { $this->red = new Red; $this->green = new Green; $this->blue = new Blue; } public function pay() { $ro = $this->doPay($this->red); $ro = $this->doPay($this->green); $ro = $this->doPay($this->blue); } . . . protected function doPay(IPay $store) { $store->pay([]); $store->callApi([]); $store->callBack([]); } } ``` 15. 因為每隻class都是統一接口,所以我們可以直接依interface的規格來了解我們有那些method是對外可以被使用的 ## 自動程式碼分析 1. 透過以下Docker-Compose.yml生成一個SonarQube環境 ``` version: '3.7' services: sonarqube: image: sonarqube:community container_name: sonarqube volumes: - './sonarqube:/opt/sonarqube' ports: - '0.0.0.0:9000:9000' networks: server networks: server: driver: bridge ``` 2. 透過以下指令將Docker內的設定檔備份出來 ``` docker cp sonarqube:/opt/sonarqube ./ ``` 3. 修改./conf/sonar.properties,讓它可以連到PostgreSql資料庫 ``` sonar.jdbc.username=[你的sonarqube資料庫帳號] sonar.jdbc.password=[你的sonarqube資料庫密碼] sonar.jdbc.url=jdbc:postgresql://[資料庫IP]/[資料庫名稱]?currentSchema=[資料庫schema] ``` 4. 追加系統設定,不然Sonarqube裡面的Elasticsearch無法啟動 ``` sysctl -w vm.max_map_count=262144 ``` 5. 進入SonarQube,[http://localhost:9000](http://localhost:9000) 6. 創立一個新項目是針對我們剛剛所新增的course,全部都輸入course就可以 7. 新項目完成之後,它會有一個要你下載Scanner的[連結](https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/) 8. 新增程式碼掃瞄設定檔,並存成course.properties ``` sonar.projectKey=course sonar.projectName=course sonar.language=php sonar.projectVersion=1.0.0 sonar.host.url=http://[你的sonarqube主機IP]:9000 sonar.projectBaseDir=[你的course程式碼所在的位置] sonar.sources=./ sonar.exclusions=**/vendor/**,**/storage/** ``` 9. 運行Scanner ``` sonar-scanner -Dproject.settings=[你的course.properties位置] ``` ## 自動上版 1. 透過此[連結](https://gitlab.com/teed7334/case)抓取上版工具 2. 設定好development、test、production相關環境所需之參數 3. 運行 ``` ansible-playbook -i [你的主機設定,好比development、test、production] deploy.yml ```