Remote Databases

If you have more than one Laravel codebase in your project, you might have issues when building databases and running your tests.

This might be because only one of the codebases knows how to build the database. Or perhaps multiple codebases interact with each other, and should all access the same database.

There are various reasons why you might have multiple codebases. For example:

Building Databases Remotely

Adapt can build databases for other instances of Adapt.

This will be useful if you're running tests from one Laravel codebase, but the migrations and seeders to build the database exist in another.

  • Install Adapt into both codebases.
  • In the codebase that runs the tests, set the remote_build_url config setting. Or you can specify it per-test by adding the $remoteBuildUrl property to your test-classes. The url just needs to point to somewhere within the other codebase's routing.
  • When each test runs, Adapt sends an http request to the remote instance. Adapt on the other side picks up the request automatically.
  • The remote instance then builds the database (for its connection with the same name).
  • It returns the details back to the first codebase, which then uses the database and continues the test, like normal.

If a database built like this can be reused, Adapt will skip the http request next time and just re-use it straight away.

⚙️ See configuration
# .env.testing

ADAPT_REMOTE_BUILD_URL=https://…

or

<?php
// config/code_distortion.adapt.php

return ['remote_build_url' => env('ADAPT_REMOTE_BUILD_URL', 'https://…'), // or null];





 


or

<?php
// tests/Feature/MyFeatureTest.php

use CodeDistortion\Adapt\AdaptDatabase;
use Tests\TestCase;

class MyFeatureTest extends TestCase
{
    use AdaptDatabase;

    protected ?string $remoteBuildUrl = 'https://…'; // or null}










 



These are the settings that are passed from your tests to the remote instance:

  • config project_name
  • config build_sources.initial_imports, or test-class property $initialImports
  • config build_sources.migrations, or test-class property $migrations
  • config build_sources.seeders, or test-class property $seeders
  • test-class property $isBrowserTest, or when a browser test is automatically detected
  • config reuse_methods.transactions, or test-class property $transactions
  • config reuse_methods.journals, or test-class property $journals
  • config reuse_methods.snapshots, or test-class property $snapshots
  • config scenarios
  • config verify_databases

NOTE

It's best to have the same version of Adapt installed in both places. Adapt will throw an exception if the versions aren't compatible.

It's also best to have the same database connections set up in each config/database.php file.

TIP

Multiple databases can be built for a test using this method. Just use the ->remoteBuildUrl('https://…') method when building extra databases.

Sharing Databases Remotely

Adapt can share databases that have been prepared (locally, or remotely as above) with other Laravel codebases.

If your project makes http requests to a second local Laravel project (e.g. when calling an API), you'd probably want it to connect a database that was prepared for the test.

Adapt gives you a header to add to these requests, which contains details about the database.

If more than one database is built for a test, they'll all be included inside the same header.

  • Install Adapt into both codebases.
  • Add the header to your http requests (example below).
  • When receiving the request, Adapt on the other side will automatically detect these headers. It then swaps to the "testing" environment, and uses the test database/s for the duration of the request.
<?php
// somewhere.php

use CodeDistortion\Adapt\AdaptDatabase;

$adaptHeaders = trait_exists(AdaptDatabase::class)
    ? AdaptDatabase::getShareConnectionsHeaders()
    : [];

// [
//   'adapt-remote-share' => 'eyJkdG9WZXJzaW9uIjo2LCJzaGFyYWJsZUNvbmZpZ1BhdGgiOm51bGwsImNvbm5lY3Rpb25EQnMiOnsibXlzcWwiOiJkYl9mZjYzNGJfNzZmYmZhZjE1OTU1In19',
// ]

$response = Http::withOptions(['headers' => $adaptHeaders])->post($url, $data);

NOTE

Checking first that the AdaptDatabase trait exists (see above) means that the code won't break in non-local or testing environments (where Adapt wouldn't be installed).

If you'd like the header key to be included in the value, pass true to AdaptDatabase::getShareConnectionsHeaders(true):

<?php
// somewhere.php

use CodeDistortion\Adapt\AdaptDatabase;

$adaptHeaders = trait_exists(AdaptDatabase::class)
    ? AdaptDatabase::getShareConnectionsHeaders(true)
    : [];

// [
//   'adapt-remote-share' => 'adapt-remote-share: eyJkdG9WZXJzaW9uIjo2LCJzaGFyYWJsZUNvbmZpZ1BhdGgiOm51bGwsImNvbm5lY3Rpb25EQnMiOnsibXlzcWwiOiJkYl9mZjYzNGJfNzZmYmZhZjE1OTU1In19',
// ]

NOTE

It's best to have the same version of Adapt installed in both places. Adapt will throw an exception if the versions aren't compatible.

It's also best to have the same database connections set up in each config/database.php file.

WARNING

You will most likely want to turn transaction-reuse off when sharing databases like this, as any changes you make from one connection won't be seen by the other.

You can turn this off by updating Adapt's reuse_methods.transactions config setting, or by adding the $transactions property to your test-classes.