20200323のlaravelに関する記事は11件です。

php artisan コマンド make:○○

migration作成

# migrationの後の名前は任意(わかりやすいようにcreate_xxx_tableにしている)
php artisan make:migrtion create_xxxx_table 

migration実行

php artisan migrate

Model作成

php artisan make:model Model名

シード作成

php artisan make:seeder XxxxSeeder

作成したシードファイルにダミーデータの作成コードを記載した後に
DatabaseSeeder.phpに設定する必要があるため下記のように設定する

DatabaseSeeder.php
    public function run()
    {    # シードを作成する度ここに追加していく
        $this->call(XxxxSeeder::class);
    }

シードの実行

php artisan db:seed

RESTコントローラ作成

php artisan make:controller XxxxController --resource
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのライブラリ「laravel-dompdf」を使ってビューの表示をPDFとして表示しよう

目的

  • ライブラリを使用して現在のビューとして表示しているコードをそのままPDFで表示する方法をまとめる

実施環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.3)
ハードウェア MacBook Air (11-inch ,2012)
プロセッサ 1.7 GHz デュアルコアIntel Core i5
メモリ 8 GB 1600 MHz DDR3
グラフィックス Intel HD Graphics 4000 1536 MB
  • ソフトウェア環境
項目 情報
PHP バージョン 7.4.3
Laravel バージョン 7.0.8

実施条件

実施方法概要

  1. コントローラの確認
  2. アクションの記載変更
  3. 確認

実施方法詳細

  1. コントローラの確認

    1. PDFとして表示したいビューファイルが呼び出されているコントローラファイルを表示する。

      <?php
      
      namespace App\Http\Controllers;
      
      use Illuminate\Http\Request;
      
      
      
      
    2. use Illuminate\Http\Request;の下に下記の内容を記載する。

      use PDF;
      
    3. コントローラファイルの設定部分が下記の様になっていることを確認する。

      <?php
      
      namespace App\Http\Controllers;
      
      use Illuminate\Http\Request;
      
      use PDF;
      
      
      
      
  2. アクションの記載変更

    1. 先に確認したコントローラファイルのビューを表示しているアクションを確認する。

      return view('ビューファイルディレクトリ名.ビューファイル名');
      
    2. 先に確認したreturn部分を下記の様に記載する。

      $pdf = PDF::loadView('ビューファイルディレクトリ名.ビューファイル名');
      return $pdf->stream();
      
  3. 確認

    1. 下記コマンドを実行してローカルサーバを起動する。

      $ cd アプリ名ディレクトリ
      $ php artisan serve
      
    2. 修正したアクションとリンクするURLにアクセスする。

    3. PDFで表示されればOKである。(日本語は文字化け表示されるが、現在の設定だと正常である。)

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

Laradockで簡単にLaravel環境構築

前提

  • Mac環境で進めていきます
  • Dockerが既にインストールされている
  • gitがインストールされている

フォルダ作成

まずは適当なファイルを作りましょう

$ mkdir docker_laravel 

次に作ったフォルダに移動します

$ cd docker_laravel

このフォルダにLaradockを構築していきます

Laradockをcloneする

では早速Laradockを先ほど作ったフォルダにcloneします
下記を実行してください

$ git clone https://github.com/LaraDock/laradock.git

上記でdoker_laravellaradockフォルダが作成されます
laradockフォルダに移動します

$ cd laradock

laradockに.envファイルを作成します

$ cp env-example .env

これで、laradockフォルダに.envが作成されました

Laravelの作成

次にLaravelプロジェクトを作成していきます
workspaceコンテナを動かします
このworkspaceコンテナにcomposerやlaravelなどが含まれており
artisanコマンドやnpmなども実行できます
workspaceコンテナを動かしコンテナ内に入ることで上記コマンドも実行できます

コンテナを動かす

$ docker-compose up -d workspace

コンテナに入る

$ docker-compose exec --user=laradock workspace bash

コンテナに入ったらLaravelプロジェクトを作成

$ composer create-project laravel/laravel sample

上記までを無事に実行できれば
docker_laravelフォルダ内にはlaradocksampleフォルダが入っているはずです

コンテナから出ます

$ exit

コンテナを一旦止めます

$ docker-compose stop

.envの編集(laradock側)

laradock内の.envファイルを下記のように修正してください

変更前
APP_CODE_PATH_HOST=../

変更後
APP_CODE_PATH_HOST=../sample
変更前
DATA_PATH_HOST=~/.laradock/data

変更後
DATA_PATH_HOST=.laradock/data
変更前
MYSQL_VERSION=latest

変更後
MYSQL_VERSION=5.7

.envの編集(sample側)

変更前
APP_NAME=Laravel

変更後
APP_NAME=Sample
変更前
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

変更後
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=sample
DB_USERNAME=root
DB_PASSWORD=secret

これで準備は完了です

コンテナを立ち上げる

それでは、コンテナを立ち上げてLaravelのwelcomeページにアクセスしましょう

$ docker-compose up -d workspace nginx mysql

これでこちらのURLにアクセスしてwelcomeページが表示されればOKです→こちら

DBにアクセスする

ターミナルにてlaradockに移動してください
laradockにて下記コマンドを実行してください

$ docker-compose exec mysql bash

これでmysqlコンテナに入れました
さらに下記のコマンドを入力してください

$ mysql -u root -p

上記を入力するとパスワードを求められますので下記を入力

$ secret

これでmysqlに入れたかと思います

マイグレーションの実行

