20200627のlaravelに関する記事は8件です。

Laravel MySQL DBのカラム名を途中で変更する

目的

  • Laravelにて新規作成後のDBのカラム名の変更方法をまとめる

実施環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.5)
ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
プロセッサ 2 GHz クアッドコアIntel Core i5
メモリ 32 GB 3733 MHz LPDDR4
グラフィックス Intel Iris Plus Graphics 1536 MB
  • ソフトウェア環境
項目 情報 備考
PHP バージョン 7.4.3 Homwbrewを用いて導入
Laravel バージョン 7.0.8 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする

前提情報

  • MySQLを使用しているが確認箇所以外はそのほかのRDSでも作業内容は変わらない。
  • カラム名を変更するとLaravelアプリで自分で実装したデータ取得処理を変更しないといけない場合があるので注視する。
  • すでに存在するカラムの名前を変更する際の方法を記載する。
  • 本方法と応用するとカラムタイプなどの変更可能となる。
  • 公式ドキュメントに記載されている内容を元に自分なりにまとめてみる。

概要

  1. ライブラリのインストール
  2. マイグレーションファイルの作成と記載
  3. マイグレート
  4. 確認

詳細

  1. ライブラリのインストール

    1. アプリ名ディレクトリで下記コマンドを実行してライブラリをインストールする。

      $ composer require doctrine/dbal
      
  2. マイグレーションファイルの作成と記載

    1. アプリ名ディレクトリで下記コマンドを実行してマイグレーションファイルを作成する。

      $ php artisan make:migration rename_変更する前のカラム名_to_変更した後のカラム名_on_所属テーブル名_table --table=所属テーブル名
      
    2. アプリ名ディレクトリで下記コマンドを実行してマイグレーションファイルを開く。

      $ vi database/migrations/YYYY_MM_DD_XXXXXX_rename_変更する前のカラム名_to_変更した後のカラム名_on_所属テーブル名_table.php
      
    3. マイグレーションファイルを下記の様に修正する。(public function up()にはマイグレーションにより実行したい処理(今回だとカラムのリネーム)処理を記載する。public function down()にはロールバックで実行したい(カラムのリネームを直す)処理)

      database/migrations/YYYY_MM_DD_XXXXXX_rename_変更する前のカラム名_to_変更した後のカラム名_on_所属テーブル名_table.php
       <?php
      
      use Illuminate\Database\Migrations\Migration;
      use Illuminate\Database\Schema\Blueprint;
      use Illuminate\Support\Facades\Schema;
      
      class Rename変更する前のカラム名To変更した後のカラム名Onテーブル名Table extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::table('テーブル名', function (Blueprint $table) {
                  //下記を追記する
                  $table->renameColumn('変更する前のカラム名', '変更した後のカラム名');
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::table('テーブル名', function (Blueprint $table) {
                  //下記を追記する
                  $table->renameColumn('変更した後のカラム名', '変更する前のカラム名');
              });
          }
      }
      
  3. マイグレート

    1. アプリ名ディレクトリで下記コマンドを実行してマイグレートを実行する。

      $ php artisan migrate
      
  4. 確認

    1. 下記コマンドを実行してMySQLにターミナルからログインする。(MySQLのパスワードを忘れてしまった方はこちら→Mac ローカル環境の MySQL 8.0 のrootパスワードを忘れた時のリセット方法)

      $ mysql -u root -p
      
    2. 下記を実行してカラム名が変更されたことを確認する。

      mysql> show columns from DB.テーブル名;
      

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel入門学習ノート part5 『データベース接続』

おことわり

勉強始めたばかりなので都度修正したり追記したりすると思います。
もちろん、内容はコアな部分ではなく初心者向けのものです。

今回の内容

DB接続

結論から言うと
安定して接続できる(=使い慣れている)DBの情報を/.envに書き込むだけ。
DBがないならたぶんxampp入れるのが一番安定する。

Laravelの設定

