2022年 4月 の投稿一覧

Laravelで複数のDBへ接続する

こんばんは、ウチイダです。

この前お引き受けしたお仕事で、複数のDBサーバを利用する案件がありました。

  • 全データを集積しているDB(マスタDB)から必要な内容を取得し、自前のDB(アプリDB)に保存
  • アプリDBには、独自に算出して業務に用いるカラムがある

という感じに開発するもので、モデル自体を別のものとして扱う方がよさそうでした。

というわけで、モデルごとに、別のDBのテーブルと連携させるための設定を調べました。

それをメモしておきます。

ちなみに、利用したLaravelのバージョンは9です。

今後の新規プロジェクトで利用できると思います。

1. .envに接続情報を分けて記載する

.envに、二つのDBの接続情報を記載します。以下のような感じです。

※もちろん、値はすべて仮のものです。

# 自前のDB(アプリDB)接続設定
APP_DB_CONNECTION=app
APP_DB_HOST=app.example.com
APP_DB_PORT=3306
APP_DB_DATABASE=app
APP_DB_USERNAME=app_user
APP_DB_PASSWORD=password

# データを集積しているDB(マスタDB)の接続設定
MASTER_DB_CONNECTION=master
MASTER_DB_HOST=master.example.com
MASTER_DB_PORT=3306
MASTER_DATABASE=master
MASTER_DB_USERNAME=master_user
MASTER_DB_PASSWORD=password

2. LaravelのDB接続設定で、envに記載した内容を反映

config/database.php で、データベースの接続設定がまとめられています。

.envで指定した内容がLaravel内で利用できるように設定していきます。

設定項目が多いように見えますが、デフォルトで「mysql」 という名前の接続情報があるので、それをベースに一部を書き換えるだけなので、それほど難しくはありません。

    /* 18行目あたり */
    /* デフォルトの接続情報はappにする */
    'default' => env('APP_DB_CONNECTION', 'app'),

    /* connections の中で、.envに指定した内容を記入する */
    'connections' = [
        /* アプリDB用の接続設定 */
        'app' => [
            'driver' => 'mysql',
            'url' => env('APP_DB_URL'),
            'host' => env('APP_DB_HOST', '127.0.0.1'),
            'port' => env('APP_DB_PORT', '3306'),
            'database' => env('APP_DATABASE', ''),
            'username' => env('APP_DB_USERNAME', ''),
            'password' => env('APP_DB_PASSWORD', ''),
            'unix_socket' => env('APP_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'),
            ]) : [],
        ],

        /* マスタDB用の接続設定 */
        'app' => [
            'driver' => 'mysql',
            'url' => env('MASTER_DB_URL'),
            'host' => env('MASTER_DB_HOST', '127.0.0.1'),
            'port' => env('MASTER_DB_PORT', '3306'),
            'database' => env('MASTER_DATABASE', ''),
            'username' => env('MASTER_DB_USERNAME', ''),
            'password' => env('MASTER_DB_PASSWORD', ''),
            'unix_socket' => env('MASTER_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'),
            ]) : [],
        ],
    ],

3. モデルファイルで、接続先のDBを指定する

次に、モデルファイルに$connection を追加し、利用する接続先の名称を指定します。

以下は、アプリDBのsamples テーブルを利用するモデルの例です。

<?php

namespace App\Models\App;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Sample extends Model
{
    use HasFactory;

    /* アプリDBへ接続する */
    protected $connection = 'app';
}

4. モデルを使ってみる

これで準備は整いました。ためしに、コントローラから呼び出してみます。

<?php

namespace App\Http\Controllers;

use App\Models\App\Sample;

class ConnectionTestController extends Controller
{

    public function test()
    {
        /* samples テーブルから1件データを取り出してみる */
        dd(Sample::first());
    }
}

ルーティング設定してブラウザからアクセスし、データが表示されたら成功です。

同じ要領で、マスタDB用のモデルも作成できます。

cinfig/connection.php に接続情報をまとめていることが理解できていれば、記述するコードの内容は想定してたより難しくありません。

フレームワークごとに設定の仕方はいろいろなので、このあたりは実際に案件を通じて経験したり、じっくりドキュメントなどを読んで理解を深めていくことが不可欠ですね。

おまけ:DB ファサードで接続先を指定する

上記の設定をした前提で、DB ファサードからマスタDBへ接続する場合は以下のようにします。

DB::connection('master')->table('sample')->first();

connection() メソッドを書かなければ、デフォルト設定しているapp が使われます。

以上です。あなたのお役に立てれば幸いです。

Docker コンテナのリソース使用率を調べるのに便利なコマンド ctop

こんばんは、ウチイダです。