実際にDBの接続がきちんとできているかを確かめるために
マイグレーションを実行して、テーブルを作成してみましょう
ターミナルにてlaradockに移動し下記コマンドを実行してworkspaceコンテナに入ります

$ docker-compose exec workspace bash

これでコンテナに入れました
マイグレーションを実行します

$ php artisan migrate

上記を実行し無事にマイグレーションが実行され
DBにテーブルが追加されていれば完了です

終わりに

以上がLaradockを使ってLaravelの環境を構築と
マイグレーションの実行やDBの操作方法になります

私はDockerにあまり詳しくないのですが
そんな自分でも簡単に環境を用意することができました

Dockerにそこまで詳しくないけど
Dockerで開発してみたいと言う方は是非、挑戦してみてください

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

未経験エンジニアが知っておくべき事(初心者向け)php/laravel

はじめに

エンジニア未経験に陥りやすいのがソースの追い方がよくわからなくなることだと思うんですが、
バグ改修、DB保存などの実装は
View → Controller → Model → DB
だけの話であって、本当に!シンプルに!単純に!これだけの話なんです。

そこでServiceやらRepositoryとかが入ってくるから余計にわからなくなってくると思うんですが、
こういった概念はあくまでもコードの可読性をあげる為のものであって、MVCに則る実装において基本形は変わらないのです。
経験者がその実装はrepositoryに書いてね。ってあたかも当然だよね?みたいな雰囲気を醸し出す為、???みたいな状況になっていくと思います
例として、LaravelにおいてデータをviewからDB登録するまでの流れを書いていきますね

Routing

ディレクトリ:/routes/web.php
それぞれの橋渡しの役目でindexを入れるとurlにlocalhost/notificationと叩くとcontrollerが走るよーって意味となる
いわゆるView → Controller → Model → DBの「→」の役目
※resourceとはcrud機能を一挙される(resourceがわからない場合、get/postにしてくださいね)

Route::resource('notification', 'NotificationController');

View

ディレクトリ:/resources/views
viewにて、送信する画面を作成します。Laravel想定なのでviewはbladeで書いています。
※classはBootstrapを使用しています。
※ソースはindex.blade.phpのみ

<div class=“col-md-8 col-md-offset-2”>
    {{Form::open([‘url’=>‘/notification’,‘method’=>‘post’,‘files’=>‘true’])}}
    <section class=“content”>
        <table class=“table table-bordered”>
            <tr>
                <th>{{Form::label(‘title’,‘タイトル’)}}</th>
                <td>{{Form::text(‘title’,‘’,[‘placeholder’=>‘タイトル’])}}</td>
            </tr>
            <tr>
                <th>{{Form::label(‘body’,‘内容’)}}</th>
                <td>{{Form::textarea(‘body’,‘’,[‘placeholder’=>‘内容を入力してください‘])}}</td>
            </tr>
        </table>
    </section>
    <section class=“content”>
        {{ Form::submit(‘作成’,[“class”=>“btn btn-primary”]) }}
    </section>
    {{ Form::close() }}
</div>

Controller

ディレクトリ:/app/Http/Controllers/NotificationController.php
urlを叩いたら、まずcontrollerのindexが呼び出され、表示させます。
表示の流れは、controller→viewですね。
一番最初に書いた流れはDB保存(store)となります。

    /**
     * お知らせ一覧
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function index()
    {
        $notifications = Notification::all();

        return view('admin.notification.index')
            ->with('notifications',$notifications);
    }
    /**
     * お知らせ追加画面
     * @return View
     */
    public function create()
    {
        return view('notification.create');
    }
    /**
     * お知らせ追加
     * @param Notification $notification
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $data = $request->all();
        Notification::create($data);

        return redirect('/notification')->with('flash_success', 'お知らせを作成しました');
    }
    /**
     * お知らせ編集画面
     * @param Request $notification
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function edit(Notification $notification)
    {
        return view('admin.notification.edit')
                ->with('notification',$notification);
    }
    /**
     * お知らせ更新
     * @param Request $notification
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function update(Request $request,Notification $notification)
    {
        $notification->title = $request->title;
        $notification->body  = $request->body;
        $notification->save();

        return redirect('/notification')->with('flash_success', 'お知らせを更新しました');
    }
    /**
     * お知らせ削除
     * @param  Notification $notification
     * @return \Illuminate\Http\Response
     */
    public function destroy(Notification $notification)
    {
        $notification->delete();
        return redirect('/admin/notification')->with('flash_success', 'お知らせを削除しました');
    }

Model

ディレクトリ:/app/Models/Notification.php
このmodelは何をするかというと何もしません。何もしませんというと、雑な説明ですが、table=modelと思ってください。
controllerからmodelを呼び込むということは、controllerからtableを呼び込むと同一です。
storeの場合、contollerからmodelを呼び出し、作成する流れとなります。

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

/**
 * Class Notification
 * @package App\Models
 */
class Notification extends Model
{

    protected $dates = ['created_at', 'updated_at', 'deleted_at'];
    protected $fillable = [
        'filtering',
        'title',
        'body'
    ];
}

余談

View → Controller → Model → DBの流れをズババーーっと書いたのですが、スクールとかで学んで現場で実装をするとき、全然書いている内容が違う、、となってしまうことがあると思います。
それが何故かというと先ほど言ったRepository概念とかが入ってくるからです。
controllerはあくまでもviewとmodelを呼び出す、呼び出される概念なだけで、DBを直接、、となると少し変わってくるのです。その為にrepositoryにmodelを呼び出す実装を書いたりするケースがあります。

