20200914のlaravelに関する記事は10件です。

【Laravel】APIでSessionが使えなかった時の予備録

laravelでAPIでルーティングされている処理の中でSessionを呼び出そうと思ったら、
エラーになりました。。

下記が追記したAPIのルーティングファイルです。

routes/api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});
Route::post('/api/func/', 'ApiController@cardAuth');

そして以下がAPIの処理になります。
今回はカード情報をrequestで取得したあと、Sessionに入れようとしました・・・

Controllers/ApiController.php
public function cardAuth(Request $request) {

        Session::put(self::KEY_SESSION_ONE, $request->all());

        $ss_one = Session::get(self::KEY_SESSION_ONE)

        $model = new InfoForm($ss_one);


        〜〜 (処理) 〜〜

が、設定しておいたloggerを見てみると、
$ss_one内に値が設定されていないというエラーの連続。

〜〜以下からが解決方法です!〜〜
appディレクトリのKarnel.phpを見てみましょう。
デフォルトでは'api'にSessionに関する記述が書かれていません。
なので追記します。

app/Karnel.php
                     〜(中略)〜

protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            \App\Http\Middleware\EncryptCookies::class, //追記
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, //追記
            \Illuminate\Session\Middleware\StartSession::class, //追記
            \Illuminate\View\Middleware\ShareErrorsFromSession::class, //追記
            'throttle:60,1',
        ],
    ];

こうすればAPIルーティングされた処理の中でもSessionを使うことが可能になります!
Modelの設定だと思い込み1時間ほど悩まされました。。笑

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

【初心者向け】LaravelアプリケーションをHerokuで公開しよう!【MySQL】

はじめに

Laravelアプリケーションを作成し、Herokuでいざ公開しようと思ったものの、これが意外や初心者には難しい。私はアプリケーションを公開するだけで3日間も悪戦苦闘してしまいました。同じ初心者の方には辛い思いをして欲しくないので、備忘録も兼ねてマニュアル記事を作成しました。

使用環境

・PHP7.2
・Laravel5.5
・mysql5.7
・Docker
※本記事では環境構築については解説いたしません
※PCはMacを使用しています

①アプリケーションをGitリポジトリに入れよう

HerokuはGitの情報を用いてアプリケーションを公開します。そのため、まずはアプリケーションをGitリポジトリに入れる必要があります。
Gitについては以下のサイトが分かりやすいです。

https://backlog.com/ja/git-tutorial/intro/01/

Gitの設定

まずは名前とメールアドレスを設定しましょう。以下のコマンドをターミナルに入力します。
※ご自身の名前とメールアドレスを入力してください。

$ git config --global user.name "haruto.takahashi"
$ git config --global user.email "haruto.takahashi@gmail.com"

設定した内容は以下のコマンドで確認できます。

$ git config --global -l

core.editor=/usr/bin/nano
user.name=haruto.takahashi
user.email=haruto.takahashi@gmail.com

リポジトリの作成

まずはアプリケーションのあるディレクトリに移動します。

$ cd アプリケーション

次に以下のコマンドを入力することでリポジトリが作成されます。

$ git init

「Initialized empty Git repository in〜」と表示された場合は、指定のディレクトリに「.git/」というGitリポジトリが設置されたということになります。
以下のコマンドで現在のステータスを確認してみましょう。

$ git status

「No commits yet」と表示されるはずです。コミットされたファイルがないという意味です。

ステージの実行

以下のコマンドを入力し、全てのファイルのステージを実行します。

$ git add .

再び以下のコマンドで現在のステータスを確認してみましょう。

$ git status

今度は「new file:」としてステージされたファイルが無数の羅列となって表示されているかと思います。

コミットの実行

以下のコマンドを入力し、コミットを実行します。

$ git commit -m "first-commit"

「first-commit」の部分は何でも良いのですが、git commit のコマンドの後に、-m "(メッセージ)" と付けることで、どんな変更を行ったかというコミットメッセージを入力することが可能です。
「create mode」と書かれた羅列が表示されていればコミット完了です。今後アプリケーションに変更を反映させる時は、同じようにコミットを実行しましょう。Herokuで公開後も同じです。

②Herokuの設定をしよう