先日、Webアプリケーションのチューニングコンテストに参加しました。

パフォーマンスの計測とボトルネックの発見を担当したのですが、その際に使用したctop というコマンドが便利だったのでメモしておきます。

公式リポジトリはこちらです。

https://github.com/bcicen/ctop

WSL2 へのインストールは以下でできました。

$ sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.1/ctop-0.7.1-linux-amd64  -O /usr/local/bin/ctop
$ sudo chmod +x /usr/local/bin/ctop

Docker コンテナの稼働状況をみたいのがウチイダの用途なので、–type オプションをつけて実行します。

$ ctop --type=docker

Laravel Sailのコンテナを立ち上げて、上記コマンドを実行すると、以下のようにモニタリングできます。

dtop –type=docker 実行結果

スクリーンショットだと見切れていますが、CGROUP のところにグループ名が書かれていて、どのコンテナかわかるようになっています。

上下キーでコンテナを選択して、 e キーでコンテナのターミナルをすぐ開けるのも便利です。

以上、あなたのお役に立てれば幸いです。

Laravel 9 にLaravel Mix でjQuery を追加する

こんばんは、ウチイダです。

Laravelの案件でも、フロントをjQueryにするパターンはちょいちょいありますね。

初期構築の際、いつもインストールに手間取るので、未来の自分のために書いておくことにします。

vueのやり方は検索に出てくるんですけど、jQuery はないのはなぜなのでしょうね…?

1. npm でjQuery をインストール

$ npm install jquery --save-dev 

2. webpack.mix.js を編集

autoload() でjQueryを指定するだけで、public/app.jsにも含まれるし、$で呼び出せるようにもなります。

bootstrap.js などrequire() を書く必要があるのかと思ってしまうのですが、それもいりません。

mix.js("resources/js/app.js", "public/js")
    .sass("resources/scss/custom.scss", "public/css")
    .postCss("resources/css/app.css", "public/css", [
    ])
    /* 以下を追記 */
    .autoload({
        jquery: ["$", "window.jQuery"],
    });
    /* 追記ここまで */

3. npm run でコンパイル

コンパイルします。

$ npm run dev

全く関係ないですが、コンパイルは機械語への変換のことだと理解していたので、JavaScript を「コンパイルする」という言葉遣いはいまだに違和感がぬぐえないんですよね…

4. View で読み込み

Blade テンプレートのヘッダ部分などに、以下を追記します。

<script src="{{ mix('js/app.js') }}"></script>

以上です。

あなたのお役に立てれば幸いです。

Laravel sail で外部APIアクセスエラーする

こんばんは、ウチイダです。

先日お引き受けした案件で、Laravelから外部APIを利用する実装が必要になりました。

いつものように、ローカル環境のSailで動作確認しつつ実装していきます。

しかし、Httpファサードで外部APIにアクセスしようとするとResolving タイムアウトが発生してしまいました。

どうやら、名前解決に失敗しているみたいです。

Dockerネットワーク外のドメインの名前解決をするDNSが設定されていないことが原因だったので、Docker-compose.ymlに、dnsを設定しました。

# For more information: https://laravel.com/docs/sail
version: '3'
services:
    laravel.test:
				# (略)

        # 外部DNSを指定する
        dns: 8.8.8.8

いったんコンテナを再起動してDNSを認識できるようにしてからリトライ。

APIサーバを見つけて、レスポンスを取ることができました。

ちなみに、これに苦労してあれこれコントローラのアクションメソッドに書き散らかしてしまったので、その後サービスクラスに切り出すのにそこそこ苦労しました(現在進行形でしてます)。

思いがけない沼にはまると、設計やクラス分解がおろそかになりがちなので気を付けたいです。

以上です。

あなたのお役に立てれば幸いです。

Laravel Sailに追加したPhpMyAdminからデータベースにつながらない

先日、Laravel Sailについて質問を受けた内容です。

PhpMyAdminを使いたいということで、自身で調べてdocker-composeにサービスの追加をしたけど、動かないということでした。

Sail を起動して、ブラウザでPhpMyAdminにログインしようとすると、エラーになってしまいます。

ログインの時点でエラー

とりあえずMySQLの疎通確認から。

Laravelコンテナからマイグレーションの実行はできているので、MySQLコンテナ自体はちゃんと動いているようです。

