けけずんセルフハッキング

エンジニアっぽい雰囲気を醸しだしているかのようなブログです!

「レガシーコード改革!UT/CIでWebサービスの技術的負債を解消する取り組み」に登壇しました

※会社のブログが移行中で記事作成できないので、一時的にこちらに書いてます

株式会社リビルドの嘉数です!

8/7(火)にランサーズ、BASE、リビルドの三社で「レガシーコード改革!UT/CIでWebサービスの技術的負債を解消する取り組み」というイベントを実施し、リビルド枠として嘉数は「Laravel5.5的継続的インテグレーション」というタイトルで登壇させて頂きました。

【好評につき増枠!】レガシーコード改革!UT/CIでWebサービスの技術的負債を解消する取り組み - connpass

というわけで各セッションについて非常にざっくりとした感じで書いていきたいと思います!

「決済リプレイスとPHPバージョンアップを支えたユニットテスト

スピーカーはBASE株式会社の東口和暉さん。ユニットテストについてお話して頂きました。

  • テストをしやすくするためにコードを疎結合にしてMockを差し込めるようにする、テストしにくい部分は破壊的だがrunkitを使用してコード内部の処理を変更する
  • テストを書く人・書かない人に分かれないよう全員がテストを書きやすい環境を整える
  • 溜まってきたテストの知見を活用して「破綻しやすいテスト」を書いていないか確認する

手探りで何が最適なのかを探しながらテストコードを書いている自分としては、非常に共感が得られる内容でした!

「レジェンドコードと向き合いレガシーからモダンへ変革する」

スピーカーはランサーズ株式会社の永田真也さん。ランサーズがこれまで行ってきた開発の歴史、もっと言えばテストの歴史についてお話して頂きました。

  • アプリ自体はPHPで実装しているが、E2EテストはRSpec+Capybaraのように疎結合に導入できるものを使用した
  • 技術的負債を解決するために多くの失敗を重ねるが、その失敗と向き合い改善を続けて前に進み続ける、徐々にコードを進化させていくことを意識する

起業から11年経った会社のテストに対する取り組みの変化は非常に面白かったです!

弊社の発表!「Laravel5.5的 継続的インテグレーション

発表!

そしてこちら弊社のプレゼン資料、タイトルで「〜的〜的」と的が連続しているのが気になります。

こちら発表風景になります。

f:id:kkznch:20190404093230j:plain
20180807_レガシーコード改革01

f:id:kkznch:20190404093314j:plain
20180807_レガシーコード改革02

質疑応答!

弊社の発表後にいくつか質問を頂いたのですが、質問内容が興味深いものでした。以下はその時の質問と回答の内容になります。

  • Q:「LaravelのPHPUnitでテストを書く際、どこからどこまでがユニットテスト結合テストの範囲なのか?」
  • A:「現在の開発であれば、結合テストには"機能の一連の手続き"と"コントローラ内のアクション"についてのテストを記述している。ユニットテストには"他に依存しない独立されたサービスクラス"のテストを記述している。ここらへんの配分って難しい、分かりみ。」

Webアプリだとユニットテスト結合テストの境目がどこからやねーんってなりますよね。皆も同じように思ってるんだなぁと感動しました(笑)。

  • Q:「GitLab CIでコンテナを使用してテストをしているようだが、最終的なデプロイ先もコンテナなのか?そうでない場合は冪等性が保証できないが、環境のテストも行っているのか?」
  • A:「今回はデプロイ先はEC2を想定していたので、コンテナは使用していない。また、環境のテストは行っていない。」

この「環境のテスト」という考えがとても面白いなと思いました。テストをする環境とデプロイ先の環境が全く同じであれば環境のテストは必要ないかもしれませんが、これらの環境が異なる場合は何が異なっていてどういった影響があるかなど確認しておく方が良さそうですね。かなり勉強になりました。

おわりに

今回のイベントでは、テストについて自分だけでなく皆が四苦八苦しながら取り組んでいるのだなと感じました。共感を得られて且つ知見の共有にもなる、とても良いイベントでした。イベントを主催してくれた方々、スタッフの方々、参加してくれた方々、皆さん本当にありがとうございました。そして懇親会のお肉が最高だったことは忘れません、ありがとう。

Gitlab CI/CDでLaravelプロジェクトのテスト及びデプロイをする

概要