repositoryを使用する場合
View → Controller ←→ Contract ←→ Repository → Model → DB

ただ、これも一概ではなくService概念を取り入れるところもあれば、controllerに全てかくところもあります(実際にcontrollerに1万行とかありました。。)
何故違うディレクトリに書くことが良いとされるかというと、単純に可読性を高めようぜ!!ってところですが、最初に申した通り、基本形は変わりません。なので、controllerから何を呼び出しているのかを見つけるところが鍵になると思います。

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

Laravel+nginx+php-fpmで環境ごとに読み込む.envファイルを切り替える

はじめに

「環境変数のAPP_ENVで指定すればよい」という説明はいくつかありましたが、その環境変数をどのように指定すればよいという説明があまりなかったので、メモとして残します。

前提

環境ごとに各.envファイルが作成されているものとします。

環境 ファイル
開発環境 .env.dev
ステージ環境 .env.stg
本番環境 .env.prod

APP_ENVを設定

設定する場所は/etc/nginx/fastcgi_paramsです。

開発環境
fastcgi_param  APP_ENV  dev;
ステージ環境
fastcgi_param  APP_ENV  stg;
本番環境
fastcgi_param  APP_ENV  prod;

設定後はnginxとphp-fpmの再起動を忘れずに。

# service nginx restart
# service php-fpm restart

以上で、環境ごとに読み込まれる.envファイルが自動的に切り替わります。

もし切り替わらないようであれば、nginxの設定でfastcgi_paramの読み込みが正しく行われているか(下記の行がコメントアウトされたりしていないか)を確認してください。

include /etc/nginx/fastcgi_params

まとめ

  • 環境ごとに.envファイルを用意する。
  • nginxの設定でfastcgi_paramsを設定する。

参考

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

1年間ログインがないユーザをLaravel のタスクスケジューラで定期削除をした話

はじめに

こちらは、
KPI 項目B:「Laravelの勉強をする」 Artisanコンソール/タスクスケジュール
のアウトプット記事です。

本編

今回はLaravelのタスクスケジューリング機能を利用して、
1年間ログインがないユーザを自動的に論理削除する機能の実装を試す。

準備

環境

Laradock等で環境の用意。
今回は以下の環境。

パッケージ バージョン
Ubuntu 16.04.6
PHP 7.3.15
PostgreSQL 9.6.17
Laravel 7.2.2

テストデータ

テーブル構造(抜粋)

カラム名 Not Null
id bigint 連番 not null
name character varying(255) 名前 not null
deleted_at timestamp(0) without time zone 論理削除日
logined_at timestamp(0) without time zone 最終ログイン日

テストデータ作成

id name logined_at
1 管理者 2020-03-23 00:00:00
2 1年間未ログインのユーザ 2019-03-22 15:00:00

今回はid=2のユーザに論理削除を行う。

Cron設定

まずはCronに設定を追加。
今回は下記のパスにプロジェクトを配置しているので、下記を指定する。

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

Cronはこれで終わり。

バッチ処理の作成

今回は、バッチ処理を毎日 0:00 に実行するように設定する。
なお、削除は論理削除とした。
手動での実行も考慮して、Artisanコマンドの作成を行う。

Artisanコマンド作成

まずArtisanコマンドの雛形クラスを作成する。

Commandクラスを継承した、BatDeleteNotLoginUserForOneYearクラスを作成する。

php artisan make:command BatDeleteNotLoginUserForOneYear

実行する処理はこのクラスにあるhandleメソッドへ記載する。
今回は、最終ログイン日(logined_at)が、コマンド実行日以前のデータを削除する。
雛形クラスを編集し、下記のように変更。

App/Console/Commands/BatDeleteNotLoginUserForOneYear.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Carbon\Carbon;
use App\User as User;

class BatDeleteNotLoginUserForOneYear extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'batch:notloginuser'; //実行時のコマンド:php artisan batch:notloginuser 

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Batch processing of Not Login User for one-year'; //説明

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // コマンド実行時の削除対象起算日を取得
        $day =  (Carbon::today())   //実行日の時刻 00:00:00
                    -> subYear(1);  //1年前

        // 1年以内にログインがないユーザを取得
        $unloginedUsers = User::where('logined_at',"<",$day)
                            ->get();

        // 取得したユーザに対して
        foreach ($unloginedUsers as $unloginedUser) {
            // 論理削除を実行
            $unloginedUser->delete();
        }
    }
}

スケジューリング

次に作成したコマンドのスケジューリングを設定する。
今回の設定は毎日 0:00

app/Console/Kernel.php
<?php

namespace App\Console;

use Illuminate\Console\Command;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\App;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        Commands\BatDeleteNotLoginUserForOneYear::class
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // スケジューリングするコマンドと実行する時間を指定する
        $schedule->command('batch:notloginuser')
                 ->at('0:00'); //毎日 0:00
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }

    /**
     * Get the timezone that should be used by default for scheduled events.
     *
     * @return \DateTimeZone|string|null
     */
    protected function scheduleTimezone()
    {
        // スケジューリングする際のタイムゾーンを指定する
        return 'Asia/Tokyo';
    }
}

結果

実行

テスト用にタスクスケジュールの実行時間を13:09で指定した結果は以下の通り。

実行前

select id,name,logined_at,deleted_at from users;
  1 | 管理者                  | 2020-03-23 00:00:00 | 
  2 | 1年間未ログインのユーザ | 2019-03-22 15:00:00 |

