LaravelのbelongsToManyで中間テーブルの情報を取得する

今回扱うテーマはデータ間の多対多の関係で2つのテーブルをつなぐ中間データが持つ情報も取得したいということを考えます。
まず、講師一覧を表すteacherというテーブルがあります。とりあえず、idとnameを持つとします。
id    name
1    鈴木
2    佐藤
3    田中
4    山田
次に、教える科目を表すsubjectというテーブルがあります。こちらも簡単に考えるため、idとsubject_nameのみを持っているとします。
id    subject_name
1    英語
2    数学
3    国語
4    社会
5    理科
さらに、講師は複数の科目を担当できるものとします。ただし、メインで教える科目とサブで教える科目は区別します。
そして、teacherとsubjectを結ぶteacher_subjectというテーブルがあります。これはteacher_id、subject_idに加えてメイン、サブを区別するtypeというカラムがあります(メインなら1、サブなら2)。
teacher_id    subject_id    type
1                  1                1
1                  4                2
2                  2                1
2                  5                2
3                  3                1
4                  4                1
4                  3                2
ここで、こんな表を作りたいとします。
講師    科目    種類
鈴木 英語 メイン
鈴木 社会 サブ
佐藤 数学 メイン
佐藤 理科 サブ
田中 国語 メイン
山田 社会 メイン
山田 国語 サブ

このとき、モデルクラスTeacher.php, Subject.phpに加えてTeacherSubject.phpをそれぞれ以下の様に用意します。

app\Teacher.php

<?php 
namespace App;
use Illluminate\Database\Eloquent\Model;

class Teacher extends Model
{
    protected $fillable = [
        'name'
    ];
    protected $table = "teacher";

    public function subjects()
    {
        return $this->belongsToMany('App\Subject', 'teacher_subject', 'teacher_id', 'subject_id')
            ->using('App\TeacherSubject')
            ->withPivot('type');
    }
}

app\Subject.php

<?php
namespace App;
use Illluminate\Database\Eloquent\Model;

class Subject extends Model
{
    protected $fillable = [
        'subject_name'
    ];
    protected $table = "subject";

    public function teachers()
    {
        return $this->belongsToMany('App\Subject', 'teacher_subject', 'subject_id', 'teacher_id')
            ->using('App\TeacherSubject')
            ->withPivot('type');
    }
}

app\TeacherSubject.php

<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;

class TeacherCountry extends Pivot
{
    protected $table = "teacher_subject";
}

こんな感じでwithPivotを使うことで中間テーブルの情報を取得することができます。中間テーブルのモデルクラスはIlluminate\Database\Eloquent\Relations\Pivotを継承して作ります。

また、ある講師に対してメインの科目だけ欲しい場合は

    public function main_subjects()
    {
        return $this->belongsToMany('App\Subject', 'teacher_subject', 'teacher_id', 'subject_id')
            ->using('App\TeacherSubject')
            ->wherePivot('type', 1);
    }

という風にwherePivotで絞り込むことができます。

Eloquentのリレーションは結構奥が深いので、是非ともしっかりとマスターしたいですね。

LaravelとVue.jsで多言語対応を行う

今回は、LaravelとVue.jsを用いたプロジェクトで多言語対応を行うやり方を紹介します。
まず、resources/langに対応する言語のjsonファイルを置きます。とりあえず、日本語と英語を想定してja.json,en.jsonとします。

ja.json

{
    "こんにちは" : "こんにちは",
    "ありがとう" : "ありがとう",
    "さようなら" : "さようなら"
}

en.json

{
    "こんにちは" : "Hello",
    "ありがとう" : "Thank you",
    "さようなら" : "Good bye"
}

次に、Laravelのbladeで表示する方法です。

index.blade.php

<span>
    {{ __("こんにちは") }}
</span>

<span>
    @lang("ありがとう")
</span>

1つ目の方法は__ヘルパ関数を使用する方法です。翻訳文字列のキーを翻訳したものに変換するヘルパ関数です(Laravel標準のヘルパ関数なのでbladeだけでなく、モデルやコントローラでも使えます)。これで変換した文字列をMustache記法でechoします。
もう1つの方法はbladeの@langディレクティブを用いる方法です。このように2通りの書き方ができますが、どちらかに統一したほうがわかりやすいかもです。