$ sail artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (553.47ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (767.61ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (589.25ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (380.02ms)

コンテナ起動時にも、ちゃんとphpmyadminコンテナが起動してます。

$ sail up -d
Creating network "laraveltest_phpmyadmin_sail" with driver "bridge"
Creating laraveltest_phpmyadmin_mailhog_1     ... done
Creating laraveltest_phpmyadmin_redis_1       ... done
Creating laraveltest_phpmyadmin_mysql_1       ... done
Creating laraveltest_phpmyadmin_selenium_1    ... done
Creating laraveltest_phpmyadmin_meilisearch_1 ... done
Creating laraveltest_phpmyadmin_phpmyadmin_1   ... done
Creating laraveltest_phpmyadmin_laravel.test_1 ... done

$ sail ps
                Name                               Command                  State                           Ports
--------------------------------------------------------------------------------------------------------------------------------------
laraveltest_phpmyadmin_laravel.test_1   start-container                  Up             0.0.0.0:80->80/tcp, 8000/tcp
laraveltest_phpmyadmin_mailhog_1        MailHog                          Up             0.0.0.0:1025->1025/tcp, 0.0.0.0:8025->8025/tcp
laraveltest_phpmyadmin_meilisearch_1    tini -- /bin/sh -c ./meili ...   Up (healthy)   0.0.0.0:7700->7700/tcp
laraveltest_phpmyadmin_mysql_1          /entrypoint.sh mysqld            Up (healthy)   0.0.0.0:3306->3306/tcp, 33060/tcp, 33061/tcp
laraveltest_phpmyadmin_phpmyadmin_1     /docker-entrypoint.sh apac ...   Up             0.0.0.0:8080->80/tcp
laraveltest_phpmyadmin_redis_1          docker-entrypoint.sh redis ...   Up (healthy)   0.0.0.0:6379->6379/tcp
laraveltest_phpmyadmin_selenium_1       /opt/bin/entry_point.sh          Up             4444/tcp, 5900/tcp

Laravel本体のコンテナとMySQLのコンテナは疎通してて、PhpMyAdminからだとつながってないような状況なので、コンテナ内でなんか起こってるのかなと目星をつけました。

ご質問者さんに了解を取ったうえで、ボリュームを削除して作り直してみます。

sail down --volumes --remove-orphans
Stopping laraveltest_phpmyadmin_laravel.test_1 ... done
Stopping laraveltest_phpmyadmin_phpmyadmin_1   ... done
Stopping laraveltest_phpmyadmin_meilisearch_1  ... done
Stopping laraveltest_phpmyadmin_selenium_1     ... done
Stopping laraveltest_phpmyadmin_mysql_1        ... done
Stopping laraveltest_phpmyadmin_redis_1        ... done
Stopping laraveltest_phpmyadmin_mailhog_1      ... done
Removing laraveltest_phpmyadmin_laravel.test_1 ... done
Removing laraveltest_phpmyadmin_phpmyadmin_1   ... done
Removing laraveltest_phpmyadmin_meilisearch_1  ... done
Removing laraveltest_phpmyadmin_selenium_1     ... done
Removing laraveltest_phpmyadmin_mysql_1        ... done
Removing laraveltest_phpmyadmin_redis_1        ... done
Removing laraveltest_phpmyadmin_mailhog_1      ... done
Removing network laraveltest_phpmyadmin_sail
Removing volume laraveltest_phpmyadmin_sail-mysql
Removing volume laraveltest_phpmyadmin_sail-redis
Removing volume laraveltest_phpmyadmin_sail-meilisearch

これで直りました。どういう事象でエラーだったのかわからないけど。。。

ボリュームを消しちゃったので、MySQLも空っぽになっています。

このあと、マイグレーション・シーディングをし直してもらいました。

以上です。あなたのお役に立てれば幸いです。

Laravel Sail でコンテナのshellを使う

こんばんは、ウチイダです。

Laravel Sail便利ですよね。docker-compose のラッパーみたいなものなので、学習コストも低くてとても良い感じです。

docker-composeでできることは何でもできるので、困ったらdocker-composeのコマンドを調べるのですが、なかなか覚えられません。

ちょくちょく使うのが、コンテナに入るコマンドです。

# Laravelアプリケーションのコンテナのbashを開く
$ docker-compose exec laravel.test bash

dockerコマンドみたいに、-it とかオプション付けなくてもいいので、まだいいですが、長いですよね。

あるときふとReadoubleを見直してみたら、sail コマンドからコンテナ接続するサブコマンドがちゃんと用意されていました。

# sail コマンドから、Laravel アプリケーソンのコンテナのbashをひらく
$ sail shell

# root ユーザーで接続する場合
$ sail root-shell

# Readoubleにはないけど、以下でもOK
$ sail bash

すごく短くなります。

sailコマンドの中身(vendor/bin/bash)は難しくないshellスクリプトなので、中身を見てみるといろいろ発見があって面白いです。

以上です。あなたのお役に立てれば幸いです。