13:09 以降

select id,name,logined_at,deleted_at from users;
  1 | 管理者                  | 2020-03-23 00:00:00 | 
  2 | 1年間未ログインのユーザ | 2019-03-22 15:00:00 | 2020-03-23 13:09:02

結論

無事に1年間ログインがないユーザをバッチ処理で論理削除することができました。

参考

タスクスケジューリング
Task Scheduling(Laravel - Official)
Laravel 7.x タスクスケジュール

Artisanコンソール
Artisan Console(Laravel - Official)
Laravel 7.x Artisanコンソール

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

Laravel7 新たに追加された3つのマイグレーションエイリアス

Laravel7 で追加されたマイグレーションエイリアス

使用できるカラムタイプのエイリアス

  • id
  • foreignId

外部キー制約のエイリアス

  • constrained

上記の3つのエイリアスが追加されてます。

環境

$ php artisan -V
Laravel Framework 7.2.2

使い方

Schema::table('posts', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained();
});

上の定義は、下記のように定義したのと同じ内容になります。

Schema::table('posts', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->unsignedBigInteger('user_id');
    $table->foreign('user_id')->references('id')->on('users');
});

補足

id

src/Illuminate/Database/Schema/Blueprint.php
    /**
     * Create a new auto-incrementing big integer (8-byte) column on the table.
     *
     * @param  string  $column
     * @return \Illuminate\Database\Schema\ColumnDefinition
     */
    public function id($column = 'id')
    {
        return $this->bigIncrements($column);
    }

シンプルなエイリアスですね。
個人的には bigIncrements って指定されてた方が分かりやすいと思うんですけど...

foreignId

src/Illuminate/Database/Schema/Blueprint.php
    /**
     * Create a new unsigned big integer (8-byte) column on the table.
     *
     * @param  string  $column
     * @return \Illuminate\Database\Schema\ForeignIdColumnDefinition
     */
    public function foreignId($column)
    {
        $this->columns[] = $column = new ForeignIdColumnDefinition($this, [
            'type' => 'bigInteger',
            'name' => $column,
            'autoIncrement' => false,
            'unsigned' => true,
        ]);

        return $column;
    }

ForeignIdColumnDefinition のインスタンスが返ってきますね。

constrained

src/Illuminate/Database/Schema/ForeignIdColumnDefinition.php
    /**
     * Create a foreign key constraint on this column referencing the "id" column of the conventionally related table.
     *
     * @param  string|null  $table
     * @return \Illuminate\Support\Fluent|\Illuminate\Database\Schema\ForeignKeyDefinition
     */
    public function constrained($table = null)
    {
        return $this->references('id')->on($table ?: Str::plural(Str::before($this->name, '_id')));
    }

foreignId に返ってきた ForeignIdColumnDefinition にメソッドチェーンでつなげて呼び出します。
$table->foreign('user_id')->references('id')->on('users'); このようにテーブル名を指定しますが、 ->foreign('user_id') から users と複数形のテーブルを自動的に設定してくれます。

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

Laravel7 新たに追加された id, foreignId, constrained マイグレーションエイリアス

Laravel7 で追加されたマイグレーションエイリアス

使用できるカラムタイプのエイリアス

  • id
  • foreignId

外部キー制約のエイリアス

  • constrained

上記の3つのエイリアスが追加されてます。

環境

$ php artisan -V
Laravel Framework 7.2.2

使い方

Schema::table('posts', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained();
});

上の定義は、下記のように定義したのと同じ内容になります。

Schema::table('posts', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->unsignedBigInteger('user_id');
    $table->foreign('user_id')->references('id')->on('users');
});

補足

id

src/Illuminate/Database/Schema/Blueprint.php
    /**
     * Create a new auto-incrementing big integer (8-byte) column on the table.
     *
     * @param  string  $column
     * @return \Illuminate\Database\Schema\ColumnDefinition
     */
    public function id($column = 'id')
    {
        return $this->bigIncrements($column);
    }

シンプルなエイリアスですね。
個人的には bigIncrements って指定されてた方が分かりやすいと思うんですけど...

foreignId

src/Illuminate/Database/Schema/Blueprint.php
    /**
     * Create a new unsigned big integer (8-byte) column on the table.
     *
     * @param  string  $column
     * @return \Illuminate\Database\Schema\ForeignIdColumnDefinition
     */
    public function foreignId($column)
    {
        $this->columns[] = $column = new ForeignIdColumnDefinition($this, [
            'type' => 'bigInteger',
            'name' => $column,
            'autoIncrement' => false,
            'unsigned' => true,
        ]);

        return $column;
    }

ForeignIdColumnDefinition のインスタンスが返ってきますね。

constrained

src/Illuminate/Database/Schema/ForeignIdColumnDefinition.php
    /**
     * Create a foreign key constraint on this column referencing the "id" column of the conventionally related table.
     *
     * @param  string|null  $table
     * @return \Illuminate\Support\Fluent|\Illuminate\Database\Schema\ForeignKeyDefinition
     */
    public function constrained($table = null)
    {
        return $this->references('id')->on($table ?: Str::plural(Str::before($this->name, '_id')));
    }

foreignId に返ってきた ForeignIdColumnDefinition にメソッドチェーンでつなげて呼び出します。
$table->foreign('user_id')->references('id')->on('users'); このようにテーブル名を指定しますが、 ->foreign('user_id') から users と複数形のテーブルを自動的に設定してくれます。

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