LaravelプロジェクトをGitlabにPushした際、Pushしたブランチに応じて自動でテストやデプロイを行うようにする。ついでに、テストが通らなかったブランチはメインのブランチに対するマージリクエストを行えないようにする。

ブランチ毎に行う処理

  • master:テスト、本番環境へのデプロイ
  • deploy:テスト、ステージング環境へのデプロイ
  • 上記以外のブランチ:テスト

処理の流れ

以下はPushからデプロイまでの処理の流れ図。

f:id:kkznch:20190404092248p:plain
GitLab CIデプロイフロー

  1. LocalからGitlabにPushする
  2. GitlabCIが実行される
  3. Unitテスト用のDockerコンテナが起動される
  4. Unitテストが実行される
  5. デプロイ用のDockerコンテナが起動される
  6. Envoyコマンドが実行される
  7. デプロイ先(本番環境orステージング環境)でPullされる

実装手順

結構やること多い。やることを列挙しとく。

  • ローカルでやること
    • Gitlabからデプロイ先に接続するための鍵組の作成
    • Dockerの準備
      • Dockerfileの作成
      • Dockerfileをビルドしてイメージを作成
      • DockerイメージをGitlab Container Registryに登録
    • Gitlab-CI設定ファイルの作成
    • デプロイ用タスクランナー設定ファイルの作成
  • デプロイ先(本番環境orステージング環境)でやること
    • デプロイ用ユーザの作成と設定
    • GitlabからClone・Pullするための鍵組の作成
    • リポジトリのCloneと設定
    • Gitlabからデプロイ先に接続するための鍵の設置
  • Gitlabでやること
    • GitlabからClone・Pullするための鍵を登録
    • Gitlabからデプロイ先に接続するための鍵の登録
    • ブランチをProtected branch化

こんな感じでやっていく。

ローカルでやること

Gitlabからデプロイ先に接続するための鍵組の作成

ローカルの任意の場所(以下/path/to/mykeysとする)で以下のコマンドを実行し、Gitlabからデプロイ先へ接続を行うための鍵組を作成する。

$ cd /path/to/mykeys
$ ssh-keygen -t ecdsa -b 521 -f gitlab-deploy-key -C "deploy-key@gitlab.com"
(色々聞かれるので全てEnter)

暗号スイートはECDSAを指定、鍵長は521bitを指定、コメントは任意のコメントを入力する。以下のコマンドで鍵組(秘密鍵、公開鍵)が作成されたことを確認する。

$ ls -l /path/to/mykeys
gitlab-deploy-key
gitlab-deploy-key.pub

これ失くしたらヤバイので、紛失しないようにちゃんと管理すること。

Dockerの準備

Gitlab-CI実行時に起動されるDocekrの準備をする。Dockerイメージの登録先として、Gitlabにmydockerというリポジトリを作成しておくこと。

Dockerfileの作成

ローカルの任意の場所(以下/path/to/mydockerとする)で以下のコマンドを実行し、Dockerfileファイルを作成する。

$ touch /path/to/mydocker/Dockerfile

上記で作成したファイルに以下の内容を記述する。

FROM centos:7
MAINTAINER myname <myname@my_email_address>

RUN echo "include_only=.jp" >>/etc/yum/pluginconf.d/fastestmirror.conf && \
    rpm --import http://ftp.riken.jp/Linux/centos/RPM-GPG-KEY-CentOS-7 && \
    rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7 && \
    rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi

RUN yum -y install epel-release && \
    yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm && \
    yum-config-manager --enable remi-php72 && \
    yum -y update

RUN yum -y install wget git unzip

RUN yum -y install php php-mbstring php-pdo php-mysqlnd php-dom php-posix

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN composer global require "laravel/envoy=~1.0"

今回のDockerfileはLaravelプロジェクトとEnvoyコマンドが動く最低限の環境を構築するための内容になっている。他に必要なものがあれば上記のファイルに適宜追加してね。

Dockerfileをビルドしてイメージを作成

作成したDockerfileから以下のコマンドでDockerイメージを作成する。

$ cd /path/to/mydocker
$ docker build -t registry.gitlab.com/[Gitlabアカウント名]/mydocker .

-tオプションには作成するイメージ名を指定してる。ビルドに少し時間かかるかも(3〜5分くらい)。

DockerイメージをGitlab Container Registryに登録