Gitの設定が完了したところで、次にHerokuの設定を行っていきます。Herokuへアプリケーションを公開(デプロイ)するためにはいくつか準備が必要です。

アカウントの作成

以下のページよりアカウントを作成してください。今回は無料版の使用を前提とします。
Heroku

設定については以下のページが参考になります。
https://blog.proglus.jp/1438/

Heroku-CLIの導入

Herokuをターミナルから操作できるようにするためのツールとしてHeroku-CLIを導入します。
まずは以下のコマンドを実行します。

$ wget https://cli-assets.heroku.com/heroku-linux-x64.tar.gz -O heroku.tar.gz
$ sudo mkdir -p /usr/local/lib/heroku
$ sudo tar --strip-components 1 -zxvf heroku.tar.gz -C /usr/local/lib/heroku

なお「-bash: wget: コマンドが見つかりません」と表示された場合は、以下のコマンドでwgetをインストールしましょう。

$ brew install wget

brewも使用できない場合は同様にインストールが必要です。インストール方法はネットで検索すれば出てくるのでぜひ探してみてください。

シンボリックリンクの作成

導入が完了したら、次にシンボリックリンクを作成します。シンボリックリンクとは特定のファイルを別の場所から参照できるようにするためのもので、簡単に言うとWindowsのショートカットのようなものです。

シンボリックリンクとは

シンボリックリンクを設定するには以下のコマンドを実行します。

$ sudo ln -s /usr/local/lib/heroku/bin/heroku /usr/local/bin/heroku

なお余談ですが、シンボリックリンクを削除したい時は以下のコマンドを実行します。

$ unlink /usr/local/bin/heroku

シンボリックリンクの設定が完了したら、以下のコマンドでHerokuへログインします。アカウント作成時に設定したメールアドレスとパスワードを聞かれるので入力しましょう。

$ heroku login -i

heroku: Enter your login credentials
Email: Herokuに登録済みのメールアドレスを入力
Password: Herokuに登録済みのパスワードを入力

③Herokuアプリケーションを作成しよう

アプリケーションの作成

Herokuで公開するためのアプリケーションを作成します。下記のコマンドで実行されます。この時、アプリケーションの名前も設定しましょう。

$ heroku create 任意のアプリ名

なお同じ名前のアプリケーションが既に作成されていた場合は、他者と重複しないよう名前を変更する必要があります。またその他の名前のルールとして、大文字やアンダーバー(_)はNGです。
作成後は以下のコマンドで名前が正しく登録されているかを確認します。

$ heroku apps

Procfileファイルの作成

Procfileファイルとは、Herokuのプラットフォーム上にあるWebアプリがどのようなコマンドで実行されるのかを記述するファイルのことです。以下のコマンドで作成できます。

$ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile

Herokuのapache2(Webサーバソフト)を使用するという記述になります。
ここで一度、Gitでコミットを実行します。

$ git add .
$ git commit -m 'add procfile'

④アプリケーションを公開しよう

いよいよ最終段階...ですが設定しなければいけないことがまだいくつかあります。

データベースの設定

Herokuでは、PostgreSQLが標準のデータベースとなっています。MySQLを利用するにはClearDBというクラウドサービスを活用します。以下のコマンドで追加できます。

$ heroku addons:add cleardb

環境変数の設定

Gitコミットを実行したファイルには.envファイルが含まれていないため、これまでとは別途で環境変数を設定する必要があります。
まず以下のコマンドを実行することで、Herokuでローカル環境と同じAPP_KEYが生成されます。

$ heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show)

以下のコマンドでHerokuアプリケーションの環境変数を確認できます。

$ heroku config

=== youtube-curation Config Vars
APP_KEY:      base64:設定されたAPP_KEYが表示
CLEARDB_DATABASE_URL: mysql://ユーザ名:パスワード@ホスト名:5432/データベース名

「DATABASE_URL」に表示されている内容を元に、以下のコマンドで環境変数の設定を行います。それぞれコピペしましょう。

$ heroku config:set DB_USERNAME=ユーザ名
$ heroku config:set DB_PASSWORD=パスワード
$ heroku config:set DB_HOST=ホスト名
$ heroku config:set DB_DATABASE=データベース名

またデータベースの設定も行います。使用するデータベースはMySQLなので以下のコマンドを実行します。