新しいアプリを作る際のLaravel環境構築(2回目以降)

はじめに

初回の環境構築はやったけど,新しくアプリを作りたいときにいろいろ調べ直すのが面倒なので,自分用にまとめました.間違い等ありましたら,ご指摘お願いします.

Homesteadの設定(参考1)

1.homesteadをgitからクローン

ターミナル
$ mkdir ~/ws/Hoge
$ cd ~/ws/Hoge
$ git clone https://github.com/laravel/homestead.git Homestead

2.init.shを実行(homesteadの初期化)

ターミナル
$ cd Homestead
$ bash init.sh

3.Homestead.yamlを編集(参考2)

ターミナル
$ vim Homestead.yaml
Homestead.yaml
ip: "192.168.10.20" #前回作ったHomesteadなどとかぶらないIPの方が良い
#--------
#〜このあたりの行はほぼ変更しないから省略〜
#--------
folders:
    - map: ~/ws/Hoge #localからプロジェクトファイルまでのパス
      to: /home/vagrant/code #vagrant(仮想環境上で)からプロジェクトファイルまでのパス

sites:
    - map: Hoge.hoge #localでアクセスするURL(これかipを使ってブラウザでアクセス)
      to: /home/vagrant/code/public # rootディレクトリのパス

4.hostsファイルを編集

ターミナル(~/ws/Hoge)
$ sudo vim ~/../../etc/hosts
hostsファイル内
#ipとホスト名を下記のようにそれぞれ追加
192.168.20.10   Hoge.hoge

5.vagrantの起動&ssh

ターミナル
$ cd ~/Hoge/Homestead
$ vagrant up
$ vagrant ssh

6.composer install

vagrant@homestead
$ cd code
$ mkdir Hoge
$ cd Hoge
$ composer install 
$ composer create-project laravel/laravel --prefer-dist 'ディレクトリ名'

7.git管理

ターミナル
# 2つめのターミナルを起動する
$ cd ~/ws/Hoge
$ git init
$ git remote add origin 'githubのリポジトリURL' #('は要らない)

Herokuへデプロイ (参考3)(参考4)

ターミナル(初めてのときはこれを実行)
# Heroku CLIのインストール
brew tap heroku/brew && brew install heroku

1.Herokuへのログイン&アプリの新規作成

ターミナル
# Herokuへログイン
$ heroku login
# Herokuアプリを新規作成し、同時にPHPを使用可能にする
$ heroku create HogeHoge --buildpack heroku/php

# リモートリポジトリの確認
$  git remote -v

2.LaravelのプロジェクトルートにProcfileを作成

ターミナル
# ProcfileはHerokuアプリの起動時に実行するプロセスを定義するためのファイル
$ echo 'web: vendor/bin/heroku-php-apache2 public/' > Procfile

3. Herokuへプッシュ(アップデート)

ターミナル
$ git push heroku master

おわりに

とりあえず最低限は書けたと思うので,今後は以下を書き足していこうと思います.

Laravel
- 認証機能

Heroku
- データベースの設定(環境変数)

Pusher
- 初期設定

参考文献

1.【Laravel超入門】開発環境の構築(VirtualBox + Vagrant + Homestead + Composer)
2.Homesteadの設定方法
3.HerokuにLaravelをデプロイする方法
4.Heroku Dev Center Buildpacks
【Laravel】Herokuを利用して無料でデプロイしてみた【手順】
Laravelをherokuにデプロイする(データベースはMySQL)

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

【Laravel7.2】Migrationを用いてテーブルを作成。Seederを用いてデータを投入する

前提環境

Laravel7.2環境を構築。Welcome!画面が表示された状態から開始。
その他、DBの設定等も済み。詳細は以下参照。

【準備編】https://qiita.com/katsuhito_01/items/db5b9581a2b6af6dc803
【導入編】https://qiita.com/katsuhito_01/items/439e3af4cea8ff00832c

Migrationを用いてテーブルを作成

まずはMigrationを用いて参照するテーブルを作成する。今回は都道府県マスタを作成。

Migration作成

Laravelプロジェクトのディレクトリ内にて、以下コマンドを実行

# php artisan make:migration create_mst_prefectures_table
Created Migration: 2020_03_22_163920_create_mst_prefectures_table

すると、database\migrations\日付_create_mst_prefectures_table.phpというファイルが作成される。
作成されたファイルをいじり、作成するテーブルの構造を記述する。
今回は以下のように記述。

【参考】:https://readouble.com/laravel/7.x/ja/migrations.html

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateMstPrefecturesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('mst_prefectures', function (Blueprint $table) {
            $table->integer('id')->primary();
            $table->string('name', 10);
            $table->string('name_kana', 10);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('mst_prefectures');
    }
}

Migration実行

構造を記述したら、Migrationを実行。

# php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.02 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.01 seconds)
Migrating: 2020_03_22_163920_create_mst_prefectures_table
Migrated:  2020_03_22_163920_create_mst_prefectures_table (0.01 seconds)

MySQLに入り、テーブルを確認。

mysql> show tables;
+-----------------------+
| Tables_in_mypage01_db |
+-----------------------+
| failed_jobs           |
| migrations            |
| mst_prefectures       |
| users                 |
+-----------------------+
4 rows in set (0.00 sec)