GitlabにDockerイメージを登録するために以下のコマンドでGitlabにログインする。

$ docker login registry.gitlab.com
(Gitlabアカウント名、パスワードの入力を要求される)

ログイン後、以下のコマンドでDockerイメージを登録する。

$ docker push registry.gitlab.com/[Gitlabアカウント名]/mydocker

ここでも少し時間がかかる(3〜5分くらい)。特にエラーがなければ正常に登録されているはず。

なお、Gitlab公式ページではLaravelプロジェクト直下にDockerfileを作成してビルドしたDockerイメージをLaravelプロジェクトのGitlabリモートリポジトリに登録しているが、今回はDocker用にGitlabリモートリポジトリに作成してそこに登録している。こうすることで、他のプロジェクトでもDockerを利用することが出来る(こういう使い方していいのか分からんけど)。

Laravel プロジェクトとは別のリポジトリに Docker コンテナを push するほうが使い回しが出来て良いかなと思っていたが、逆に使いにくかったので Laravel プロジェクトのリポジトリに push する方が良いことが分かった。

Gitlab-CI設定ファイルの作成

Gitlab-CIではGitlab-CI設定ファイル.gitlab-ci.ymlに記述された内容に沿ってCIが実行される。以下のコマンドでLaravelプロジェクト直下(以下/path/to/myappとする)に.gitlab-ci.ymlファイルを作成する。

$ touch /path/to/myapp/.gitlab-ci.yml

上記で作成したファイルに以下の内容を記述する。

image: registry.gitlab.com/[Gitlabアカウント名]/mydocker

stages:
  - test
  - deploy

test_pupunit:
  stage: test
  services:
    - mysql:latest
  variables:
    DB_HOST: mysql
    DB_USERNAME: root
    MYSQL_DATABASE: homestead
    MYSQL_ROOT_PASSWORD: secret
  script:
    - cp .env.example .env
    - composer install
    - php artisan key:generate
    - php artisan migrate
    - vendor/bin/phpunit

.shared_hidden_key: &before_deploy
  before_script:
    - 'type ssh-agent || yum -y install openssh-clients'
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >~/.ssh/config'

deploy_stg:
  stage: deploy
  <<: *before_deploy
  script:
    - ~/.composer/vendor/bin/envoy run deploy_stg
  environment:
    name: staging
    url: [ステージング環境で公開してるURL]
  when: on_success
  only:
    - develop

deploy_prd:
  stage: deploy
  <<: *before_deploy
  script:
    - ~/.composer/vendor/bin/envoy run deploy_prd
  environment:
    name: production
    url: [本番環境で公開してるURL]
  when: manual
  only:
    - master

image項目では先ほどGitlabに登録したDockerイメージを参照してあげる。あとはテストの項目、デプロイの項目が順に記述されている感じ。あとデプロイ先毎に同じ内容の処理を記述するのがダサい感じがしたので、.shared_hidden_key: &before_deployの項目に処理をまとめて記述しておいて、各デプロイ先の処理部(deploy_stg, deploy_prd)に <<: *before_deployを記述しておく。これでなんとなくスマートな感じがする。

.gitlab-ci.ymlがローカルリポジトリに存在する状態でGitlabにPushするとGitlab-CIが実行されるようになる。しかし今の段階ではちゃんと動かないので、本ブログの手順を全て終えてから最後にPushしてね。

デプロイ用タスクランナー設定ファイルの作成

Gitlab-CIから呼び出されるデプロイ用タスクランナー設定ファイルEnvoy.blade.php/path/to/myapp直下に作成する。

$ touch /path/to/myapp/Envoy.blade.php

上記で作成したファイルに以下の内容を記述する。

@servers(['stg-host' => 'deployer@[ステージング環境のIPアドレス]', 'prd-host' => 'deployer@[本番環境のIPアドレス]'])

@setup
  $app_dir = '/var/www/myapp'
@endsetup

@story('deploy_stg', ['on' => 'stg-host'])
  pull_repository
  run_composer
  run_artisan
  run_npm
@endstory

@story('deploy_prd', ['on' => 'prd-host'])
  pull_repository
  run_composer
  run_artisan
  run_npm
@endstory

@task('pull_repository')
  echo 'Pull repository'
  cd {{ $app_dir }}
  git pull
@endtask

@task('run_composer')
  cd {{ $app_dir }}
  composer update
  composer install --no-dev --optimize-autoloader