heroku config:set DB_CONNECTION=mysql

最後にもう一度、環境変数が正しく設定されているかを確認しましょう。

$ heroku config

=== youtube-curation Config Vars
APP_KEY:       base64: APP_KEY
CLEARDB_DATABASE_URL:  mysql://ユーザ名:パスワード@ホスト名:5432/データベース名
DB_CONNECTION: mysql
DB_USERNAME:   ユーザ名
DB_PASSWORD:   パスワード
DB_HOST:       ホスト名
DB_DATABASE:   データベース名

確認ができたら以下のコマンドでHerokuアプリケーションのマイグレーションを実行します。

$ heroku run php artisan migrate

以下のように

Do you really wish to run this command? (yes/no) [no]:

と聞かれた場合は「y(yes)」と答えます。

またシーダーを挿入する場合は以下のコマンドも実行します。

$ heroku run php artisan db:seed

Herokuアプリケーションへのアクセス

設定は以上です。お疲れ様でした。
以下のURLからアプリケーションへアクセスしましょう。

https://Herokuアプリ名.herokuapp.com/

アプリケーションへの接続がうまくいかない場合は環境変数を見直してみましょう(私もここでミスがありました)
先ほどと同じ「heroku config:set」のコマンドを用いることで、環境変数を上書きすることができます。

【補足①】Heroku公開後にアプリケーションの更新を反映する方法

復習になりますが、以下のコマンドでHerokuアプリケーションに変更が反映されます。

$ git add .
$ git commit -m 'メッセージ'
$ git push heroku master

【補足②】Heroku公開後にエラーが発生した場合

Herokuアプリケーションはエラー発生時に「something went wrong.」というメッセージのみ表示されます。しかしこれではエラーの原因が分からないままです。以下のコマンドを実行することで、エラーの詳細を表示することができます。

$ heroku config:set APP_DEBUG=true

先ほどのメッセージが表示された画面を更新すると、エラーの詳細が表示されるはずです。
エラーが解決したら以下のコマンドでエラーの詳細が表示されないように設定を戻しておきましょう。

$ heroku config:set APP_DEBUG=false

あとがき

私は初めてアプリケーションを作成した時に、ネットで公開するだけでまさかこんなにたくさんの手順があるとは思いもよらず絶望していました。この記事がそんな辛い思いをしている駆け出しエンジニアの方のお役に立てば幸いです。最後までお読みいただきありがとうございました!

参照サイト

https://yu-nocode.com/wp/entry/laravel-quest-6/#i
https://qiita.com/yu731994/items/86e03c5ff91aa3ba7e9d
https://qiita.com/fukkun/items/dfa7002371b9f6e1abae
https://laraweb.net/environment/4115/

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

Eloquentモデルの名前空間が他の階層で重複している時("Cannot declare class 〜, because the name is already in use")

クラス名重複してるよ〜のエラーメッセージが出る場合...

①対処法

1:本当に記述している文字列が正しいか確認する
2:namespaceの階層が正しいか確認する(\App\Models\temp...)
3:asで別名を付与(詳細は以下参照)

②それ以外の場合 とは?

あまり多くないパターンだと思いますが、自分が修正を担当しているプロジェクトのModelsの階層がこんな感じでした。

\APP
 \temp.php(フルパス:\APP\temp.php)

 \Models
  \temp.php(フルパス:\APP\Models\temp.php)

最初見た時、Laravelはこんなふうになってるのかーと思って特に気にしませんでした。
(Eloquentモデルと通常のModelなので役割はそもそも違います)
が、後々機能を追加するとなったときになって困りました。

use APP\Model\Temp
use APP\Temp

Cannot declare class〜〜〜〜, because the name is already in use

これはNGなんですね...。
記述や文字列の誤りがない、階層が違う、としても同名だとそもそもインポートNGのようです。

use APP\Model\Temp
use APP\Temp as eloquent_temp

こんな感じに別名であれば解決します。
なので正確には同名クラスからのインポートがNGというわけではないです。

※そもそも3のパターンは命名の時点でおかしいので、Eloquentモデルの作成時にはmodelと同名にするべきではないです!

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

【備忘録】Eloquentモデルの名前空間が他の階層で重複している時("Cannot declare class 〜, because the name is already in use")