mysql> desc mst_prefectures;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| id         | int(11)     | NO   | PRI | NULL    |       |
| name       | varchar(10) | NO   |     | NULL    |       |
| name_kana  | varchar(10) | NO   |     | NULL    |       |
| created_at | timestamp   | YES  |     | NULL    |       |
| updated_at | timestamp   | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

出来てますね!

Seederを用いてテーブルにデータを投入

市区町村マスタができたので、Seederを用いてデータを投入する。

Modelを作成する

まずはModelを作成。
以下実行で、app直下にModelが作成される。
とりあえず今は何も書かない。

php artisan make:model MstPrefecture

ちなみに作成されたModelの中身を見てみると、空のクラスがあるだけ。
テーブルとの紐づけを明示する記述がどこにもない。

明示的に設定することもできるが、公式ドキュメントには以下の記述がある。

他の名前を明示的に指定しない限り、クラス名を複数形の「スネークケース」にしたものが、テーブル名として使用されます。今回の例で、EloquentはFlightモデルをflightsテーブルに保存します。モデルのtableプロパティを定義し、カスタムテーブル名を指定することもできます。

【引用元】https://readouble.com/laravel/5.7/ja/eloquent.html

今回でいうと、「MstPrefectur」を「mst_prefectures」と自動的に結び付けてつけてくれる。
逆を言うと、テーブル名を決める際はLaravelの命名規則に則っていないと、こういった恩恵が受けられない。
「おせっかいだ」と思った方は、Modelのクラス内に以下記述を追加することで、Modelとテーブルを明示的に紐づけることができる。

protected $table = 'テーブル名';

Seeder作成

続いてSeederを作成。

# php artisan make:seeder MstPrefecturesSeeder
Seeder created successfully.

以下のファイルが作成される。
database\seeds\MstPrefecturesSeeder.php

早速中身をいじり、投入するデータを記述する。

<?php

use Illuminate\Database\Seeder;
use App\MstPrefecture;

class MstPrefecturesSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        MstPrefecture::insert([
            ['id' =>  1, 'name' => '北海道', 'name_kana' => 'ホッカイドウ', 'created_at' => now(), 'updated_at' => now()],
            ['id' =>  2, 'name' => '青森県', 'name_kana' => 'アオモリケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' =>  3, 'name' => '岩手県', 'name_kana' => 'イワテケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' =>  4, 'name' => '宮城県', 'name_kana' => 'ミヤギケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' =>  5, 'name' => '秋田県', 'name_kana' => 'アキタケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' =>  6, 'name' => '山形県', 'name_kana' => 'ヤマガタケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' =>  7, 'name' => '福島県', 'name_kana' => 'フクシマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' =>  8, 'name' => '茨城県', 'name_kana' => 'イバラキケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' =>  9, 'name' => '栃木県', 'name_kana' => 'トチギケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 10, 'name' => '群馬県', 'name_kana' => 'グンマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 11, 'name' => '埼玉県', 'name_kana' => 'サイタマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 12, 'name' => '千葉県', 'name_kana' => 'チバケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 13, 'name' => '東京都', 'name_kana' => 'トウキョウト', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 14, 'name' => '神奈川県', 'name_kana' => 'カナガワケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 15, 'name' => '新潟県', 'name_kana' => 'ニイガタケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 16, 'name' => '富山県', 'name_kana' => 'トヤマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 17, 'name' => '石川県', 'name_kana' => 'イシカワケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 18, 'name' => '福井県', 'name_kana' => 'フクイケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 19, 'name' => '山梨県', 'name_kana' => 'ヤマナシケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 20, 'name' => '長野県', 'name_kana' => 'ナガノケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 21, 'name' => '岐阜県', 'name_kana' => 'ギフケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 22, 'name' => '静岡県', 'name_kana' => 'シズオカケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 23, 'name' => '愛知県', 'name_kana' => 'アイチケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 24, 'name' => '三重県', 'name_kana' => 'ミエケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 25, 'name' => '滋賀県', 'name_kana' => 'シガケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 26, 'name' => '京都府', 'name_kana' => 'キョウトフ', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 27, 'name' => '大阪府', 'name_kana' => 'オオサカフ', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 28, 'name' => '兵庫県', 'name_kana' => 'ヒョウゴケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 29, 'name' => '奈良県', 'name_kana' => 'ナラケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 30, 'name' => '和歌山県', 'name_kana' => 'ワカヤマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 31, 'name' => '鳥取県', 'name_kana' => 'トットリケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 32, 'name' => '島根県', 'name_kana' => 'シマネケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 33, 'name' => '岡山県', 'name_kana' => 'オカヤマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 34, 'name' => '広島県', 'name_kana' => 'ヒロシマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 35, 'name' => '山口県', 'name_kana' => 'ヤマグチケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 36, 'name' => '徳島県', 'name_kana' => 'トクシマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 37, 'name' => '香川県', 'name_kana' => 'カガワケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 38, 'name' => '愛媛県', 'name_kana' => 'エヒメケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 39, 'name' => '高知県', 'name_kana' => 'コウチケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 40, 'name' => '福岡県', 'name_kana' => 'フクオカケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 41, 'name' => '佐賀県', 'name_kana' => 'サガケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 42, 'name' => '長崎県', 'name_kana' => 'ナガサキケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 43, 'name' => '熊本県', 'name_kana' => 'クマモトケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 44, 'name' => '大分県', 'name_kana' => 'オオイタケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 45, 'name' => '宮崎県', 'name_kana' => 'ミヤザキケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 46, 'name' => '鹿児島県', 'name_kana' => 'カゴシマケン', 'created_at' => now(), 'updated_at' => now()],
            ['id' => 47, 'name' => '沖縄県', 'name_kana' => 'オキナワケン', 'created_at' => now(), 'updated_at' => now()]
        ]);
    }
}

