3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Laravel9 + Postgres + Heroku Connect のプロジェクトでスキーマの指定を省略する

Last updated at Posted at 2022-04-26

概要

Salesforce と連携したアプリケーションの開発をする際に、便利な設定を見つけたので記事にしました。
Salesforce のデータを Heroku Connect によって Heroku Postgres とデータ同期をすると salesforce というスキーマが作成されます。
今までは Eloquent モデルにテーブル名を指定する際に、下記のようにスキーマ名を入れていましたが、これを省略する方法を紹介します。

App/Models/SalesforceTest.php
use Illuminate\Database\Eloquent\Model;
class SalesforceTest extends Model {
  protected $table = 'salesforce.test__c';
}

環境

  • Laravel 9
  • Heroku Postgres
  • Heroku Connect

結論

こちらの Heroku Connect のドキュメントにスキーマ名を省略する方法が載っていますが、別途SQLを発行する必要があります。

SET search_path TO salesforce,public;

この記事では Laravel の設定で上記と同じ状態にします。
結論から言いますと Laravel プロジェクトの設定ファイルの config/database.php 内にある search_path もしくは schema の項目に salesforce を追加すると完成です。

config/database.php
'connections' => [
  'pgsql' => [
    'driver' => 'pgsql',
    'url' => env('DATABASE_URL'),
    'host' => env('DB_HOST', '127.0.0.1'),
    'port' => env('DB_PORT', '5432'),
    'database' => env('DB_DATABASE', 'forge'),
    'username' => env('DB_USERNAME', 'forge'),
    'password' => env('DB_PASSWORD', ''),
    'charset' => 'utf8',
    'prefix' => '',
    'prefix_indexes' => true,
-   'search_path' => 'public',
+   'search_path' => ['public', 'salesforce'],
    'sslmode' => 'prefer',
  ]
]

解説

ここからは Laravel 内での挙動を解説します。
Laravel が Postgres の DB にSQLを発行する際に vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.phpconfigureSearchPath 関数が実行されます。

vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.php
/**
 * Set the "search_path" on the database connection.
 *
 * @param  \PDO  $connection
 * @param  array  $config
 * @return void
 */
protected function configureSearchPath($connection, $config)
{
  if (isset($config['search_path']) || isset($config['schema'])) {
    $searchPath = $this->quoteSearchPath(
      $this->parseSearchPath($config['search_path'] ?? $config['schema'])
    );  
    $connection->prepare("set search_path to {$searchPath}")->execute();
  }
}

この $config には config/database.phppgsql の内容が入っています。
search_path がなければ schema が参照されるようになっているため、両方設定されている場合は search_path が優先されます。
また quoteSearchPath 関数と parseSearchPath 関数によって整形されるため、配列とカンマ区切りの設定に対応しています。

  • 'search_path' => ['public', 'salesforce']
  • 'search_path' => 'public, salesforce'

$connection->prepare("set search_path to {$searchPath}")->execute(); により search_path が設定されます。

最後に

もし環境ごとにスキーマ名が変わる場合は、環境変数で制御するようにできます。

.env
DB_SCHEMA=stgpublic
DB_SCHEMA_SALESFORCE=stgsalesforce
config/database.php
'connections' => [
  'pgsql' => [
    'search_path' => [env('DB_SCHEMA', 'public'), env('DB_SCHEMA_SALESFORCE', 'salesforce')],
  ]
]

同じ悩みを抱えている方の助けになれば嬉しいです。
私がコードを読んで解釈した内容ですので、もし間違っている箇所がありましたらご指摘いただけますと幸いです。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?