@endtask

@task('run_artisan')
  cd {{ $app_dir }}
  php artisan down
  php artisan migrate
  php artisan cache:clear
  php artisan config:cache
  php artisan view:clear
  php artisan up
@endtask

@task('run_npm')
  cd {{ $app_dir }}
  npm run production
@endtask

デプロイ先(本番環境orステージング環境)でやること

デプロイ先(本番環境、ステージング環境)それぞれにログインして以下の作業を行う。

デプロイ用ユーザの作成と設定

rootユーザで以下のコマンドを実行し、デプロイ用のユーザを作成する。

root$ adduser deployer

どうせ公開認証方式でしかログインしないだろうからパスワードの設定しなくてもいいんだけど、念のため設定しておく。

root$ passwd deployer
(任意のパスワードを入力)

deployerユーザが/var/www下でリポジトリをClone・Pull出来るよう、以下のコマンドで権限を与える。/var/wwwがない場合は作成すること。

root$ setfacl -R -m u:deployer:rwx /var/www
GitlabからClone・Pullするための鍵組の作成

deployerユーザで以下のコマンドを実行し、GitlabからClone・Pullを行うための鍵組を作成する。

deployer$ mkdir -p ~/.ssh
deployer$ chmod 700 ~/.ssh
deployer$ ssh-keygen -t ecdsa -b 521
(色々聞かれるので全てEnter)

以下のコマンドで鍵組(それぞれ秘密鍵、公開鍵)が作成されたことを確認する。

deployer$ ls -l ~/.ssh
id_ecdsa
id_ecdsa.pub
リポジトリのCloneと設定

deployerユーザで以下のコマンドを実行し、GitlabからLaravelプロジェクトをCloneする。

deployer$ cd /var/www
deployer$ git clone git@gitlab.com:[Gitlabアカウント名]/myapp.git

CloneしてきたLaravelプロジェクト下にあるstorageにのみ書き込み権限を与える。

deployer$ chmod -R 777 /var/www/myapp/storage

chmodコマンドで-Rオプションつけて777って場所間違えたら大変なことになるので注意。

Gitlabからデプロイ先に接続するための鍵の設置

ここが少しややこしい。手順「ローカルでやること/Gitlabからデプロイ先に接続するための鍵の作成」で作成した鍵のうち公開鍵gitlab-deploy-key.pubをデプロイ先に設置する。以下のコマンドをローカルで実行し、公開鍵を転送する。

$ scp /path/to/mykeys/gitlab-deploy-key.pub deployer@[デプロイ先のIPアドレス]:~/

公開鍵認証使ってる人は上記のコマンドを実行すると特に何も聞かれずに実行完了するけど、使ってない人はパスワード求められるのでパスワードを入力する。さっき設定したパスワードがここで活きるというね、設定しててよかった(小並感)。

次に以下のコマンドをデプロイ先で実行し、転送されてきた公開鍵をauthorized_keysに記述する。あとは適切なアクセス権を付与することで、Gitlabからデプロイ先へ接続可能な状態になる。最後に、転送されてきた公開鍵を削除するのを忘れずに。

deployer$ cat ~/gitlab-deploy-key.pub >> ~/.ssh/authorized_keys
deployer$ chmod 600 ~/.ssh/authorized_keys
deployer$ rm ~/gitlab-deploy-key.pub

コマンドの実行場所(ローカルとデプロイ先)を間違えないように注意しよう。

Gitlabでやること

ここからはブラウザでGitlabのページを開いて作業を行う。ローカルにあるLaravelプロジェクト/path/to/myappのリモートリポジトリはGitlabに作成済みであるとする。

GitlabからClone・Pullするための鍵を登録

ここもややこしい。手順「デプロイ先でやること/GitlabからClone・Pullするための鍵の作成」で作成した鍵のうち公開鍵id_ecdsa.pubをGitlabに登録する。以下のコマンドをデプロイ先で実行し、出力された値をコピーする。

deployer$ cat ~/.ssh/id_ecdsa.pub
(なんか出力されるので範囲選択してコピーする)

LaravelプロジェクトのGitlabリモートリポジトリページからProject > Settings > Repositoryと辿っていき、Deploy Keysの項目で登録する鍵のタイトルを任意で入力、それと先ほどコピーした公開鍵の内容をペーストする。以下のような感じ。入力後はAdd keyボタンを押して登録する。

