- 投稿日:2020-08-30T23:42:44+09:00
Using another database for phpunit test on Laravel 6 with docker-compose.
Every engineer would hope to divide database when running test.
I'll show using another database for phpunit test on Laravel 6 with docker-compose in this article.STEP
- Adding test database on docker-compose
- Adding setting for test database in config/database.php
- Adding environment at phpunit.xml
- Create .env.testing as new env file
- Running migration command for test database
- Running phpunit
CODES
docer-compose.ymlversion: '3' services: db: build: context: ./app/mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: hoge MYSQL_USER: hoge MYSQL_PASSWORD: hoge container_name: mydb ports: - "3306:3306" tty: true volumes: - ./app/mysql/db_data:/var/lib/mysql testdb: build: context: ./app/mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: hoge MYSQL_USER: hoge MYSQL_PASSWORD: hoge container_name: testdb ports: - "3307:3306" tty: true volumes: - ./app/mysql/testdb_data:/var/lib/mysql web: ...config/database.php... 'connections' => [ ... 'mysql' => [ ... ], 'mysql_testing' => [ ... 'host' => 'testdb', ... ],phpunit.xml<?xml version="1.0" encoding="UTF-8"?> ... <php> <env name="APP_ENV" value="testing" force="true"/> <env name="DB_CONNECTION" value="mysql_testing" force="true"/> ... </php> </phpunit>.env.testingAPP_ENV=test APP_KEY=[YOURKEY] APP_DEBUG=true$ php artisan:migrate database=mysql_testing $ ./vendor/bin/phpunit
- 投稿日:2020-08-30T23:08:55+09:00
LaravelユーザがRailsの勉強を始めようと思った話
スキルセット
- HTML
- CSS
- JavaScript
- PHP
- Laravel
勉強中
- AWS
- Docker
- CircleCI
理由
- 開発が早そう
- Railsでチーム開発がしたい
- 身の回りにRailsユーザが多い
- Rails + AWS + Docker + CicleCIでなにか作りたい
勉強法
オブジェクト指向の理解や、MVCは理解済みなので、とりあえずProgateやって経過を見ます。
- 投稿日:2020-08-30T13:13:29+09:00
【Laravel実践】リクエストパラメータ名をスネークケースに変換する方法
Version
- Laravel 5.7
- PHP 7.2.31
前提
LaravelでAPIを開発する際、キャメルケースとして書かれたリクエストパラメータ名をスネークケースに変換したい、という要望を想定します。たとえば、SPA開発においてReact.jsやVue.jsにより非同期通信でLaravelのAPIにリクエストを送信する際、フロント側としてはキャメルケースで統一したいがバックエンド側としてはスネークケースで統一したい、というケースです。
Laravel側で簡単に変換する方法をググったのですが、ベストプラクティス的な方法が出てこなかったのでここに共有します。
早速、変換してみよう。
結論だけ述べると、以下の方法で実現できます。
$request->all()
でリクエストパラメータを受け取り、リクエストパラメータ名($key
)に大文字が含まれる場合にスネークケースに変換・挿入、offsetUnset()
で元のプロパティ名を消す、ということをやっています。foreach ($request->all() as $key => $value) { if(preg_match('/[A-Z]/', $key)){ $new_key = Str::snake($key); $request->merge([$new_key => $request->$key]); $request->offsetUnset($key); } }たとえば、TestControllerのindexで受け取ることを考えてみましょう。バリデーションを一旦無視すれば、以下のように書けるはずです。
TestController.phpclass TestController { public function index(Request $request) { // スネークケースに変換する処理 foreach ($request->all() as $key => $value) { if(preg_match('/[A-Z]/', $key)){ $new_key = Str::snake($key); $request->merge([$new_key => $request->$key]); $request->offsetUnset($key); } } // hogehoge処理 ... return $request; } }応用: スネークケース変換用のクラスを作成
色々と応用する方法はあると思いますが、最終的に以下の方法で落ち着きました。
- FormRequestクラスでバリデーション処理(※1)
- Controllerクラスを継承する形でスネークケースに変換するクラスを作成(※2)
- indexのController側でスネークケース変換用のメソッドを呼び出し(※3)
NormalizedController.php// ※2 class NormalizedController extends Controller { /** * Change request parameter from camel case to snake case * * @param object $request * @return object */ protected function normarize_request(Object $request) : object { foreach ($request->all() as $key => $value) { if(preg_match('/[A-Z]/', $key)){ $new_key = Str::snake($key); $request->merge([$new_key => $request->$key]); $request->offsetUnset($key); } } return $request; } }TestController.php// FormRequestクラス(※1) use App\Http\Requests\Test\GetRequest; class TestController extends NormalizedController { public function index(GetRequest $request) { // 呼び出し(※3) $this->normarize_request($request); // hogehoge処理 ... return $request; } }参照
- 投稿日:2020-08-30T12:58:20+09:00
laravel 別のMYSQLに動的接続、切り替え
laravel で 別のデータベースに切り替えたい時がある。
例えば、古いDBから新しいDBにデータを以降する時など。今回は、database twiski に切り替たい
database.php//色々と略 'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), ], 'old' => [ 'driver' => 'mysql', 'url' => env('DATABASE_URL'), 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => 'twiski',//接続したいDBに書き換える ],これで twiski に切り替えられる
HogeContorller.php$model = new User; $res = $model ->orderBy('id', 'ASC') ->first(); $res = $model ->setConnection('old')//これが味噌 ->orderBy('id', 'ASC') ->first();DBファサードを使う
これで
old
のusers
テーブルのデータ取得できるHogeController.php//use DB; $profiles_tags = DB::connection('old') ->table('users') ->limit(5) ->get();以上
- 投稿日:2020-08-30T11:52:46+09:00
Sign In With Appleを実装
概要
- Sign In With Appleをアプリに組み込む際に調べたことをまとめました。
- 今回の内容はサーバーサイドのみの内容となります。
開発環境
- 使用言語:PHP(v7.3.11)
- フレームワーク:Laravel(v7.20.0)
- DB:Sqlite
事前準備
- Apple Developerに登録してSign In With Appleの設定をしておく 以下の値、ファイルを取得
- アプリのバンドルID
- KeyID
- 秘密鍵の.p8ファイル(1度しかダウンロードできないので注意)
- TeamID
認証の流れ
以下の手順で認証を行いました
* クライアント側でSign In With Appleの認証をする
* 認証結果のcode値をサーバに送る
* サーバ側でcodeの検証
* 検証結果がJWT形式で返ってくるのでJWTデコードするcodeの検証
検証はAppleが提供している検証APIに以下のパラメータをPOSTして行います。
API:POST https://appleid.apple.com/auth/token
パラメータ
* client_id:アプリのバンドルIDのこと
* client_secret
* code:クライアント側から取得する
* grant_type:検証なので'authorization_code'を設定
* redirect_uri:あらかじめDevelopperサイトで登録しておくclient_secretの作成
- client_secretとは検証に必要なJWTでエンコードされた値
- JWTとは3種類の文字列をドットで繋げた文字列
- JWTの作成にはfirebaseが提供しているライブラリを使用(他にもありましたが今回は以下を使用しました)
client_secret作成に必要な値
- alg:ES256
- kid:KeyID
- iss:TeamID
- iat:現在時刻
- exp:有効期限
- aud:'https://appleid.apple.com'(固定)
- sub:ClientID(アプリのバンドルID)
今回は以下のように実装しました
$key = openssl_pkey_get_private('file://'.PRIVATE_KEY_PASS); // 秘密鍵ファイルのパス $now = time(); $expire = time() + 86400 * 180; // 有効期限を半年に設定 $payload = array( 'iss' => TEAM_ID, 'iat' => $now, 'exp' => $expire, 'aud' => 'https://appleid.apple.com', 'sub' => CLIENT_ID ); return JWT::encode($payload, $key, 'ES256', KEY_ID); // ES256は署名アルゴリズム検証結果からユーザーを一意に特定するIDを取得
- ユーザーを特定する文字列はid_tokenの中に含まれているのですが、JWT形式のためそのまま取り出すことはできません。
- id_tokenは「ヘッダー.ペイロード.署名」のように情報をドット区切りで持っています
- ユーザーを特定するIDはペイロードの中に含まれる「sub」値がそれに該当します
以下のようにしてsub値を取得しました
$jwt_token = expload('.', 'id_token'); $payload = base64_decode($jwt_token[1]); $decode_payload = json_decode($payload, true); $sub = $decode_payload['sub'];参考資料
- 投稿日:2020-08-30T08:51:35+09:00
【GitHub Actions】LaravelのCI環境構築
実現したいこと
GitHub Actionsを用いて、LaravelのCI環境構築をします。
前提
開発環境でPHPUnitの
vendor/bin/phpunit
コマンドを実行したら問題なくテストが正常に動作するのが前提です。ワークフローの作成
github/workflows/ci.ymlname: CI on: push: branches: [master] pull_request: branches: [master] jobs: php-nuit: runs-on: ubuntu-latest services: mysql: image: mysql:8.0.19 ports: - 3306:3306 options: --health-cmd "mysqladmin ping -h localhost" --health-interval 20s --health-timeout 10s --health-retries 10 env: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: testdatabase env: DB_CONNECTION: mysql DB_HOST: 127.0.0.1 DB_PORT: 3306 DB_DATABASE: testdatabase DB_USERNAME: root DB_PASSWORD: password steps: - uses: actions/checkout@v2 - name: Copy .env run: cp .env.ci .env working-directory: ./server - name: composer install run: | composer install --no-scripts working-directory: ./server - name: Generate key run: php artisan key:generate working-directory: ./server - name: Directory Permissions run: chmod -R 777 storage bootstrap/cache working-directory: ./server - name: migrate run: php artisan migrate working-directory: ./server - name: php-unit test run: ./vendor/bin/phpunit working-directory: ./server今回のテストでは、データベースも絡んでいるため、MySQLを使用しました。また、私のLaravelのディレクトリ構造は下記の添付画像のようになっていたため、コマンドによってはディレクトリを指定する
working-directory: ./server
を記述しています。■参考
https://github.com/yuuta1988/shussekikun/blob/master/.github/workflows/ci.yml.env.ciの作成
ワークフローで.env.ciを元に.envファイルを複製するので、.env.ciを作成します。
server/.env.ciAPP_NAME=Laravel APP_ENV=testing APP_KEY= APP_DEBUG=true APP_URL=http://localhost DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=testdatabase DB_USERNAME=root DB_PASSWORD=password■参考
https://github.com/yuuta1988/shussekikun/blob/master/server/.env.ci参考
- 投稿日:2020-08-30T02:51:51+09:00
CodeIgniter3 から Laravel へ。文化の異なるフレームワークへ飛び込む上で,ハードルになりそうなパッケージ管理システムの概要を解説
概要
今回は,より高度な(実用的な)仕様の例題を設定し,CodeIgniter と Laravel のコードを対比させていきたいと思います。
具体的には,CSS と JS を組み込んだページを作成したいと思いますが,具体的なコードの紹介は次回の記事にゆだね,今回は,もっと基本となる「パッケージ管理システム」について触れます。
あまり一気に難しくならないよう,極力配慮したいと思いますが,前回よりは,ハードルがぐーんと高くなり,おじさんの言語化能力で,どこまで的確に表現できるか,冷や汗をかきそうです(プレッシャーの重圧感)。
マサカリ歓迎案件です(いろいろ教えてください)。
Laravel で登場する,2つのパッケージ管理システム
どのタイミングで話すべきか迷ったのですが,いずれ書かねばならないことなので,今のタイミングにします。
「軽量であること」を強みとする CodeIgniter は,フレームワークと言うより,フォルダ構造を決めただけの,ファイルの集合体に近いですね(そんな言い方をしてしまうと,世の中のすべてのフレームワークが,「ファイルの集合体」と言えますが……)。
一方,Laravel も「ファイルの集合体」ではありますが,「パッケージ管理システム」が標準的な仕組みとして多用されることが大きな相違点です。
※パッケージ管理システムをまったく使わず,Laravel で開発するのも可能かと思いますが,ほとんどメリットはないと思います(しんどくなるだけ)
※「パッケージ管理システムが何であるか」は,優れた記事が多数あるため,本記事の記述スコープに含めません
しかも,驚くなかれ,Laravel には,二種類のパッケージ管理システムが採用されています:
Composer
バックエンド側(PHP ファイル)のパッケージ管理を担うLaravel Mix
フロントエンド側(CSS / JS ファイル)のパッケージ管理を担うどっちか一つを使うというものではなく,役割がそもそも異なっているのですね(バックエンド側か,フロントエンド側か)。
以下,もっと具体的に見ていきましょう。
プロジェクト新規作成
CodeIgniter は,公式サイトから zip としてダウンロードする方法。
あくまでも,開発者が,ブラウザで公式サイトへアクセスし,そこからファイル一式を取得するというスタンスですね。
一方,Laravel では,Composer というパッケージ管理システムを使って,コマンドラインからプロジェクトのファイル一式を生成します。
たとえば,
example
という名のプロジェクトを生成するには,以下のようなコマンドを実行します:composer create-project --prefer-dist laravel/laravel exampleCodeIgniter に慣れていると,つい,手作業でファイルを追加したり,移動したりする衝動に駆られてしまいますが,そこはグッと我慢することが,Laravel 文化の入り口です。
最後に,もう一度まとめます:
工程 CodeIgniter Laravel テンプレート一式の取得 公式サイトから zip をダウンロード Composer
コマンド経由で取得PHP ファイルの追加
CodeIgniter で新しい PHP ファイル(例:コントローラ)を追加するときには,テキストファイルをコピペする感覚で,みんな大好き
Ctrl + C
やCtrl + P
のショートカットが大活躍でした。一方,Laravel では,新しい PHP ファイル(例:コントローラ)を追加するときには,パッケージ管理システム Composer を使って,コマンドライン上で実行します。
たとえば,
MyFirstController
というコントローラを作る場合,以下のようなコマンドを実行します:php artisan make:controller MyFirstControllerLaravel でも,
Ctrl + C
とCtrl + P
で,新しい PHP ファイルを生成可能(例:既存のクラスからコピーして生成可能)ですが,コピー後のファイルの中身を,自分で書き換える手間が生じるので,あまりスマートな方法だとは言えません。最後に,もう一度まとめます:
工程 CodeIgniter Laravel PHP ファイルの追加 Ctrl + C
とCtrl + P
で手動対応Composer
コマンド経由で作成CSS / JS ファイルの追加
CSS / JS ファイルといった,フロントエンドのアセットを生成するケースを考えます。
「ファイルの集合体」のようにシンプルな CodeIgniter では,所定のフォルダへ,CSS や JS を保存するだけ(&その後,ビュー側の
<head></head>
部で,読み込ませるだけ)。Laravel でも,所定のフォルダへ,CSS / JS を保存するという,CodeIgniter 時代のスタイルは利用可能です。
一方,Laravel では,もう一つのパッケージ管理システム Laravel Mix を使うというオプションも,用意されています。
超ざっくり書くと,以下のような役割を果たしてくれます。
- 依存関係のあるライブラリを一括取得(一番「親」のライブラリを指定すると,配下の関連ライブラリを,芋づる式に,拾ってきてくれます)
- リリースしやすいよう,関連ファイルを,一つのファイルにまとめてパッキング
コマンドラインでは,
npm run dev
とすれば,開発環境でデバッグが容易な(人の目で見ても解釈しやすい)形式にパッキングしてくれます。一方,
npm run production
とすれば,リリースに適した形式(空白や改行を除外し,コンピュータの解釈に適したもの。ファイルサイズとしても,すごく小さくなる)にパッキングしてくれます。ひとつ強調しておくと,Laravel Mix は,その名に 'Laravel' を冠しながらも,Laravel 利用の有無とは関係なく使える,パッケージ管理システムだったりします。
つまり,CodeIgniter でも,Laravel Mix を活用することは可能です。
最後に,もう一度まとめます:
工程 CodeIgniter Laravel CSS / JS ファイルの追加 所定フォルダに,手動で保存 Laravel Mix
利用まとめ
かなり駆け足になりましたが,CodeIgniter では手作業メインで行っていたファイル管理を,Laravel では,コマンドライン経由で済ませるのだという理解を形成いただければ,本記事のリリース目的は達成されました。
事実,コマンドラインで,パッケージ管理システムを上手に活用し,エンジニアが本来注力すべき作業へ集中させてくれるようになっているのは,Laravel のコンセプトでもあるように感じます。
次回では,実際に,パッケージ管理システムを操作しながら,Laravel を用いたフロントエンドアセット(CSS / JS)の組み込みについて,CodeIgniter と比較させながら見ていきたいと思います。