Skip to content

Make the database adapter available inside shouldExecute()#1100

Merged
markstory merged 1 commit into
5.xfrom
issue-1099-adapter-in-shouldexecute
Jul 9, 2026
Merged

Make the database adapter available inside shouldExecute()#1100
markstory merged 1 commit into
5.xfrom
issue-1099-adapter-in-shouldexecute

Conversation

@dereuromark

Copy link
Copy Markdown
Member

Fixes #1099.

shouldExecute() could not use the database to decide eligibility. The adapter
is only set on the migration/seed by Environment::executeMigration() /
executeSeed(), immediately before the migration body runs - which is after
the shouldExecute() gate in Manager. So any getAdapter() / execute() /
query() / hasTable() call inside shouldExecute() threw
RuntimeException: Adapter not set., limiting eligibility checks to local
application state only.

Change

Manager::executeMigration() and Manager::executeSeed() now attach the
environment's adapter to the migration/seed before the shouldExecute() check:

$migration->setAdapter($this->getEnvironment()->getAdapter());

Environment::getAdapter() memoizes its adapter, so this adds no extra
connection. Environment::executeMigration() still sets and (for down /
change) wraps the adapter before running the body, so migrate/rollback
behavior is unchanged - shouldExecute() simply gains a read-capable adapter.

This keeps the adapter lazy and Environment-owned, rather than moving
setAdapter() to migration construction time (which has no direction/environment
context and would fight the record-adapter wrapping used for reversible
migrations).

Tests

Added testMigrationShouldExecuteCanQueryDatabase, backed by a new
ShouldExecuteWithDb fixture whose shouldExecute() calls
$this->getAdapter()->hasTable(...). It errors with Adapter not set. without
the fix and passes with it.

Docs

Documented that the adapter is available inside shouldExecute(), with an
example.

The adapter was only set on the migration/seed by the Environment, right
before running the migration body - after the shouldExecute() gate in the
Manager. As a result shouldExecute() could not query the database (calling
getAdapter() threw "Adapter not set."), so eligibility could only depend on
local application state, not the state of the database.

Set the environment's adapter on the migration and seed before the
shouldExecute() check. getEnvironment()->getAdapter() is memoized, so this
adds no extra connection, and the Environment still (re)sets and wraps the
adapter before executing the body, leaving migrate/rollback behavior
unchanged.
@dereuromark dereuromark requested a review from markstory July 8, 2026 17:49

@markstory markstory left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable to me. We can't remove the existing setAdapter() calls as they are load-bearing because of Environment::executeMigration().

@markstory markstory merged commit f08f5bc into 5.x Jul 9, 2026
20 checks passed
@markstory markstory deleted the issue-1099-adapter-in-shouldexecute branch July 9, 2026 03:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DB connection not available to shouldExecute().

2 participants