実行するSeederに追加

投入するデータの記述ができたら、以下を編集。
実行するSeederとして追加しておく。
database\seeds\DatabaseSeeder.php

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(MstPrefecturesSeeder::class);
    }
}

Seederを実行

まずはComposerオートローダを再作成。
基本的に新しいクラスを追加したときは、このコマンドを実行しておく

# composer dump-autoload
Package manifest generated successfully.
Generated optimized autoload files containing 4098 classes

そしてSeederを実行。

# php artisan db:seed
Seeding: MstPrefecturesSeeder
Seeded:  MstPrefecturesSeeder (0.06 seconds)
Database seeding completed successfully.

MySQLよりテーブルを見てみると…

mysql> select * from mst_prefectures order by id;
+----+--------------+--------------------+---------------------+---------------------+
| id | name         | name_kana          | created_at          | updated_at          |
+----+--------------+--------------------+---------------------+---------------------+
|  1 | 北海道       | ホッカイドウ       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
|  2 | 青森県       | アオモリケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
|  3 | 岩手県       | イワテケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
|  4 | 宮城県       | ミヤギケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
|  5 | 秋田県       | アキタケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
|  6 | 山形県       | ヤマガタケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
|  7 | 福島県       | フクシマケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
|  8 | 茨城県       | イバラキケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
|  9 | 栃木県       | トチギケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 10 | 群馬県       | グンマケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 11 | 埼玉県       | サイタマケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 12 | 千葉県       | チバケン           | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 13 | 東京都       | トウキョウト       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 14 | 神奈川県     | カナガワケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 15 | 新潟県       | ニイガタケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 16 | 富山県       | トヤマケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 17 | 石川県       | イシカワケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 18 | 福井県       | フクイケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 19 | 山梨県       | ヤマナシケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 20 | 長野県       | ナガノケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 21 | 岐阜県       | ギフケン           | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 22 | 静岡県       | シズオカケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 23 | 愛知県       | アイチケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 24 | 三重県       | ミエケン           | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 25 | 滋賀県       | シガケン           | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 26 | 京都府       | キョウトフ         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 27 | 大阪府       | オオサカフ         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 28 | 兵庫県       | ヒョウゴケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 29 | 奈良県       | ナラケン           | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 30 | 和歌山県     | ワカヤマケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 31 | 鳥取県       | トットリケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 32 | 島根県       | シマネケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 33 | 岡山県       | オカヤマケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 34 | 広島県       | ヒロシマケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 35 | 山口県       | ヤマグチケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 36 | 徳島県       | トクシマケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 37 | 香川県       | カガワケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 38 | 愛媛県       | エヒメケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 39 | 高知県       | コウチケン         | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 40 | 福岡県       | フクオカケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 41 | 佐賀県       | サガケン           | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 42 | 長崎県       | ナガサキケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 43 | 熊本県       | クマモトケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 44 | 大分県       | オオイタケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 45 | 宮崎県       | ミヤザキケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 46 | 鹿児島県     | カゴシマケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
| 47 | 沖縄県       | オキナワケン       | 2020-03-23 03:17:52 | 2020-03-23 03:17:52 |
+----+--------------+--------------------+---------------------+---------------------+
47 rows in set (0.00 sec)

入ってますね!
今回はDatabaseSeeder記述のSeederをすべて実行する形でしたが、以下のように個別に実行することも可能。

php artisan db:seed --class=MstPrefecturesSeeder

次回から、CRUDを作っていきましょうか。

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

できるだけ楽にlaravel-mixから素のwebpackに移行する

laravel-mixからwebpackに移行する

webpackのラッパーであるlaravel-mixは使い始めは死ぬほど便利なのですが、さまざまな事情によりやめたくなる瞬間がやって来ることがあります。

  • 特定のnpm packageだけ別チャンクにしたい(例:正規表現等で別チャンクにするパッケージを指定する)
  • プロジェクトが依存しているnpm packageの読み込みをもっとカスタマイズしたい(例:moment.jsから不要なロケールを消す、特定のパッケージは自力でビルドする)
  • 複雑なsassビルドがしたい(例:共通変数の読み込み)
  • mix.webpackConfigでカスタマイズし続けてたら、ある日突然「これ素のWebpackで書いたほうが楽なのでは?」と感じ始めた

とはいえ、laravel-mixをやめたくなる一方で、今後も使い続けたい非常に便利な機能もあります。
ひとつめは、分割されたファイルをいい感じに読み込んでくれる点、もうひとつは、バージョニングされたファイルも1行で読み込んでくれる点です。

app.blade.php
<script src="{{ mix('js/manifest.js') }}"></script>
<script src="{{ mix('js/chunks/vendors.js') }}"></script>
<script src="{{ mix('js/app.js') }}"></script>
mix-manifest.json
{
    "/app.js": "/app.js?id=1b4046accec02c510461",
    "/app.css": "/app.css?id=ed9d614f178e884779da",
    "/manifest.js": "/manifest.js?id=186d4d6bdb3251d7b7f2",
    "/vendor.js": "/vendor.js?id=331a3da9d77df744d791"
}