次に、Vue.jsでの多言語対応の方法です。
vue-i18nというVue.jsのプラグインを使います。vue-i18nについての詳しい説明はこことかここを読んで下さい。
まず、

npm install vue-i18n

でvue-i18nをインストールします。
次に、こんな感じでvue-i18nをjs側で読み込みます。

main.js

window.Vue = require('vue');

import VueI18n from 'vue-i18n';
Vue.use(VueI18n);

// 言語の設定
Vue.use(VueI18n);
const i18n = new VueI18n({
    locale: locale,
    messages: {
        ja : require('../../lang/ja.json'),
        en : require('../../lang/en.json')
    }
});

import MainComponent from './components/MainComponent.vue';

const app = new Vue({
    i18n: i18n,
    components: {
        MainComponent
    }
});

MainComponent.vue

<template>
<div id="main-component">
    <span>
        {{ $t("さようなら") }}
    </span>
</div>
</template>

これで、Vue.jsで多言語表示ができるようになります。

ただ、1つ問題がありまして、vue-i18nでは第一階層のデータしか読み込めないので、

ja.json

{
    "果物一覧" : {
        "りんご" : "りんご",
        "みかん" : "みかん",
        "バナナ" : "バナナ"
    }
}

en.json

{
    "果物一覧" : {
        "りんご" : "apple",
        "みかん" : "orange",
        "バナナ" : "banana"
    }
}

のようなデータがこのままでは読み込むことが出来ないのです。
その場合は以下のように一旦blade側で加工してからコンポーネントに渡します。

index.blade.php

<script>
    var fruits_list = JSON.parse('{!! json_encode((__("果物一覧"))) !!}');
</script>

<main-component></main-component>

main.js

window.Vue = require('vue');

import VueI18n from 'vue-i18n';
Vue.use(VueI18n);

// 言語の設定
Vue.use(VueI18n);
const i18n = new VueI18n({
    locale: locale,
    messages: {
        ja : require('../../lang/ja.json'),
        en : require('../../lang/en.json')
    }
});

import MainComponent from './components/MainComponent.vue';

const app = new Vue({
    i18n: i18n,
    components: {
        MainComponent
    },
    data: function() {
        return {
            fruits_list : fruits_list
        }
    }
});

MainComponent.vue

<template>
<div id="main-component">
    <span v-for="fluit in fruits_list">
        {{ fluit }}
    </span>
</div>
</template>

自分はこんな感じのやり方でやりました(もしかしたらもっといいやり方もあるかもしれないので、他にいいやり方があれば教えていただければと思います)。

また、今回は言語切替機能については触れませんでしたが。そのあたりについてはこちらが参考になりました。

久々にローカル環境で作業したときにたまにやりがちなこと

とりあえずphp artisan make:migrationでマイグレーションファイル作って、さあphp artisan migrateと打って、

あれ??

https://qiita.com/hondy12345/items/d32ed749fb49e9da7de6
MySQLのサーバー立ち上げてなかった(汗)

PHPフレームワーク Laravel入門

今のところ、書店でよく売られているLaravelについて書かれた本はそんなに多くなく(どちらかというとCakePHPの方がよく売っている印象)、かつ現時点では知っている限りでは一番新しい本ではないかと思う。
本の印象としては、Laravelの基本的なことがコンパクトにまとめられていて、全体的に読みやすいと思う。個人的にはLaravelのミドルウェアについて理解が浅かったころChapter4の「リクエスト・レスポンスを補完する」を読んで理解が深まった気がする。
欲を言えば、最後のChapter7がいろいろな内容(セッション、ページネーションなど)があっさりとすまされているので、その辺りをもう少し増強してほしかったという気もする。
ちなみに、この本はLaravel5.4(2018年7月30日時点最新は5.6)を前提に書かれているので、それ以外のバージョンを使う場合は日本語版Laravelドキュメントも参考にしつつ(英語が得意な方は公式サイトでいいかと)、手を動かしながら使っていくことでLaravelへの理解が深まるのではないかと思う。