f:id:kkznch:20190404092347p:plain
GitLabデプロイ用公開鍵の設置

Gitlabからデプロイ先に接続するための鍵の登録

またもやここもややこしい。手順「ローカルでやること/Gitlabからデプロイ先に接続するための鍵の作成」で作成した鍵のうち秘密鍵gitlab-deploy-keyをGitlabに登録する。以下のコマンドをローカルで実行し、出力された値をコピーする。

$ cat /path/to/mykeys/gitlab-deploy-key
(なんか出力されるので範囲選択してコピーする)

LaravelプロジェクトのGitlabリモートリポジトリページからProject > Settings > CI/CDと辿っていき、Secret variablesの項目で登録する鍵のタイトルに「SSH_PRIVATE_KEY」と入力し(重要!!)、先ほどコピーした秘密鍵の内容をペーストする。「Protected」のトグルはよく分からんけどオンにしておく。以下のような感じ。入力後はSave variablesボタンを押して登録する。

f:id:kkznch:20190404092520p:plain
GitLabデプロイ用秘密鍵の設置

鍵のタイトルに「SSH_PRIVATE_KEY」を入力したのは、手順「ローカルでやること/Gitlab-CI設定ファイルの作成」で作成したGitlab-CI設定ファイル内で環境変数として使用するため。鍵のタイトルとGitlab-CI設定ファイルに記述した環境変数名は統一すれば何でも良いのだけど、分かりやすいように今回はこのタイトルにした。

特定のブランチをProtected branch化

最後の手順。Gitlab-CIでテストを実行した後、テストが通ったブランチをメインのブランチにマージしないよう設定する(正確にはマージリクエストが出来ないようにする、かな?)。

LaravelプロジェクトのGitlabリモートリポジトリページから、Project > Settings > Repositoryと辿っていき、Protected Branchesの項目でProtected branch化したいブランチを選択する。おそらく本番環境で使用するmasterブランチはデフォルトでProtected branchになってるので、今回はステージング環境で使用するdevelopブランチ辺りをProtected branch化する。以下のような感じ。

f:id:kkznch:20190404092639p:plain
GitLabで特定のブランチを保護

Gitlab-CI実行

ここまで長い工程をお疲れ様でした。最後に、ローカルからLaravelプロジェクト/path/to/myappをPushし、Gitlab-CIが実行されるか確認しよう。このとき、本番環境にデプロイするならmasterブランチ、ステージング環境にデプロイするならdevelopブランチでPushする。最初に説明したが、developブランチはPushすると自動でデプロイされるが、masterブランチはPushしても自動でデプロイはされない。masterブランチをデプロイする際はLaravelプロジェクトのGitlabリモートリポジトリページからテストが通っていることを確認し、手動でデプロイすること。

$ cd /path/to/myapp
$ git push -u origin master

感想

主にGitlab公式ページを参考に作業を行ったが、実際に手を動かして理解できた。作業自体も時間がかかったが、この記事を書くのにも時間かかった...。自分のための記録として、また他の人の参考として、本記事が役に立つと嬉しい。間違い等があれば指摘おなしゃす、

参考

LaravelでS3へファイルをアップロード・参照する

概要

LaravelでアップロードされたファイルをS3に保存・参照する。

ファイルアップロード時の処理は下図の通り、クライアントからLaravelを通ってS3に保存される。

f:id:kkznch:20190404093027p:plain
LaravelからS3へアップロード

ファイルを参照する際は下図の通り、Laravelが対象となるファイルのURLをS3から取得してページにリンクする。URLからS3上のファイルを参照するために、対象となるファイルはPublicに公開される必要がある。

f:id:kkznch:20190404092903p:plain
LaravelからS3のファイルを参照

環境

  • Laravel 5.5.36

Laravelが動作するEC2、ファイル保存・参照先となるS3バケットは作成済みとする。

手順

AWS側の操作

AWSコンソールへログインし、以下の操作を行う。

IAMユーザーの作成

サービス「IAM」からサイドバーの「ユーザー」をクリックし、続いて以下の操作を行う。

  1. 「ユーザーを追加」をクリックする
  2. 「ユーザー名」を入力する
  3. 「プログラムによるアクセス」にチェックを入れる
  4. 「次のステップ:アクセス権限」をクリックする
  5. 「ユーザーをグループに追加」を選択する
  6. 「次のステップ:確認」をクリックする
  7. 「ユーザーの作成」をクリックする