そこで本記事では、laravel-mixをやめつつ上記2点の便利ポイントをwebpackで実現する方法について書きます。

※webpack+vueで最低限のビルドを通す方法は以下の記事に譲ります。
https://ics.media/entry/16028/#webpack-babel-vue
(スーパー分かりやすい記事でおすすめです!)

1. webpackのCode Splittingを使って、特定のパッケージを別ファイルにする

ここでは、moment.jsをvendors.jsに分割してみます。

webpack.config.js
entry: {
    app: path.join(__dirname, '/resources/assets/js/app.js'),
},
// optimizationのところが、ファイル分割をしている部分
optimization: {
    splitChunks: {
        cacheGroups: {
            default: false,
            // このvendorsの部分は、好きな名前にしてOK
            vendors: {
                test: /node_modules(?!\/moment)/,
                name: 'vendors',
                chunks: 'all',
            },
        }
    },
}

laravel-mixでは.extractを記述していましたが、webpackではsplitChunksと表現します。
上記の設定でビルドすると、app.jsに加えて、vendors.jsというファイルが出力できたはずです。

その他オプションなどの公式ドキュメントはこちら
https://webpack.js.org/plugins/split-chunks-plugin/

2. バージョニングしたファイルをいい感じに読み込む

まずはバージョニングする

laravel-mixでは出力したファイルにバージョンごとの値を付与することを「versioning」と言い、.versionで実行していましたが、webpackではcachingと表現します。地味に表現の仕方が違ってややこしい!

cachingするためには、outputオプションで出力ファイル名と[chunkhash]を指定します。こうすると、ファイル名の末尾に/app.js?id=1b4046accec02c510461といった感じでhashがつくようになります。

webpack.confing.js
entry: {
    app: path.join(__dirname, '/resources/assets/js/app.js'),
},
output: {
    filename: 'js/[name].js?id=[chunkhash]',
    chunkFilename: 'js/chunks/[name].js?id=[chunkhash]',
    publicPath: '/',
    path: path.join(__dirname, '/public'),
},
optimization: {
    splitChunks: {
        cacheGroups: {
            default: false,
            vendors: {
                test: /node_modules(?!\/moment)/,
                name: 'vendors',
                chunks: 'all',
            },
        }
    },
}

詳細はこちら
https://webpack.js.org/configuration/output/#outputchunkfilename

mix-manifest.jsonを、laravel-mixを使わずに自作する

app.blade.php側で<script src="{{ mix('js/app.js') }}"></script>のように簡単に読み込むためには、mix-manifest.jsonが必要です。ここでは、webpack-stats-pluginを使って自作してみます。本来はビルドした際の統計情報を書き出したりするプラグインなのですが、ビルド後の統計情報にはハッシュ付きファイル名も含まれているので、これを使ってしまおう!という作戦です。
https://github.com/FormidableLabs/webpack-stats-plugin

インストール

$ npm install --save-dev webpack-stats-plugin
または
$ yarn add --dev webpack-stats-plugin

webpackの設定

webpack.config.js
// プラグインの読み込み
const { StatsWriterPlugin } = require("webpack-stats-plugin")

// mix-manifest.jsonをどのように書き出すかを指定
const MixManifest = data => {
    return JSON.stringify({
        "/js/app.js": '/' + data.assetsByChunkName.app,
        "/js/chunks/vendors.js": '/' + data.assetsByChunkName.vendors,
    })
}

module.exports = {
// (関連なさそうなオプションは省略)
    entry: {
        app: path.join(__dirname, '/resources/assets/js/app.js'),
    },
    output: {
        filename: 'js/[name].js?id=[chunkhash]',
        chunkFilename: 'js/chunks/[name].js?id=[chunkhash]',
        publicPath: '/',
        path: path.join(__dirname, '/public'),
    },
    optimization: {
        splitChunks: {
            cacheGroups: {
                default: false,
                vendors: {
                    test: /node_modules(?!\/moment)/,
                    name: 'vendors',
                    chunks: 'all',
                },
            }
        },
    },
    // ここで、書き出すファイル名を指定
    plugins: [
        new StatsWriterPlugin({
            filename: "mix-manifest.json",
            transform: MixManifest
        })
    ]
}

上記でビルドすると、laravel-mixが出力していたmix-manifest.jsonと同じ形式のJSONファイルが出力されます。

それぞれのビルド環境によってapp.jsやvendors.jsの他にもcssファイルを出力したりとさまざまなケースがあるかと思いますが、ビルド後のファイル名はdata.assetsByChunkNameオブジェクトの中に全て入っているので、そこから抽出できます。例えばこんな感じ。

webpack.config.js
const MixManifest = data => {
    return JSON.stringify({
        "/css/app.css": '/' + data.assetsByChunkName.app[1],
        "/js/app.js": '/' + data.assetsByChunkName.app[0],
        "/js/chunks/vendors.js": '/' + data.assetsByChunkName.vendors,
        "/css/commons.css": '/' + data.assetsByChunkName.commons[1],
    })
}

これで、無事mix-manifest.jsonが出来ました!あとはbladeファイルに配置するだけです。

app.blade.php
// manifestファイルは必要ありません
<script src="{{ mix('js/chunks/vendors.js') }}"></script>
<script src="{{ mix('js/app.js') }}"></script>

それでは、webpackでカスタマイズし放題のとっても楽しい(苦しい)ライフをお過ごしください?

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