Running OroCommerce with PHP -s Built-in Server
Guide of running OroCommerce without the overhead of a traditional web server stack. Using the built-in PHP server is a “lean” developer’s dream, provided you handle the routing correctly.
Below is your article, polished for readability with enhanced formatting and clear visual separation for the technical steps.
How to start OroCommerce locally without Nginx, Apache, or the Symfony CLI — just php -S. This approach is ideal for local development, E2E testing, and CI environments where a full web server is unnecessary overhead.
The One-Line Mistake Everyone Makes
If you use the standard PHP server command pointing directly to index.php, every .js, .css, and image request will be treated as a PHP script. Because OroCommerce's compiled bundles are complex, PHP tries to execute them and fails.
# WRONG — every .js/.css request goes through PHP
php -S 0.0.0.0:8000 -t public/ public/index.php
# RIGHT - static files served directly, PHP only for app routes
php -S 0.0.0.0:8000 -t public/ router.phpWhy it breaks
When using the wrong router, you’ll see errors like:
Fatal error: Uncaught TypeError: Invalid return value... from "/public/build/app.js"
The result is a “Ghost Load”: the HTML structure appears, but the Oro AMD/RequireJS module system never boots, leaving you stuck on a “Loading…” screen forever.
How router.php Works
OroCommerce ships with a router.php in the project root. This script acts as a traffic cop:
<?php
$requestUri = $_SERVER['REQUEST_URI'];
$path = parse_url($requestUri, PHP_URL_PATH);
$file = __DIR__ . '/public' . $path;
// 1. If the file exists on disk (css, js, images), serve it as-is.
if ($path !== '/' && file_exists($file) && !is_dir($file)) {
return false;
}
// 2. Otherwise, forward the request to Symfony's front controller.
require __DIR__ . '/public/index.php';return false tells the built-in server: "I'm not handling this; serve the physical file directly."
1. Configure the EnviroVerifying Health
Use these quick terminal commands to ensure everything is routed correctly:
- Smoke Test:
curl -I http://localhost:8000/(Should return200 OK) - Static Asset Test:
curl -I http://localhost:8000/build//app.js - Success:
200 OK - Failure:
500 Internal Server Error(You are likely usingindex.phpas the router instead ofrouter.php).
Requred PHP Extensions
OroCommerce is demanding. Ensure you have the following installed:
bcmath, curl, gd, intl, mbstring, opcache, pdo_pgsql, soap, xml, zip.
Performance Optimization
The built-in server is single-threaded. To make it snappier for local dev, create a php-local.ini and increase the memory limit and realpath cache:
memory_limit = 2048M
realpath_cache_size = 4096K
realpath_cache_ttl = 600
opcache.enable = 1Start the server with this config:
php -c php-local.ini -S 0.0.0.0:8000 -t public/ router.phpFix single threaded server:
You can tell the PHP server to spawn multiple “worker” processes. This allows the server to handle multiple concurrent requests (e.g., loading the HTML while simultaneously fetching JS and CSS assets).
Command:
# Set 4 workers and start the server
PHP_CLI_SERVER_WORKERS=4 php -S 0.0.0.0:8000 -t public/ router.phpWhy skip the Symfony CLI?
While symfony serve is excellent, it adds an 3d party external dependency to your toolchain. Using php -S with router.php relies strictly on what is already in the project repository and your PHP installation, making it more portable for CI/CD pipelines and simplified onboarding.