ここでユーザの作成が完了する。このとき、作成したユーザーのセキュリティ認証情報が記述されたファイル(CSV)がダウンロード出来るので、ダウンロードしておく。

IAMユーザのアクセス権限を設定

サービス「IAM」からサイドバーの「ユーザー」をクリックし、続いて以下の操作を行う。

  1. 作成したユーザーをクリックする
  2. 「アクセス権限」タブを選択し、「インラインポリシー」をクリックする
  3. 「ビジュアルエディタ」タブにある項目を以下のように入力する
    1. 「サービスの選択」:S3
    2. 「アクション」:
      • 「GetObject」にチェック
      • 「PutObject」にチェック
      • 「DeleteObject」にチェック
      • 「PutObjectAcl」にチェック
    3. 「リソース」:
  4. 「Review policy」をクリックする
  5. 「名前」を入力する
  6. 「Create a policy」をクリックする

ちなみにJSONは以下のようになる。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::mybucket/myprefix/*"
        }
    ]
}

Resource要素の末尾に*がないと指定したプレフィックス(今回はmyprefix)以下を操作する権限がないと言われるので注意!

Laravel側の操作

パッケージをインストール

Laravelプロジェクトフォルダ下で以下のコマンドを入力する。

$ composer require league/flysystem-aws-s3-v3

これによりLaravelのファイルシステムでファイルの保存・参照先をS3に向けるためのパッケージがインストールされる。

.envを編集

.envファイルに以下を追記する。

AWS_S3_KEY=[AWS S3接続用ユーザのAccess Key ID]
AWS_S3_SECRET=[AWS S3接続用ユーザのSecret Key]
AWS_S3_REGION=[AWS S3設置リージョン]
AWS_S3_BUCKET=[AWS S3のバケット名]

config/filesystems.phpを編集

config/filesystems.phpを以下のように編集する。

<?php
return [
    'default' => 'local',
    'cloud' => 's3',

    'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],

        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL').'/storage',
            'visibility' => 'public',
        ],

+        's3' => [
+            'driver' => 's3',
+            'key' => env('AWS_S3_KEY'),
+            'secret' => env('AWS_S3_SECRET'),
+            'region' => env('AWS_S3_REGION'),
+            'bucket' => env('AWS_S3_BUCKET'),
+        ],

    ],

];

Controllerの作成

以下のコマンドでControllerを作成する。

$ php artisan make:controller UploadContentController

app/Http/Controllers/UploadContentController.phpを以下のように編集する。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class UploadContentController extends Controller
{
    public function index()
    {
        return view('upload');
    }

    public function store(Request $request)
    {
        $this->validate($request, ['myfile' => 'required|image']);

        $image = $request->file('myfile');

        /**
         * 自動生成されたファイル名が付与されてS3に保存される。
         * 第三引数に'public'を付与しないと外部からアクセスできないので注意。
         */
        $path = Storage::disk('s3')->putFile('myprefix', $image, 'public');

        /* 上記と同じ */
        // $path = $image->store('myprefix', 's3');

        /* 名前を付与してS3に保存する */
        // $filename = 'hoge.jpg';
        // $path = Storage::disk('s3')->putFileAs('myprefix', $image, $filename, 'public');

        /* ファイルパスから参照するURLを生成する */
        $url = Storage::disk('s3')->url($path);

        return redirect()->back()->with('s3url', $url);
    }
}

Viewの作成

resources/views/upload.blade.phpを作成し、以下のようにする。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Upload S3 Test</title>
</head>

<h1>S3アップロードテスト</h1>

{!! Form::open(['url' => '/upload', 'method' => 'post', 'class' => 'form', 'files' => true]) !!}

<div class="form-group">
{!! Form::label('myfile', 'Upload a file') !!}
{!! Form::file('myfile', null) !!}
</div>

<div class="form-group">
{!! Form::submit('Upload') !!}
</div>

{!! Form::close() !!}

@if (session('s3url'))
    <h1>いまアップロードしたファイル</h1>
    <img src="{{ session('s3url') }}">
@endif
</html>

考察

LaravelからS3に対してファイルのアップロード及びファイルの参照を行うことができた。Controller内でファイルアップロード時のS3のプレフィックスを指定している箇所があるが、毎回同じプレフィックスを指定するの面倒くさいな。何かいい方法ないかな。

