- 投稿日:2021-03-02T22:56:42+09:00
プログラミング初心者でもできる laravel で hello world 画面に表示させるまでの道のり
前提
- Macbookでの操作になります。
- ターミナルがなんなのかがわかるくらいのレベルの人向けの記事です。
- laravelが使える段階まで環境構築を済ませていること。
- php, homebrew, compser をインストールし終わって環境構築を完了している人
- ここでは初心者向けに難しい単語などをイメージができるような説明をするため
実際の意味とは異なる説明をするかもしれません。上級者の方は見て見ぬ振りでお願いします。
プロジェクトの作成
いきなり専門用語でてきますね。
プロジェクトの意味をなんとなくイメージできるように一つ例えをしましょう。あなたはパキラの種を持っていました。
家の中でパキラを咲かせたいです。
まずやらなければいけないのは器を用意することです。
器がないと何も始まりません。
器があって初めて土を入れられます。プロジェクトはその器だとお考えください。
そしてhello worldを表示させることはパキラ育てること(目的)だと思ってください。チューリップを育てたい(hello meの表示をしたい)って思った場合でも
やはりまずは器(プロジェクト)がないと何も始まりません。
まずは器(プロジェクト)を手に入れましょう。これでだいたいイメージはつきましたでしょうか?
では器を手に入れる(プロジェクトを作成する)にはターミナルで下記のコマンドをコピペしましょう。
※現在いるディレクトリにプロジェクトが作成されるため、プロジェクトをおきたい場所に移動してから
下記のコマンドをいれましょう。composer create-project laravel/laravel pakira
pakiraはプロジェクト(器)の名前です。
pakiraの部分は何をつけても構いません。練習の時は。動作確認
※ここからは器の話は忘れてくださいね?頭を切り替えていきましょう。
作ったプロジェクトにディレクトリを移動し下記のコマンドを実行する
php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
みたいな結果が出てくるので
そのurlをchromeのurl欄にコピペする
おそらくほとんどの人は http://127.0.0.1:8000 になってるはず。
止める時は キーボードのcontrol + c
で
自分はlaravelのバージョンが8.29.0なのでこう言う画面になってますがバージョンによって表示される内容がちょっと変わったりするそうです。
エラーとかでなければ成功です!APP_KEYの生成
これも専門的な言葉が出てきますね。とりあえず、laravel取り入れたらこれをやるものなんだって覚えましょう
(他の人laravelをcloneしてきた時も同じ。これを行ってください)
これがないとうまく使えない機能とかあります。そのうち、あれ?なんで動かないんだ?って
一日中原因調査する羽目になったりするかもしれないので。php artisan key:generateこれをやると
.env
っていうファイルの中のAPP_KEY=
っていうところに英数字が追加されてます。
追加されてたら成功!heroku使う予定がある方
heroku
というサービスを使う予定であれば
heroku側でもこのkeyの設定がないとうまく動かないので
※heroku使わない方はここはスキップしてください。heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show)heroku関連の設定したほうがいいもの
エラーがweb画面で見れるようにする
config/app.php の
'debug' => (bool) env('APP_DEBUG', false),
って書いてあるところ
こいつをfalseじゃなくてtrueにすると見れるようになるはず。
42行目あたりにこの記述があると思いますが
なかったらバージョンが変わったことによっての影響なので別途必要に応じて調べれくださいconfig/app.php'debug' => (bool) env('APP_DEBUG', true),Procfileを作成
これも
手動でもできますしコマンドでもできます。
ここではコマンドを使って作成する方法を紹介します。
やりたいことはアプリフォルダ直下にProcfileって言う名前のファイルを作ってコピペするだけです。touch Procfileecho 'web: vendor/bin/heroku-php-apache2 public/' > Procfile
- 投稿日:2021-03-02T19:14:53+09:00
flysystem-aws-s3-v3は~1.0を使いましょう
概要
LaravelからAWS S3に画像をアップロードをしようとしたら起きた事象です。
Class 'League\Flysystem\AwsS3v3\AwsS3Adapter' not found
原因
LaravelのReadableを見たら、
Composerパッケージ
S3やSFTPドライバーを使用するときは、事前にComposerパッケージマネージャーを介して適切なパッケージをインストールする必要があります。
Amazon S3: league/flysystem-aws-s3-v3 ~1.0と書かれておりました。
何も考えずにインストールしたら、
composer require league/flysystem-aws-s3-v3
2.0が入ってしまっていたので、ダウングレードします。
composer require league/flysystem-aws-s3-v3 ~1.0
無事直せました。
- 投稿日:2021-03-02T15:33:49+09:00
初学者がCircleCI/CDを実装する上で感じた注意点
前提
・以下の記事に書かれていることを理解している
いまさらだけどCircleCIに入門したので分かりやすくまとめてみた・Laravelを用いたアプリケーションに対してCI/CDを実行する
CI・・・Githubプッシュ時にPHPUnitが自動で実行される(テスト用データベースにSQLiteのインメモリ機能を使用)
CD・・・Dockerfileより自前のイメージを作成し、そのイメージをOrbsを利用しECRへ自動プッシュし、そしてそれをECSへ自動デプロイする環境
PHP Laravel PHPUnit SQLite Docker 7.4.5 7.28.4 8.5 3.28.0 19.03.13 .circleci/config.yml
version: 2.1 orbs: aws-ecr: circleci/aws-ecr@6.5.0 aws-ecs: circleci/aws-ecs@1.2.0 jobs: test: docker: - image: circleci/php:7.4.5-node-browsers working_directory: ~/intro-app steps: - checkout - run: name: Update apt-get command: sudo apt-get update - restore_cache: keys: - v1-dependencies-{{ checksum "composer.json" }} - v1-dependencies- - run: name: Install PHP libraries command: composer install -n --prefer-dist - save_cache: paths: - ./vendor key: v1-dependencies-{{ checksum "composer.json" }} - run: name: Install three libraries related to GD command: sudo apt-get install -y wget git unzip libpq-dev libfreetype6-dev libjpeg62-turbo-dev libpng-dev - run: name: Support Freetype2 and jpeg command: sudo docker-php-ext-configure gd --with-freetype --with-jpeg - run: name: Install GD library command: sudo docker-php-ext-install -j$(nproc) gd - run: name: Generate php artisan key command: php artisan key:generate --env=testing - run: name: Run PHPUnit command: vendor/bin/phpunit workflows: test_and_deploy: jobs: - test - aws-ecr/build-and-push-image: requires: - test context: AWS_ECR_ECS repo: intro-app_circleci tag: '${CIRCLE_SHA1}' filters: branches: only: master - aws-ecs/deploy-service-update: requires: - aws-ecr/build-and-push-image context: AWS_ECR_ECS family: 'intro-app' cluster-name: 'intro-app' service-name: 'intro-app' container-image-name-updates: 'container=intro-app,image-and-tag=${AWS_ECR_ACCOUNT_URL}/intro-app_circleci:${CIRCLE_SHA1}' filters: branches: only: masterCIに関するエラー
ダミーファイルを生成できない
CircleCIのテスト時に、ダミーファイルを使用した箇所全てにエラーが表示された。
UploadedFile::fake()->image('photo.jpg'),Tests\Feature\InformationControllerTest::testStore Call to undefined function Illuminate\Http\Testing\imagecreatetruecolor()このメソッドが定義されているIlluminate\Http\UploadedFileクラスをコンテナ内で使うには、PHP GDというPHPのライブラリが必要なので、CircleCI環境下にもインストールしてあげる。
PHP GDのインストールは以下の記事を参考にするとうまくいく(他の記事ではなかなかうまくいかないので要注意)
Docker上でPHP拡張モジュール『GD』を有効化する.circleci/config.ymlでのインストール箇所
- run: name: Install three libraries related to GD command: sudo apt-get install -y wget git unzip libpq-dev libfreetype6-dev libjpeg62-turbo-dev libpng-dev - run: name: Support Freetype2 and jpeg command: sudo docker-php-ext-configure gd --with-freetype --with-jpeg - run: name: Install GD library command: sudo docker-php-ext-install -j$(nproc) gdCDに関するエラー
1 Orbsはワークフロー内で使用しなければならない
一度、Orbsを以下のようにjobsの中に書いてみたことがある。
jobs: test: // 省略 deploy: steps: - aws-ecr/build-and-push-image: requires: - test context: AWS_ECR_ECS repo: intro-app_circleci tag: '${CIRCLE_SHA1}' filters: branches: only: master - aws-ecs/deploy-service-update: requires: - aws-ecr/build-and-push-image context: AWS_ECR_ECS family: 'intro-app' cluster-name: 'intro-app' service-name: 'intro-app' container-image-name-updates: 'container=intro-app,image-and-tag=${AWS_ECR_ACCOUNT_URL}/intro-app_circleci:${CIRCLE_SHA1}' filters: branches: only: master workflows: test_and_deploy: jobs: - test - deploy: requires: testこのように設定すると、「aws-ecr/build-and-push-image」や「aws-ecs/deploy-service-update」はコマンドではない!と怒られる(stepsにはCI環境上で行うコマンドなどを記述する。jobsの下にstepsを配置するのはマスト)。
よってOrbsはworkflow内に記述する。
2 Orbsのパラメータに注意を払う
Orbsのパラメータはいろいろ存在する。
aws-ecr/build-and-push-imageのパラメータ
パラメータ 説明 必須 デフォルト aws-access-key-id アクセスキー NO AWS_ACCESS_KEY_ID aws-secret-access-key シークレットアクセスキー NO AWS_SECRET_ACCESS_KEY account-url ECRアカウントURL NO AWS_ECR_ACCOUNT_URL repo ECRレポジトリ名 YES なし region リージョン NO AWS_REGION tag タグ NO latest dockerfile ECRへプッシュするイメージを作成するためのDockerfileの指定 NO Dockerfile context コンテキスト no なし aws-ecs/deploy-service-updateのパラメータ
パラメータ 説明 必須 デフォルト aws-access-key-id アクセスキー NO AWS_ACCESS_KEY_ID aws-secret-access-key シークレットアクセスキー NO AWS_SECRET_ACCESS_KEY family タスク定義名 YES なし cluster-name クラスター名 YES なし service-name サービス名 NO 空文字列 container-image-name-updates デプロイ先のコンテナ名とデプロイするイメージ名 NO 空文字列 context コンテキスト no なし 注意するポイントは以下の2つ。
パラメータにはデフォルト値が設定されている
デフォルト値とCirclCIの環境変数が一致している場合、パラメータの記述を省略しても、そのパラメータに設定したCircleCIの環境変数が適用される。
contextを設定しなければCircleCIの環境変数を参照できない
ここはかなり詰まってしまったところだ。
contextの中に環境変数を設定した場合、パラメータにcontextを設定しなければ、そのcontext内の環境変数を参照できない。3 vendorディレクトリの不足
デプロイには成功したが、コンテナが落ちてしまった。CloudWatchでコンテナ内で起きたエラーをチェックしてみると以下のエラーメッセージが検出された。
Warning: require(/workdir/vendor/autoload.php): failed to open stream: No such file or directory in /workdir/artisan on line 18このエラーは、「vendorディレクトリが存在しない」ために起きたもの。
リモートリポジトリにプッシュする際、vendorディレクトリは含まれない設定になっているため(.gitignoreに記述してある)、本番環境にデプロイしたLaravelのコード群の中にもvendorディレクトリは存在しない。ではどうするか?
vendorディレクトリは「composer install」でインストールできるので、Dockerfileに以下のように記述する。RUN composer install補足
「composer install」をDockerfile内のどこにどうやって書けばいいのか悩んでしまったので、その経緯を一応細かく書いておきます。(めちゃくちゃ基礎的なことを理解できていませんでした)
悩んだ原因は、Dockerfileの「RUN」コマンドと「CMD」コマンドを誤って解釈していたからでした。
僕の間違った解釈
RUN・・・イメージを生成するためだけのコマンド
CMD・・・コンテナ内で実行するコマンド正しい意味
RUN・・・コンテナ内で実行するコマンド
CMD・・・コンテナ起動時一度だけ実行されるコマンド上記のように解釈していたので、もうCMDコマンドはサーバーを立ち上げるために一度使っているから、どうやって「composer install」を実行すればいいのか?と悩みました。。。
以下の記事が大変参考になりました。
僕はイメージのbuildを間違って捉えていました。。。
DockerのRUNとCMDの違い
- 投稿日:2021-03-02T11:11:04+09:00
SQLiteを使ったテストで初学者がはまったエラー ~Laravel~
前提
テスト用データベースはSQLiteインメモリを使用しています。
環境
PHP Laravel PHPUnit SQLite 7.4.5 7.28.4 8.5 3.28.0 エラー内容 「リレーションが辿れない」
前提
SQLiteは以下のデータ型の値しか格納しない。
型 内容 INTEGER 符号付整数。1, 2, 3, 4, 6, or 8 バイトで格納 NUMERIC 負号付きの整数 (1、2、3、4、6、8バイト) REAL 浮動小数点数。8バイトで格納 TEXT テキスト。UTF-8, UTF-16BE or UTF-16-LEのいずれかで格納 NONE カラムにデータを指定しなかった場合この型になる 以前Laravelで書いていたマイグレーションファイルの一部はこんな感じ。
profilesテーブル
/** * Run the migrations. * * @return void */ public function up() { Schema::create('profiles', function (Blueprint $table) { $table->increments('id'); $table->unsignedInteger('user_id'); $table->string('name'); $table->text('introduction'); $table->timestamps(); $table->foreign('user_id')->references('id')->on('users'); }); }profilesテーブルのuser_idカラムとusersテーブルidカラムで紐付かせている。
エラー
テストする際にこのリレーションの箇所でサーバーエラーが連発した。ここの紐づきだけでなく、他の全てのリレーションを辿るアクションでサーバーエラーが発生した。
ここでかなり詰まってしまった。原因が分からない。。。原因
いろいろ調べた結果、SQLiteがサポートしている型にエラーの原因が存在することが判明した。
SQLiteのサポートしている型一覧
サポートしている型 実際にSQLiteが格納する型 INT
INTEGER
TINYINT
SMALLINT
MEDIUMINT
BIGINT
UNSIGNED BIG INT
INT2
INT8INTENGER CHARACTER(20)
VARCHAR(255)
VARYING CHARACTER(255)
NCHAR(55)
NATIVE
CHARACTER(70)
NVARCHAR(100)
TEXT
CLOBTEXT NUMERIC
DECIMAL(10,5)
BOOLEAN
DATE
DATETIMENUMERIC REAL
DOUBLE
DOUBLE PRECISION
FLOATREAL BLOB NONE どういうことかというと、テーブル作成の際にカラムの型を指定をするが、そのカラムの型がSQLiteでは使用できない型である場合、SQLite自身がSQliteでも扱えるデータ型に強制的に変換し、データを格納する。
表の左側が変換対象のカラムの型、表の右側は変換後の型。これを踏まえて上のマイグレーションファイルをもう一度確認してみると、外部キーに設定しているuser_idカラムの型は「unsignedInttenger」。
SQLiteを見てみると、「UNSIGED BUG INT」は存在するが、「UNSIGNED INT」は存在しない。つまり外部キーに設定したカラムの型は、SQLiteではサポートされていなかったということ。
したがってprofilesテーブルのuser_idカラムの値はINTENGERと扱われず、その結果リレーションメソッドを用いても紐づきを辿ることができず、サーバーエラーになったっぽい。解決案
外部キーカラムを「UNSIGNED INT」型にしてしまえばよい。
僕はLaravel7で新しく導入された外部キーのフォーマットにしたがってマイグレーションファイルを書き換えた。
profilesテーブル(変更後)
/** * Run the migrations. */ public function up(): void { Schema::create('profiles', function (Blueprint $table) :void { $table->id(); $table->foreignId('user_id')->constrained(); $table->string('name'); $table->text('introduction'); $table->timestamps(); }); }変更前の外部キー設定
$table->unsignedInteger('user_id');$table->foreign('user_id')->references('id')->on('users');変更後の外部キー設定
$table->foreignId('user_id')->constrained();この変更された外部キー設定の特徴は、
・1行で外部キー設定が完了する(テーブル名とカラム名が規約通りではない場合、constrainedの引数にテーブル名を指定する)
・この外部キーのカラムの型は自動的に「unsignedBigInteger」となるしたがって、このフォーマットにしたがって外部キー設定をすることで外部キーカラムの型は「UNSIGNED BIG INT」型になり、SQLiteのサポート範囲内となり、きちんとINTENGER型としてデータを格納してくれる。
結果、リレーションを辿ることができた。
補足
ミドルウェアにて以下のポリシーを用いてアクセス制限をしていた。/** * プロフィール編集の権限があるかチェック * * @param User $user * @return mixed */ public function view(User $user) { $profile = $user->profiles()->first(); return $user->id === $profile->user_id; }SQLiteを使用したテストのときだけこのポリシーを通過できなかった。
「===」を使って厳密な型比較せず、「==」に変更した場合はクリアした。
外部キーをunsignedBigIntengerにして、SQLiteにIntengerとして扱ってもらったが、厳密な型比較をすると、なぜか差異がでるそう。。。ここらへんはまだ理解していません。。。最後に
このように対処することで解決致しましたが、何か間違いがあるかもしれません。
何かお気づきの方いらっしゃいましたら、気軽にコメントのほどよろしくお願い致します。
- 投稿日:2021-03-02T08:21:25+09:00
With スコープの外の変数使えない
このように書く。
function($query) use (変数名) {}
- 投稿日:2021-03-02T08:21:25+09:00
With スコープの外の変数使えないので使えるようにするには
このように書く。
function($query) use (変数名) {}