クラス名重複してるよ〜のエラーメッセージが出る場合...

①対処法

1:本当に記述している文字列が正しいか確認する
2:namespaceの階層が正しいか確認する(\App\Models\temp...)
3:asで別名を付与(詳細は以下参照)

②それ以外の場合 とは?

あまり多くないパターンだと思いますが、自分が修正を担当しているプロジェクトのModelsの階層がこんな感じでした。

\APP
 \temp.php(フルパス:\APP\temp.php)

 \Models
  \temp.php(フルパス:\APP\Models\temp.php)

最初見た時、Laravelはこんなふうになってるのかーと思って特に気にしませんでした。
(Eloquentモデルと通常のModelなので役割はそもそも違います)
が、後々機能を追加するとなったときになって困りました。

use APP\Model\Temp
use APP\Temp

Cannot declare class〜〜〜〜, because the name is already in use

これはNGなんですね...。
記述や文字列の誤りがない、階層が違う、としても同名だとそもそもインポートNGのようです。

use APP\Model\Temp
use APP\Temp as eloquent_temp

こんな感じに別名であれば解決します。
なので正確には同名クラスからのインポートがNGというわけではないです。

※そもそも3のパターンは命名の時点でおかしいので、Eloquentモデルの作成時にはmodelと同名にするべきではないです!

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

HerokuにデプロイしたLaravelアプリでDBのレコード表示(日本語)が文字化け

問題

先日、Laravelで制作しているクチコミ投稿サイトをHerokuにデプロイしました。データベースにはClearDB MySQLを使用していますが、日本語の文字化けが発生しました。YouTube万屋エンジニアチャンネル様の多大な協力のおかげで解決できました。

状況整理

  • MacターミナルのMySQLでINSERTしたデータはブラウザで表示するとƒ–ルーノート最高のミïみたいに文字化けする
  • 一方ブラウザ上のフォームから投稿した内容はターミナルで表示すると?????????となる
  • ただし、ターミナルでINSERTしたデータはターミナル上ではきちんと表示され、ブラウザのフォームから投稿したデータはブラウザ上ではきちんと表示される

ちなみに、teratailにも質問投稿していました→ https://teratail.com/questions/291553?reply=true

環境確認

Heroku, ClearDB MySQL, Laravel 7, MacOS

原因は何か?

上のteratailを見ていただくとわかりますが、私は文字コードに関連しそうな箇所の見当をつけるべくviewの

のやdatabase.phpなど見当違いな箇所を見てましたが、今回に関しては関係ありませんでした。

原因はMySQLクライアントの文字コード設定でした。ターミナルでMySQLにログインして下記コマンドで確認できます↓

mysql> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

↑このlatin1をutf8に変更する必要があります。変更にはMySQLの設定ファイルをいじることが必要です。

MySQLの設定ファイルを探せ!

設定ファイルはmy.cnfで、複数のディレクトリに存在していて、優先順位があるみたいです。下記コマンドで、それぞれのディレクトリと優先順位を確認できます。

$ mysql --help | grep my.cnf
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf

1つめのディレクトリにはファイルが存在しませんでした...↓

$ cd /etc/my.cnf
-bash: cd: /etc/my.cnf: No such file or directory

2つめはディレクトリが存在しませんでした...↓

$ cd /etc/mysql
-bash: cd: /etc/mysql: No such file or directory

3つめのディレクトリにはありました...↓

$ cd /usr/local/etc
$ ls
bash_completion.d   freetds.conf        locales.conf        odbc.ini        openldap        php
fonts           gitconfig       my.cnf          odbcinst.ini        openssl@1.1     pool.conf

catコマンドでファイルを閲覧します↓catは、concatenate(連結するの意)の略でファイルを閲覧したり連結コマンド。

$ cat my.cnf
# Default Homebrew MySQL server config
[mysqld]
# Only allow connections from localhost
bind-address = 127.0.0.1
mysqlx-bind-address = 127.0.0.1

↑character(文字)に関する設定がありません。これを使っていきます!

その前に一応4つめも↓...ありません。

$ cd ~/.my.cnf
-bash: cd: /Users/私のユーザー名/.my.cnf: No such file or directory

