LaravelとPHPWordを使って、年賀状の宛名面を出力してみた。

PHP(Laravel)を使って、Wordファイルを出力する記事です。

わざわざLaravelとPHPWordを使ってはがき宛名面の作成は実用性低いですが、
この手順は報告書の自動作成などにも応用できます。

ちなみに、年賀状の宛名面がテーマなのはただの思いつきで決めました:sweat_smile:

動作環境
・Windows 10
・XAMPP
・Word 2016

開発環境
・Laravel 6

<h2>1.LaravelとPHPWordのインストール</h2>

Composerを利用して、Laravelのインストールを行います。
プロジェクトのフォルダに移動して、下記コマンドを実行します。

```
 $ composer create-project "laravel/laravel=6.0.*" project
```

PHPWordをインストールします。

```
$ composer require phpoffice/phpword
```

<h2>2.マイグレーションファイルを作成します。</h2>

```
$ php artisan make:migration create_addresses_table --create=addresses
```

```2020_11_09_134553_create_addresses_table.php
<?php

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

class CreateAddressesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('addresses', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
            $table->string('zipcode', 7);
            $table->string('name', 50);
            $table->string('prefecture', 30);
            $table->string('city', 30);
            $table->string('town', 100);
        });
    }

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

<h2>3.モデルを作成します。</h2>


```
$ php artisan make:model Address
```

<h2>4.コントローラーを作成します。</h2>

```
$ php artisan make:controller TestController
```
<h2>5.シーダーを作成します。</h2>

```
$ php artisan make:seeder AddressTableSeeder
```

```AddressTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class AddressTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('addresses')->insert([
            [
                'zipcode' => '1430002',     //郵便番号
                'prefecture' => '東京都',   //都道府県
                'city' => '大田区',         //市区町村
                'town' => '城南島六ー二ー一 カーム城南島 一〇〇六号室',      //町域
                'name' => '高野彦好',       //名前
            ],
            [
                'zipcode' => '1730003',     //郵便番号
                'prefecture' => '東京都',   //都道府県
                'city' => '板橋区',         //市区町村
                'town' => '加賀二ー二ー九',      //町域
                'name' => '米田政広',       //名前
            ],
            [
                'zipcode' => '1940204',     //郵便番号
                'prefecture' => '東京都',   //都道府県
                'city' => '町田市',         //市区町村
                'town' => '小山田桜台一ー一三ー八 アスコットヴィラ小山田桜台 二一二',    //町域
                'name' => '溝口為一郎',     //名前
            ],
            [
                'zipcode' => '1300025',     //郵便番号
                'prefecture' => '東京都',   //都道府県
                'city' => '墨田区',         //市区町村
                'town' => '千歳二ー七ー七五',       //町域
                'name' => '小倉真紀子',     //名前
            ],
            [
                'zipcode' => '2060041',     //郵便番号
                'prefecture' => '東京都',   //都道府県
                'city' => '多摩市',         //市区町村
                'town' => '愛宕五ー二ー九',      //町域
                'name' => '吉井孝市',       //名前
            ]
        ]);
    }
}
```

<h2>6.マイグレーションとシードを同時に実行します。</h2>

```
$ php artisan migrate:fresh --seed
```

<h2>7.Viewのレイアウトファイルを作る</h2>

```html:base.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <title>アプリケーション名</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>

<body>
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">テスト</a>
  </nav>

@yield('content')

    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>

</html>
```

<h2>8.ルーティングの設定をする</h2>

```web.php
Route::group(['prefix' => 'test'], function() {
    Route::get('index','TestController@index');
    Route::post('word_inport','TestController@word_inport');
    Route::get('word_inport','TestController@word_inport');
});
```

<h2>9.コントローラーの設定をする。</h2>
今回は、phpwordのテンプレートプロセッサを利用してdocxファイル出力をする。

```TestController.php
<?php

namespace App\Http\Controllers;

use App\Address;

use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\TemplateProcessor;

use Illuminate\Http\Request;

class TestController extends Controller
{
    //
    public function index(){
        $addresses = Address::all();
        
        return view('index',['addresses' => $addresses]);
    }

    public function word_inport(Request $request){
        $addresses = Address::find($request->id);

        $templateprocessor = new TemplateProcessor('./template/template.docx');
        $templateprocessor->setValue('zipcode',$addresses->zipcode);
        $templateprocessor->setValue('prefecture',$addresses->prefecture);
        $templateprocessor->setValue('city',$addresses->city);
        $templateprocessor->setValue('town',$addresses->town);
        $templateprocessor->setValue('name',$addresses->name);

        $templateprocessor->saveAs($addresses->name.'様宛名.docx');
        return response()->download($addresses->name.'様宛名.docx')->deleteFileAfterSend(true);
    }
}

```

<h2>10.一覧画面を作る</h2>

```html:index.blade.php
@extends('base')
@section('title', 'テスト')

@section('content')
<div class="container">
    <div class="table_position">
        <table class="table table-bordered">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>郵便番号</th>
                    <th>都道府県</th>
                    <th>市区町村</th>
                    <th>町域</th>
                    <th>名前</th>
                    <th></th>
                </tr>
            </thead>
            <tbody class="table">
            @foreach($addresses as $address)
                <tr>
                    <td>{{ $address->id }}</td>
                    <input type="hidden" value="{{ $address->id }}" name="id">
                    <td>{{ $address->zipcode }}</td>
                    <input type="hidden" value="{{ $address->zipcode }}" name="zipcode">
                    <td>{{ $address->prefecture }}</td>
                    <input type="hidden" value="{{ $address->prefecture }}" name="prefecture">
                    <td>{{ $address->city }}</td>
                    <input type="hidden" value="{{ $address->city }}" name="city">
                    <td>{{ $address->town }}</td>
                    <input type="hidden" value="{{ $address->town }}" name="town">
                    <td>{{ $address->name }}</td>
                    <input type="hidden" value="{{ $address->name }}" name="name">
                    <th><a href="{{ action('TestController@word_inport', ['id' => $address->id]) }}" class="btn btn-primary">Word出力</a></th>
                </tr>
            @endforeach
            </tbody>
        </table>
    </div>
</div>
@endsection
```

<h2>11.テンプレートファイルを置く</h2>
Wordで、宛名面のテンプレートファイルを使って図のように編集する。
<font color="red">注意：宛名印刷テンプレートが利用できるのは、Windows版のWordのみです。
Mac版の場合は、ご自身でテンプレートファイルを探してください。</font>
![スクリーンショット 2020-11-29 201401.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871835/f6bc091c-a59f-7dbb-d8bc-6c5a648844e9.png)

編集したものは、project\public\templateに置く
（ここでは、ファイル名はtemplate.docxになっている。）

<h1>動作確認をしてみる。</h1>
<a>http://localhost:8000/test/index</a>を開き、Word出力のボタンを押す。

![スクリーンショット 2020-11-29 204843.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871835/b16a132e-8b3b-e267-e7df-0982851ce205.png)

ダウンロードされたdocxファイルを開く。

![スクリーンショット 2020-11-29 204949.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871835/ac6d530b-8178-13d7-397f-f132497d7ed6.png)

以上で、LaravelとPHPWordを用いてのテンプレート出力が完了です。