参考

PhpStorm+phpcsでシンタックスチェック

概要

PhpStormのデフォの機能だけでシンタックスチェック出来るかと思って色々探してみたが、見つからず。 諦めてphpcsをインストールしてそれを使ってシンタックスチェックをするようにしてみる。

手順

参考にした記事とまんま同じこと書いてるだけ。

Terminalでやること

composerをインストールする

phpcsをインストールするためにcomposerコマンドを使用するので、brewコマンドでcomposerをインストールする。

$ brew install homebrew/php/composer

phpcsをインストールする

composerコマンドでphpcsをインストールする。 システム全体で使用できるようにglobalにインストールする。

$ composer global require "squizlabs/php_codesniffer=*"

試しに実行してみる。

$ phpcs -i
The installed coding standards are PEAR, Zend, PSR2, MySource, Squiz and PSR1

出来てるっぽいのでオッケー。 この後でPhpStormの設定をする際にphpcsのパスを入力する必要があるので、以下のコマンドでパスを確認しておく。

$ where phpcs
/Users/[ユーザ名]/.composer/vendor/bin/phpcs

PhpStormでやること

Languages & Flameworksの設定

"PhpStorm"->"Preferences"を開く。 サイドバーの"Languages & Frameworks"->"PHP"->"Code Sniffer"を選択する。 "Configuration"の右側にある"..."(何だこれ)をクリックする。 "PHP Code Sniffer (phpcs) path"欄の右側にある入力欄に先ほどのphpcsのパスを入力する。 "Validate"をクリックしてパスを検証、特に問題がなければ"OK"をクリックする。

PHP Code Sniffer validationの設定

"PhpStorm"->"Preferences"を開く。

サイドバーの"Editor"->"Inspections"を選択する。 "PHP"->"PHP Code Sniffer validation"の右側にあるチェックボックスにチェックを入れ、"Options"->"Coding standard"の右側にあるリロードマークをクリックし、選択欄から"PSR2"(ここに関してはお好みで)を選択する。

以上の設定でシンタックスチェックが行われるが、デフォだとどの箇所が規約に沿っていないのかが分かりづらいので、規約に沿っていない箇所の色を変えて分かりやすくする。 サイドバーの"Editor"->"Inspections"を選択する。 "PHP"->"PHP Code Sniffer validation"を選択した状態で、"Options"->"Show warnings as"の右側にある選択欄から"Edit Serverities"を選択する。 "+"ボタンをクリックしてお好みで色を設定し、"OK"をクリックする。

最後に"Preferences"ウィンドウ右下にある"OK"をクリック、これで準備OK。

試しに使ってみる

PSR2に準拠してない行の上にカーソルを合わせると怒られている内容を確認することが出来る。

参考

Laradock+PhpStormでXdebug

概要

Laradock+PhpStormな環境でXdebugを使う設定をするよ。

環境

手順

Laradockの設定、PhpStormの設定と順を追って設定していく。

Laradock

.envの設定

laradock/.envの項目を以下のように設定する。 もしかするとデフォで設定されてるかもだが、確認すべし。

WORKSPACE_INSTALL_XDEBUG=true
PHP_FOM_INSTALL_XDEBUG=true

php-fpmの、workspaceの設定

laradock/php-fpm/xdebug.inilaradock/workspace/xdebug.iniを以下のように設定する。

xdebug.remote_host=docker.for.mac.localhost
xdebug.remote_connect_back=0
xdebug.remote_port=9001
xdebug.idekey=PHPSTORM

xdebug.remote_autostart=1
xdebug.remote_enable=1
xdebug.cli_color=1
xdebug.profiler_enable=0
xdebug.profiler_output_dir="~/xdebug/phpstorm/tmp/profiling"

xdebug.remote_handler=dbgp
xdebug.remote_mode=req

xdebug.var_display_max_children=-1
xdebug.var_display_max_data=-1
xdebug.var_display_max_depth=-1

xdebug.remote_portが9000だとphp-fpmと衝突するため、9001にしている。 あと他のサイトだとxdebug.remote_connect_backが1でも動作するっぽいけど、自分の環境だと動かなかったので0にしている。

スケジューラのコメントアウト