番外編で下記の方法でも探しました。大量の結果が出てきて、しかも長かったので途中でCtrl+cでキャンセルしましたが、2点ほど気になる結果が。

$ find / -name "my*.cnf"
find: /usr/sbin/authserver: Permission denied
/usr/local/etc/my.cnf
/usr/local/Cellar/mysql/8.0.21_1/.bottle/etc/my.cnf

一応中を覗いてみるとこんな感じ↓でもこれは一旦無視。

$ cd /usr/local/Cellar/mysql/8.0.21_1/.bottle/etc
$ ls
my.cnf
$ cat my.cnf
# Default Homebrew MySQL server config
[mysqld]
# Only allow connections from localhost
bind-address = 127.0.0.1
mysqlx-bind-address = 127.0.0.1

my.cnfファイルに文字コードの設定を追記する

/usr/local/etc/my.cnfファイルをいじっていきます。
下記のように[mysqld]にcharacter-set-server = utf8、[client]にdefault-character-set = utf8を追記しました。(アンダーバーとハイフンなどスペルミスお気をつけください!汗)
念のため、開くコマンドは$vi my.cnf、開いたらINSERTのiで編集モード、終わったらescボタン :wq Enterボタンです。

my.cnf
[mysqld]
# Only allow connections from localhost
bind-address = 127.0.0.1
mysqlx-bind-address = 127.0.0.1
character-set-server = utf8
[client]
default-character-set = utf8
[mysql]

結果確認

MySQLを再起動($ mysql.server stop $ mysql.server start)して、見てみると...↓

mysql> show variables like "character%";
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

↑character_set_serverがlatin1のままなのは気になりますが、この状態でターミナルからINSERT文で挿入したレコードの日本語はきちんとブラウザで表示され、ブラウザのフォームから投稿して挿入されたレコードはターミナルのMySQLできちんと日本語で表示されるようになりました。

ちなみに、過去に文字化けしたレコードはそのまま文字化けしたままです。

もしこれでうまく行かなかったらぜひコメントください m(_ _)m

YouTube万屋エンジニアチャンネル様、重ね重ねありがとうございました。

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

Cannot use '$this' in non-object context エラーの対処法

Laravelを使用中に、モデル内で$this->を使って当該モデルを参照しようとしたところ
Cannot use '$this' in non-object contextのエラーが出たので備忘録として対処法を残しておきます

結論からいうと当該モデルのgetUser()がインスタンス化されていないのでself::でアクセスするのが正解でした

Model.php
  public static function getUser($ids){
        return self::whereIn('id', $ids);
    }

上記で$this->からself::に変更したらエラーが改善しました

Controller.php
 public function index()
    {
        $searchResults =  Model::getUser([1,2,3])->get();
        return response()->json([
            'search_results' => $searchResults,
        ], 200);
    }

思考停止してしまって、インスタンス化など全く意識せずに何でもかんでも$this->を使っている状態だったので
はまってしまったエラーでした

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

【備忘録】Laravel Gate権限制御にて@canだとクエリ数が増えちゃった話&対処法

Gate機能のcanによる判定でクエリ数がめちゃくちゃ増えてたら...

①対処法

blade内での@canによる判定箇所を@ifに変更
および使いたい権限パラメータの受け渡し方を変える

②原因

@canによる判定の度にPolicy内のコンストラクタによって権限取得のためのクエリ実行が行われてしまうため

③例

①の通り対象のbladeにて@can記述を@ifに変更
 →controllerでcompact、withメソッドの引数に追加
  →viewで受け取って好きなように使用

(compactメソッドに関してはわかりやすい記事がたくさんありますのでそちらをご覧ください)


あまり深掘りできていないですが、Gate機能の仕様と思われます。
indexなどその他の対処がしてあり、処理速度に影響がなければ@canのままで問題ないのですが
自分の場合は対処前だとクエリ重複多数(7~8割)になっていました。
以上となります。参考になれば幸いです。

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

【Laravel】Cannot declare class ◯◯◯, because the name is already in use"【備忘録】

クラス名重複してるよ〜のエラーメッセージが出る場合...

①対処法

1:本当に記述している文字列が正しいか確認する
2:namespaceの階層が正しいか確認する(\App\Models\temp...)
3:それ以外の場合は以下参照

②それ以外の場合とは