config/database.phpにLaravelからDBを利用する際の設定が書かれている。
見てみると、設定項目は連想配列でsqliteやmysqlのように分かれており、さらにその子のキー名からなんの設定かわかる。

config/database.php
<?php

use Illuminate\Support\Str;

return [
    'default' => env('DB_CONNECTION', 'mysql'),

    'connections' => [
        'sqlite' => [
            'driver' => 'sqlite',
            'url' => env('DATABASE_URL'),
            'database' => env('DB_DATABASE', database_path('database.sqlite')),
            'prefix' => '',
            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
        ],

        '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'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
// 省略

.envの設定

database.phpに設定が書かれているが、env(...)という関数が使われている。
env関数は.envファイルに書かれた設定を参照する関数。
.envファイルはlaravelアプリフォルダの直下にある。

.envファイルを使用するDBに合わせて下記のように設定する。
(例)

/.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=practice
DB_USERNAME=root
DB_PASSWORD=abcd1234

この.envファイルの中からenv関数の第一引数に指定された項目を参照する。
なかった場合、第二引数で指定したものがデフォルトが返ってくる。

env('DB_DATABASE', 'forge')

この場合、.envのDB_DATABASEにはpracticeが設定されているのでpracticeが返ってくる。
設定されていない時は、forgeが返ってくる。

DB接続のようにほぼ固定な情報は.envにまとめておくのがいい気がする。
dbnameやportなどもろもろ設定する。

接続確認

設定したら接続確認。
いきなりDBを操作してもいいけど不安な時はコマンドで確認できる。

プロジェクトフォルダに移動してartisanのtinkerコマンドを使用する。

cd laravel_project
php artisan tinker

>>>が出てきてプログラムを1行ずつ実行できるようになる。
その状態で下記を実行。

DB::connection()->getConfig();  // ...(1)
DB::connection()->getPdo();     // ...(2)

(1)では、今回DB接続に使用する設定が出力される。
(2)では、接続したDBの情報が表示される。

確認ができたら

exit();

で終了。

接続が失敗すると(2)で赤文字でいろいろ言われるっぽい。
うまくつながらない時は.envの設定やDBの状態などを確認。

.envを変更した時はexit();で終了し、再度php artisan tinkerからやり直さないと設定が反映されないので注意。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】グローバルスコープを用いてコード量を減らす

はじめに

実装していてモデルのクエリに制約で何度も同じ実装することはありませんか。
そんな時はグローバルスコープというLaravelの機能のグローバルスコープを使って1回の実装で済むようにするのも1つの方法かなと思います。

グローバルスコープとは

グローバルスコープにより、指定したモデルの全クエリに対して、制約を付け加えることができます。Laravel自身のソフトデリート機能は、「削除されていない」モデルをデータベースから取得するためにグローバルスコープを使用しています。独自のグローバルスコープを書くことにより、特定のモデルのクエリに制約を確実に、簡単に、便利に指定できます。

引用:Eloquent:利用の開始 7.x Laravel

グローバルスコープを1回の実装すれば特定のモデルのクエリに制約ができ、かなり便利です。

グローバルスコープの実装

Illuminate\Database\Eloquent\Scope配下に適当なファイルを作成します。

walkingMinutes.php
<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class walkingMinutesScope implements Scope
{
    /**
     * Eloquentクエリビルダへ適用するスコープ
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function setGlobalScope(Builder $builder, Model $model)
    {
        static::addGlobalScope('walking_minute', function (Builder $builder) {
            $builder->orderByRaw('walking_minute' ASC NULLS LAST);
        });
    }
}

こんな感じに実装するとどこでもwalking_minutes(徒歩時間)が短い順に表示できるようになります。

おわりに

いかがでしたでしょうか。
うまく実装して無駄な実装を減らしていきましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel開発用のDockerイメージできたのでシェアします。

これからLaravelを使って開発とかしていく予定だったので、すぐにスタートできるようにDockerでイメージ作りました。
同じ環境で開発してる方など、よかったら持ってってください。

https://hub.docker.com/r/ryuki0529/webserver

大まかなイメージ環境

  • OS:CentOS 7.8
  • サーバー:Apache 2.4.6
  • PHP 7.4.7
  • PHPMyAdmin 5.0.2
  • Composer 1.10.7
  • Laravel Installer 3.1.0
  • Git 2.9.5
  • データベース:mysql Ver 15.1 Distrib 10.4.13-MariaDB

注意点

docker runでコンテナ作るときに、--privilegedと起動時のコマンドで/sbin/initを指定しないとsystemctlコマンド周りが使えないので注意です。これで3時間ほどハマってしまいました。

詳しくは下記の記事で説明されてます。
CentOS7のコンテナでsystemctlを使うための方法

ということで、最終的にコマンドは以下になります。

docker run -itd -p 80:80 --privileged webserver:1.0.2 /sbin/init
docker exec -it webserver /bin/bash
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

S3 に アップロードした view ファイルの URL を一時的なものにする。( Severless Framework x Laravel )

はじめに

セキュリティの面で、S3 にアップロードしている view ファイルの URL を一時的なものに変更する必要があったので、その手順を残します。

S3 に view ファイルをアップロードする記事はこちら
https://qiita.com/soma_sekimoto/items/5cdeb4b51141e95ba972

1. .env の "AWS_ACCESS_KEY=" などの AWS 関連の部分を複製する。そして、S3 のバケットのポリシーを持つキーを入力する。

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=

+ AWS_ACCESS_KEY_ID_S3=XXXXXXXXXXXX
+ AWS_SECRET_ACCESS_KEY_S3=XXXXXXXXXXXX
+ AWS_DEFAULT_REGION_S3=XXXXXXXXXXXX
+ AWS_BUCKET_S3=XXXXXXXXXXXX

理由としては、serverless framework を利用したときに、lambda の 環境変数がすでにセットされているため、それを使って S3 にアクセスしようとすると、Access Denied のエラーが出るから。

2. config/filesystems.php に以下のように記述

disks => {
  ~省略~
  's3'=> [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID_S3'),
    'secret' => env('AWS_SECRET_ACCESS_KEY_S3'),
    'region' => env('AWS_DEFAULT_REGION_S3'),
    'bucket' => env('AWS_BUCKET_S3'),
    'url' => env('AWS_URL_S3'),
    'endpoint' => env('AWS_ENDPOINT_S3'),
  ]
  ~省略~
}

3. app/helpers.php 作成・編集

<?php
if (!function_exists('s3_asset')) {
    function s3_asset($path)
    {
        return \Illuminate\Support\Facades\Storage::disk('s3')->temporaryUrl($path, now()->addMinute());
    }
}

4. composer.json に追記

"autoload": {
    "psr-4": {
        "App\\": "app/"
    },
    "classmap": [
        "database/seeds",
        "database/factories"
    ],
+    "files" : [        #<= ここから追記
+       "app/helpers.php"
+    ]
},

5. composer dump-autoload 実行。


$ composer dump-autoload

これで、helpers.php の s3_asset 関数が使えるようになりました。

6. resources/views/layouts/app.blade.php に 関数の記述

@if(env('APP_ENV') == 'local')
    <link href=" {{ mix('css/app.css') }} " rel="stylesheet"></link>
@else
    <link href=" {{ s3_asset('css/app.css') }} " rel="stylesheet"></link>
@endif

# 条件分岐で、local環境では違うところから asset をとってくるようにしている。

7. 以下コマンドを実行

$ npm run dev
$ php artisan config:clear
$ sls deploy -v

終わりに

Lambda の環境変数と S3 の環境変数、両方を扱わなくてはいけないので、ちょっと面倒ですが、これだけやってしまえれば、あとはもう何もしなくていいので、便利です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

S3 に view ファイルをアップロード ( Severless Framework x Laravel )

はじめに

この記事に書かれているのは、AWS コンソールで、IAM と S3 bucket を作成した後の手順なので、それ以前の設定はご自身でご自由にしてください。

1. .env を編集

ASSET_URL=https://[S3 のバケット名].s3-ap-northeast-1.amazonaws.com


AWS_ACCESS_KEY_ID=XXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXX
AWS_DEFAULT_REGION=ap-northeast-1
AWS_BUCKET= S3 のバケット名

2. Serverless Framework にプラグインインストール

$ sls plugin install -n serverless-s3-sync

3. serverless.yml への記述

plugins:
   - ./vendor/bref/bref
   - serverless-domain-manager
+  - serverless-s3-sync

 custom:
+  s3Sync:
+    # A simple configuration for copying static assets
+    - bucketName: ${self:service.name}-${opt:stage, self:provider.stage}-asset
+      localDir: public # required

+resources:
+  Resources:
+    StaticContentS3:
+      Type: AWS::S3::Bucket
+      Properties:
+        BucketName: ${self:service.name}-${opt:stage, self:provider.stage}-asset

4. s3 と laravel を連携させるパッケージをインストール

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

これで
Illuminate\Support\Facades\Storage::disk('s3')
で使うことができます。

おわりに

Serverless Framework と laravel での開発にも慣れてきて、記事もまあそれとなく書けるようになってきましたが、まだまだ理解浅いと感じているので、間違いや、不足している部分などありましたら、どんどんコメントしてください!

こちらの記事も読んでみてください。

S3 に アップロードした view ファイルの URL を一時的なものにする。( Severless Framework x Laravel )
https://qiita.com/soma_sekimoto/items/bd16bbc6c2b650af79f9

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WSL2+Docker+Laravel既存コードでの開発環境作成(XAMPPからの移行)

PC移行に伴い新たな開発環境を構築する必要が出てきたが、XAMPP入れるのも古いかな(nginx使いたいし)、WSL上にごちゃごちゃ入れると何入れたかわからなくなる、と思ったのでDockerでなんとかならないかと試してみることに。
Dockerが動く状況なら移行先でも同様の開発環境がすぐに構築できるようになったはず。

WSLを入れるところから長々書いているので、答えだけdockerのファイルの答えだけ見たい方は、下の方を見るか
https://github.com/miyawa-tarou/docker-test/commit/5d5c78633a6c0e94b0c25849cf683c9a459b891e
あたりを見てください。

WSL2を入れる

Windowsのアップデート

  • Windows 10、バージョン 2004、ビルド 19041 以上である必要があるので、アップデートします。
  • WindowsUpdateのところからできる場合もあるようですが、ゆっくりと順次配布のためない場合は下記からダウンロードできます

仮想化を有効にする

BIOS

  • ここはメーカーによるから細かい方法は置いておくが、BIOSに入って
  • Intel Virtualizationとかがdisalbeになっていたらenableにする

Windows

Windowsの仮想化を有効に(GUIからやる方法もあるはず)
PowerShellを管理者モードで開き下記を実行

> Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
> Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

再起動

WSL2の設定

https://docs.microsoft.com/ja-jp/windows/wsl/install-win10
再びPowerShellを管理者モードで開き下記を実行

> dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
> dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

WSLのデフォルトをバージョン2にしておく
powershell
wsl --set-default-version 2

「最新の WSL2 Linux カーネル更新プログラム パッケージ」が必要なこともあるかもしれない。
その場合は下記からダウンロード。

https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel

ディストリビューションを入れる

https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#install-your-linux-distribution-of-choice

WindowsStoreから好みを入れる(自分はUbuntuを入れた)
入ったら一回起動しておく(ここは起動しなくて動くか確かめてない)

ディストリビューションをあとからWSL2にする

WSL1で入れてしまった場合は、下記コマンドで変換する

> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-18.04    Stopped         1
  Ubuntu          Running         1
> wsl --set-version Ubuntu 2

変換なのでちょい時間がかかる

Docker Desktopを入れる

https://www.docker.com/products/docker-desktop

Enable WSL2 Windows Featuresのチェックは付けたまま
これでDocker環境の準備は整ったはず

既存ファイル郡にDockerのファイルを追加する

ここからはDockerの話
既存コードににDocker設定を入れる

  • ドキュメントルートに docker-composer.yml
  • それ以外のDocker関連ファイルを ./docker/ 以下に置く

docker-composer.yml

XAMPPからの移行だが、本番はに近づけるため、
nodeサーバー、php-fpm、MariaDBと、XAMPPを意識するという点で今回はphpmyadminを入れる

それぞれ別のコンテナで動かす

docker-composer.yml
version: '3'
services:
  test_db:
    image: mariadb:latest
    volumes:
      # データ永続化用
      - ./docker/dbdata:/var/lib/mysql
      # 初期データ用(ここに置いたsqlファイル等は実行される)
      - ./docker/initdb:/docker-entrypoint-initdb.d
    environment:
      - MYSQL_ROOT_PASSWORD=mariadb
    ports:
      # Docker外(ローカル)からも3306で繋がるようにしておく
      - 3306:3306
  test_myadmin:
    image: phpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      # 上のDBコンテナ名
      - PMA_HOST=test_db
      # root固定
      - PMA_USER=root
      # 上のMYSQL_ROOT_PASSWORDの値
      - PMA_PASSWORD=mariadb
    links:
      # DBコンテナにつながるようにする
      - test_db
    ports:
      # ローカルのブラウザからはlocalhost:8080で見られるようにする
      - 8080:80
  test_nginx:
    image: nginx:alpine
    depends_on:
      - test_php
    volumes:
      # nginxの設定
      - ./docker/nginx/docker.conf:/etc/nginx/conf.d/default.conf
      # nginxのrootに合わせる(rootにはpublicを付ける必要がある)
      - .:/var/www/test
    ports:
      - 80:80
    environment:
      - NGINX_PORT=80
  test_php:
    # これだけ素のイメージでは足りないのでDockerfileを利用する(Dockfileのパスを指定)
    build: ./docker/php
    links:
      - test_db
    volumes:
      # php.iniの設定を送る(今回は特にめだった何かはしていない)
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini
      - .:/var/www/test
    ports:
      - 9000:9000

Dockerを理解してないがゆえに割と悩んだのが、多くの環境構築系資料で、ここにおいたコードが実行されるでしょみたいの書かれるけど、「え?どうやって編集するの?」ということ

結論としては、volumes以下はコピーされるのではなくマウントされるので、更新すれば自動で反映される。なので

volumes
  - .:/var/www/hoge

とかやれば、ファイル全体が自動的にマウントされる、Dockerコンテナ側に反映される

Dockerfile(PHPサーバー)

docker/php/Dockerfile
FROM php:7.3-fpm

RUN apt-get update \
    # Laravel実行には必要
    && apt-get install -y zlib1g-dev libzip-dev mariadb-client \
    && docker-php-ext-install zip pdo_mysql \
    # XDebug用(今回は不要)
    && pecl install xdebug \
    && docker-php-ext-enable xdebug
COPY --from=composer /usr/bin/composer /usr/bin/composer

composerは必須ではないが、後述のLaravelクソ重い問題で利用する

Docker に Composer をインストールするベストプラクティス(と解説)

Nginxのconf

docker/nginx/docker.conf
server {
    # nginxコンテナのポートの右側の数値
    listen       80;
    server_name  localhost;
    charset      utf-8;

    # volumesでマウントしているところと一致させる(Laravelなのでこちらはpublicをつける)
    root /var/www/test/public;

    index index.php;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        # test_phpはdockerのPHPコンテナ名、9000はそのポート(右側の数字)
        fastcgi_pass  test_php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

初期SQLを置く

docker-compose.yml のファイル内のコメントに書いたが、データベース系のコンテナだあと
/docker-entrypoint-initdb.d に置かれたファイルは自動でよしなにしてくれるらしい。
ここに .sql , .sql.gz をおけばSQLが実行、.shを置けばシェルが走るらしい。
artisanでmigrationで行う場合は .sh で書けば良い

上のdocker-composerで/docker/initdb においたものが/docker-entrypoint-initdb.d にコピーされるのでそこにおいておく

なお、いきなりテーブル作成をしてしまうとエラーになる。ちゃんとdatabaseの作成・指定から行う。

Docker で MySQL 起動時にデータの初期化を行う

Laravelの.env設定

関係あるのはDB周りだけなので、そこの部分だけ修正する。

DB_CONNECTION=mysql
# DBコンテナ名
DB_HOST=test_db
# DBコンテナで指定したポート(右側)
DB_PORT=3306
# 実際に使っているもの次第(今回は初期データがここに入ってる)
DB_DATABASE=docker_test
DB_USERNAME=root
# 指定したパスワード
DB_PASSWORD=mariadb

起動してみる

composer-docker.ymlのある場所まで移動して

$ docker-compose up -d

Windows側でもWSL側でも動くはずである。
ミスがなければ起動するはず。
DockerDesktop側のDashboardからも起動が確認できる

動作確認

問題点1:Laravelがクソ重い

上のを実行すると気づくとも思うが、何もしてない処理でもクソ重い。
大して何もしてないページなのに表示に数秒かかる・・・。これではさすがに厳しい。
どうやら調べてみると、「マウントするファイルが多いと重くなる」模様
下記が解決策として実行したもの・浮かんだもの

不要なファイルはマウントしない(今回やった解決策)

自分で触ることのないファイルはわざわざ、マウントする必要がない

  • vendor以下は依存を変えない限りは不要である
  • storage以下は自動で作られるファイルだからこちらかアップすることはない

しかし単にマウントしないだけだと以下の問題が起きる

  • vendor以下がないため、composer installをする必要がある
  • storage以下のファイルが存在しないからエラーになる

一旦ファイルを送ってからマウントを切るという手もあるが、一発で構築できないという点でイケてない。
構築後に中に入って準備をするのもイケてない。

なので、必要なファイルはDockerfileで取得するようにする

docker-compose.yml
volumes:
  # php.iniの設定を送る
  - ./docker/php/php.ini:/usr/local/etc/php/php.ini
  - .:/var/www/test
  # 除外
  - /var/www/test/storage
  - /var/www/test/vendor

Dockerfileに下記を追加

docker/php/Dockerfile
# storageファイルはマウントしないのでもともと必要なディレクトリは作成する
RUN mkdir -p /var/www/test/storage/app/public
RUN mkdir -p /var/www/test/storage/framework/cache/data
RUN mkdir -p /var/www/test/storage/framework/sessions
RUN mkdir -p /var/www/test/storage/framework/testing
RUN mkdir -p /var/www/test/storage/framework/views
RUN chmod -R 777 /var/www/test/storage

# vendorはマウントしないのでcomposerで入れる
COPY composer.lock /var/www/test/composer.lock
# いらないかも
COPY composer.json /var/www/test/composer.json

# composer.jsonで必須になっているもの(autoloadまわり)
RUN mkdir -p /var/www/test/database/seeds
RUN mkdir -p /var/www/test/database/factories

# cd /var/www/test && composer install でも動きそう
WORKDIR /var/www/test
# scriptsでファイルチェックをしているが、マウント前のこの時点では存在しないのでそれは避ける
RUN composer install --no-scripts

これで再作成

$ docker-compose build --no-cache

表示に1秒かからなくなった!

その他解決策1:docker-syncを使う

WindowsもLinuxもベータ版らしい

Docker for MacのLaravel アプリケーションのが遅い?それ、ファイルをいっぱいマウントしてるからかもです。

Macだとこれが普通に行われている記事をよく見る

その他解決策2:ファイルwatch+rsyncする

上のdocker-syncはrsyncしているだけなので、自分で動かすこともできる気がする。
実際うまく動くかは不明

https://medium.com/@imranhsayed/rsync-using-phpstorm-on-save-b1e73c079db0

問題点2:同じ.envファイルでWSLとDocker上両方動かせない

.envDB_HOST=test_db としているがDocker内での名称であり、WSL側では認識せず動かせない
そのため、開発を行うWSL側から php artisan などを実行してもDB周りが上手く動かない

  • 127.0.0.1だとDockerコンテナからは127.0.0.1ではないため動かない
    • Connection refused.
  • localhostだとsocketのエラーが出る
    • SQLSTATE[HY000] [2002] No such file or directory

Socketファイルを云々している記事もあったがこれじゃない感。

Docker側から見てlocalhostとはなにかというと、 host.docker.internal であり、これを入れて見るとartisanも動いたし、Dockerホスト側からも動いた

.env
DB_HOST=host.docker.internal

最終形

こちらにLarvelのテストファイルと共に置いてます:https://github.com/miyawa-tarou/docker-test/commit/5d5c78633a6c0e94b0c25849cf683c9a459b891e

docker-compose.yml

docker-compose.yml
version: '3'
services:
  test_db:
    image: mariadb:latest
    volumes:
      # データ永続化用
      - ./docker/dbdata:/var/lib/mysql
      # 初期データ用(DB系イメージだとここに置いたsqlファイル等が実行される)
      - ./docker/initdb:/docker-entrypoint-initdb.d
    environment:
      - MYSQL_ROOT_PASSWORD=mariadb
    ports:
      # Docker外からも3306で繋がるようにしておく
      - 3306:3306
  test_myadmin:
    image: phpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      # 上のDBコンテナのホスト
      - PMA_HOST=test_db
      # root固定
      - PMA_USER=root
      # 上のMYSQL_ROOT_PASSWORDの値
      - PMA_PASSWORD=mariadb
    links:
      # DBコンテナにつながるようにする
      - test_db
    ports:
      # ブラウザからはlocalhost:8080で見られるようにする
      - 8080:80
  test_nginx:
    image: nginx:alpine
    depends_on:
      - test_php
    volumes:
      - ./docker/nginx/docker.conf:/etc/nginx/conf.d/default.conf
    ports:
      - 80:80
    environment:
      - NGINX_PORT=80
  test_php:
    # これだけ素のイメージでは足りないのでDockerfileを利用する(Dockrfileのパスを指定)
    build:
      # composer.lockをDockerfile内で使うために実行場所は変えない(通常だとDockerfileの位置からの参照、親ファイルは読めない)
      context: .
      dockerfile: ./docker/php/Dockerfile
    links:
      - test_db
    volumes:
      # php.iniの設定を送る
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini
      - .:/var/www/test
      # 除外
      - /var/www/test/storage
      - /var/www/test/vendor
    ports:
      - 9000:9000

docker/php/Dockerfile

docker/php/Dockerfile
FROM php:7.3-fpm

# composer.jsonで必須になっているもの
RUN mkdir -p /var/www/test/database/seeds
RUN mkdir -p /var/www/test/database/factories

RUN apt-get update \
    # Laravel実行には必要(多分)
    && apt-get install -y zlib1g-dev libzip-dev mariadb-client \
    && docker-php-ext-install zip pdo_mysql \
    # XDebug用
    && pecl install xdebug \
    && docker-php-ext-enable xdebug
COPY --from=composer /usr/bin/composer /usr/bin/composer

# storageファイルはマウントしないのでもともと必要なディレクトリは作成する
RUN mkdir -p /var/www/test/storage/app/public
RUN mkdir -p /var/www/test/storage/framework/cache/data
RUN mkdir -p /var/www/test/storage/framework/sessions
RUN mkdir -p /var/www/test/storage/framework/testing
RUN mkdir -p /var/www/test/storage/framework/views
RUN chmod -R 777 /var/www/test/storage

# vendorはマウントしないのでcomposerで入れる
COPY composer.json /var/www/test/composer.json
COPY composer.lock /var/www/test/composer.lock

# composer.jsonで必須になっているもの(autoloadまわり)
RUN mkdir -p /var/www/test/database/seeds
RUN mkdir -p /var/www/test/database/factories

# cd /var/www/test && composer installでも動きそう
WORKDIR /var/www/test
# scriptsでファイルチェックをしているが、この時点ではないのでそれは避ける(後でマウントされるため)
RUN composer install --no-scripts

docker/nginx/docker.conf

docker/nginx/docker.conf
server {
    # nginxコンテナのポートの右側の数値
    listen       80;
    server_name  localhost;
    charset      utf-8;

    # volumesでマウントしているところと一致させる
    root /var/www/test/public;

    index index.php;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        # test_phpはdockerのPHPコンテナ、9000はそのポート(右側の数字)
        fastcgi_pass  test_php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

.env(差分では.env.exampleに置いてます)

.env
DB_CONNECTION=mysql
DB_HOST=host.docker.internal
DB_PORT=3306
# 実際に使っているもの次第
DB_DATABASE=docker_test
DB_USERNAME=root
DB_PASSWORD=mariadb

Xdebug入れてますが、まだ設定はしていない・・・。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel × react × ajax でformを送信する

環境

・Laravel Framework 7.16.1
・react
・jquery

コード

form

名前、メッセージ、画像を送信します。

import React from 'react';

function Post() 
{
    return(
         <>
         <div>
             <form className="main_form" action="" method="post">
                 <p>NAME:<input type="text" name="name"></input></p>
                 <textarea spellCheck="false" name="message" id="" cols="30" rows="10"></textarea>
                 <p>Image:<input type="file" name="path"></input></p>
                 <p><button type="submit">Post!</button></p>
              </form>
         </div>

         {posts.map((post) => 

          <div key={post.id}>
               <p>{post.name}</p>
              <img src={'/storage/' + post.path}></img>
              <p>{post.message}</p>
          </div>
         )}
       </>  
      )
}

export default Post;

ajaxの処理
※FormDataは送信が可能な、フォームフィールドおよびそれらの値から表現されるキーと値のペアのセットを簡単に構築する手段を提供します。

下記コードは空のFormDataにappendを使ってinputの値を入れています。

以下のコード内の

 processData: false,
 contentType: false

について。
ザックリ言うと、Ajaxはデータ送信時にデータ形式を変換しようとするのですが、それを許すとエラーが出るらしいので形式変換させないように指定しています。

welcome.blade.php
<head>
~
<meta name="csrf-token" content="{{ csrf_token() }}">
~
</head>

<body>
    <div id="app"></div>
    <script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
    <script>
    $(function(){

      $.ajaxSetup({
          headers: {
              'X-CSRF-TOKEN' : $('meta[name="csrf-token"]').attr('content')
          }
      })

      $('.main_form').submit(function(event) {
          event.preventDefault();

          var formData = new FormData();
          formData.append('name',    $("input[name=name]").val());
          formData.append('message', $("textarea[name=message]").val());
          formData.append('path',    $("input[name=path]")[0].files[0]);

       $.ajax({
          url:  "{{ action('ReactController@post') }}",
          type: 'POST',
          data: formData,
          processData: false,
          contentType: false
       })
       .done(function(data) {
           console.log('succecss')
       })
       .fail(function(data) {
           console.log('fail')
       });
      });
    });
    </script>
</body>

postされたデータを保存するためのコントローラー

web.php
Route::post('/post', 'ReactController@post');

名前、メッセージ、画像を保存する

ReactController.php
    public function post(Request $request) 
    {    
       $post = new Post;
       $form = $request->all();
       unset($form['_token']);

       $file_name = $request
                    ->file('path')
                    ->getClientOriginalName();
:kissing_heart:
       $request->file('path')->storeAs('public', $file_name);
       $post->name    = $request->name;
       $post->message = $request->message;
       $post->path    = $file_name; 
       $post->save();

       return redirect('/user');
    }

以上です。

素人の日記なので、気になるところはしっかり調べて正しい情報を得ることをお勧めします。
:kissing_heart:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む