survos/bedrock

Makes a Roots Bedrock WordPress site work under the Symfony CLI local server: directory index, DB_PORT folding, and a shared installer.

Maintainers

Package info

github.com/survos/bedrock

pkg:composer/survos/bedrock

Transparency log

Fund package maintenance!

kbond

Statistics

Installs: 12

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

2.24.38 2026-08-27 11:23 UTC

This package is auto-updated.

Last update: 2026-08-27 11:26:26 UTC


README

Makes a Roots Bedrock WordPress site work under the Symfony CLI local server, so a WordPress site can be developed the same way as every other project in this tree — symfony server:start, a .wip domain through the proxy, host PHP.

None of what this fixes is a Bedrock problem. Bedrock is fine under Apache, nginx, Valet, DDEV and Trellis. These are all consequences of serving WordPress with a server built for single-front-controller applications, which WordPress is not: its front end is web/index.php, but its admin is a tree of real PHP files behind a directory index.

Install

composer require survos/bedrock

web/index.php

<?php

require dirname(__DIR__) . '/vendor/autoload.php';

if ($index = Survos\Bedrock\LocalServer::directoryIndex(__DIR__)) {
    require $index;

    return;
}

define('WP_USE_THEMES', true);
require __DIR__ . '/wp/wp-blog-header.php';

Composer's autoloader is idempotent, so wp-config.php requiring it again is a no-op.

The require must stay at global scope. WordPress's admin files set globals — $title, $parent_file, $submenu_file — and requiring one inside a method would make those function-local and break the admin in ways that are tedious to trace. That is why directoryIndex() returns a path instead of including it.

config/application.php

Config::define('DB_HOST', Survos\Bedrock\Env::dbHost(env('DB_HOST'), env('DB_PORT')));

bin/install.sh

source vendor/survos/bedrock/bin/bedrock.sh
bedrock::boot
bedrock::require_db
bedrock::install_core

wp rewrite structure '/%postname%/'
# ... and whatever else this particular site needs

Sourced rather than executed, so install.sh stays the readable record of how that site is configured.

What each piece is for

LocalServer::directoryIndex() — Roots' documented nginx config for Bedrock is try_files $uri $uri/ /index.php?$args. symfony server:start --passthru=index.php implements $uri and the /index.php fallback but not $uri/, so every URL ending in a slash reaches WordPress's front controller and /wp/wp-admin/ renders the home page with a 200. Inert under Apache and nginx, which resolve the directory first.

Env::dbHost()symfony server:start detects the Docker Compose services of the project it runs from and injects their connection details prefixed with the service name: a service called db yields DB_HOST, DB_PORT, DB_USER, DB_NAME, DB_PASSWORD. Bedrock's dotenv repository is immutable, so those override .env — and WordPress has no DB_PORT, it wants host:port in DB_HOST. The published port is silently dropped and WordPress dials 3306. Symptom: mysqli_real_connect(): (HY000/2002): Connection refused on web requests while wp-cli connects fine, the CLI getting no injection.

Inert when the database lives outside the project, which is the better arrangement anyway — with no project Compose service there is nothing to inject at all.

bin/bedrock.sh — the parts of an installer every site shares. bedrock::require_db checks reachability through mysqli rather than wp db check, which shells out to a mysqlcheck binary that need not be installed.

Gotcha

The Symfony server passes the environment to php-fpm when it starts. After changing .env — or after moving the database — a running server keeps serving the old values, and the site 500s with Access denied for user ... while wp-cli works fine. Restart it:

symfony server:stop && symfony server:start -d