自分の場合なので


以上です。

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

composer installのエラー

ターミナルで"composer install"と打ったところ、次のようなエラーメッセージが表示された。

Problem 1
    - Installation request for league/flysystem 1.0.66 -> satisfiable by league/flysystem[1.0.66].
    - league/flysystem 1.0.66 requires ext-fileinfo * -> the requested PHP extension fileinfo is missing from your system.
  Problem 2
    - league/flysystem 1.0.66 requires ext-fileinfo * -> the requested PHP extension fileinfo is missing from your system.
    - laravel/framework v5.8.37 requires league/flysystem ^1.0.8 -> satisfiable by league/flysystem[1.0.66].
    - Installation request for laravel/framework v5.8.37 -> satisfiable by laravel/framework[v5.8.37].

調べたところ、この”extension fileinfo"というところがキーになるらしい。

extension=php_fileinfo.dll

をphp.iniで有効化するということだったのだが、私の場合は探してもなかったのでphp.iniに書き加えた。
すると無事インストールできた。

参考:https://qiita.com/sola-msr/items/95e06e66730468b6c7bc

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

laravelでテスト用DBを設定する手順

ほとんどをよしなに手軽にやってくれるLaravelですが、
DBを使うphpunit設定はちょっと分かりにくいです。

SQLSTATE[HY000] [1044] Access denied for user 'user'@'%' to database 'test_db'

↑phpunitのコマンドでこんな表示があった人は、幸せにできる記事です。

※DBはmysql

設定のポイント

・テスト用のDB(スキーマ)を作る必要がある
作成したスキーマに、テスト時に使う接続設定(ユーザー権限)を加える必要がある
・phpunit側に接続情報を加える必要がある

1 テスト用のDBを作成する

ここではrootユーザーで接続している想定です。

CREATE SCEMA test_db;

2 アクセス権限の設定

laravelの接続情報(.envに書くDB_USERNAMEのとこ)がroot以外のユーザーの場合、
デフォルトではrootユーザーが作成したDBへのアクセス権限がない場合がある(rootユーザ以外でSHOW DATABASESしてもDB一覧に表示されない)。

ので、rootユーザーでGRANT文を実行、アクセス権限を与えて、テストで使えるようにしてあげる

GRANT ALL ON test_db.* TO user(ユーザー名);

もし権限を与えたいユーザー名がわからない時は、mysqlスキーマから確認

mysql> SHOW DATABASES; -- スキーマ一覧を表示

+--------------------+
| Database           |
+--------------------+
| information_schema |
| app_db             |
| mysql              |
| performance_schema |
| sys                |
| test_db            |
+--------------------+

mysql> use mysql;

mysql> select * FROM user;
-- ユーザーとHOST(どこからの接続を許容するか)、ユーザーが持つ権限も表示される

※ アプリ用DBユーザとテスト用DBユーザを分けるメリットはそれほどないと思うので、laravelの.envに書いてあるユーザーでいいと思います。

3 phpunit.xmlに接続情報を記入

あとは、.envに書いてある接続情報を、phpunit.xmlに書いてあげればOK!

DB_DATABASE=db # アプリで使うDB
DB_USERNAME=user
DB_PASSWORD=pw

.envに↑みたいに書いてあったら、↓のように書く。

    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="MAIL_DRIVER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <!-- テストで使うDBのスキーマ名 -->
        <server name="DB_DATABASE" value="test_db"/>
        <!-- 接続するuserの名前 -->
        <server name="DB_USERNAME" value="user"/>
        <!-- 接続するuserのパスワード -->
        <server name="DB_PASSWORD" value="pw"/>
    </php>

DBを使うテストファイルを実行してみましょう。

./vendor/bin/phpunit ./tests/Feature/DatabaseTest.php

記事冒頭のエラーで困っていた人は、解決できているハズ!

その他phpunitの準備に役立ちそうな記事

PHPUnitの使い方メモ

MySQLをMacのターミナルで操作するときのメモ

おわりに

DBに接続する時の設定をする、という当然のことをしただけなんですが、人が用意してくれた自動化環境(AWSやらdocke)に慣れてしまうと、触れる機会が少なくなってしまうものです。

こういう基本的なとこに触れるのも、たまにはいいですよね。

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