Laradockはデフォでスケジューラが組み込まれており、定期的にphp artisanなコマンドがcronで呼ばれるという罠が仕掛けられている(ちゃんとした使いみちは知らん)。 こいつはデバッガに引っかかってしまうため、呼び出されないように設定する。

laradock/workspace/crontab/laradockを以下のようにコメントアウトする。

# * * * * * laradock php /var/www/artisan schedule:run >> /dev/null 2>&1

これ確か前の勉強会の時にサボさんが言ってた奴だよな...。

dockerイメージの再構築

以下のコマンドを入力してdockerイメージを再作成する。

$ docker-compose build workspace php-fpm

PhpStorm

Languages & Flameworksの設定

"PhpStorm"->"Preferences"を開く。 サイドバーの"Languages & Frameworks"->"PHP"->"Servers"を選択する。 "Languages & Frameworks"の"+"をクリックする。

各項目の設定を以下のように行う。

  • "Name": laradock(なんでもよい)
  • "Host": localhost
  • "Port": 80
  • "Debugger": Xdebug
  • "User path mapping": チェックを入れる
  • パスマッピング(ローカルPCとdockerでリンクされるプロジェクトのパス)
    • "File/Directory": ローカルPC上のlaravelプロジェクトのパス
    • "Absolute path on the server": docker上のlaravelプロジェクトのパス

Debugの設定

"PhpStorm"->"Preferences"を開く。 サイドバーの"Languages & Frameworks"->"PHP"->"Debug"を選択する。 "Xdebug"項目中の項目を以下のように設定する。

  • "Debug port": 9001

PHP Remote Debugの設定

"Run"->"Edit Configurations..."を開く。 サイドバーの"Defaults"->"PHP Remote Debug"を選択する。

各項目の設定を以下のように行う。

  • "Filter debug connection by IDE key": チェックを入れる
  • "Server": laradock("Language & Framework"で付けた名前)
  • "IDE key(session id)": PHPSTORM

以上で設定終わり。

実行してみる

PhpStormで任意のコードにブレークポイントを仕掛ける。 ブラウザからそのコントローラに対応するページにアクセスすると、PhpStormのデバッガが反応してくれる。

参考

macにDockerをインストール

概要

mac上でdockerを動かしたい。 brewコマンドでdockerをインストールするとdocker単体しかインストールされないため、brew caskコマンドでdockerをインストールする。

環境

手順

Docker.appのインストール

以下のコマンドでDocker.appをインストールする。

$ brew cask install docker

この時点ではdockerコマンドを叩いても使用できない。

$ docker --version
zsh: command not found: docker

Docker.appを起動

Docker.appを起動する。 色々設定した後にdockerコマンドが使用できるようになる。

$ docker --version
Docker version 17.09.1-ce, build 19e2cf6

感想

dockerよくわからんまま使ってるので少し勉強しないといけんなー。

「モブプログラミングでワイワイする会 その2.5」に参加して

[TDDYY会] モブプログラミングでワイワイする会 その2.5

2017/12/26(Tue)

YWT

Y

  • モブプログラミング
    • ある問題に対して皆で協力して挑む
    • PCと画面は一つずつで、ドライバー(PC操作する人)が一人、それ以外はナビゲータ
  • テスト駆動開発
    • 何をどうテストするか定義し、テストに沿って実装する
  • FizzBuzz問題
    • 3の倍数のときに"Fizz"を出力
    • 5の倍数のときに"Buzz"を出力
    • 15の倍数のときに"FizzBuzz"を出力
  • 動作をToDoリストとして列挙する
    • ToDoリストの更新はどのタイミングでもよい
  • タイムライン
    • 時間軸(横軸)に沿って何をやったか洗い出す
    • その時間毎の自分のモチベーションの上下を縦軸に線を描く

W

  • モブプログラミング楽しい
    • 考える時間はなるべくなくして、手を動かしながら考える
    • みんなでワイワイできる
    • 話し合いながら進めることで、お互いの知識をシェア出来て非常に良い
  • テスト駆動開発
    • 先にテストを書くことで何を実装するのかが明確になる
    • テスト書くの面倒と思っていたが、モブプログラミングと組み合わせると楽しい
    • 単体テストの方法は分かったが、結合テストの方法がちょっとよくわからん

T

  • テストの方法について勉強する
  • テストをするためのモジュールについて調べておく
  • 次回のtddyy会も開催する

参考