A while ago, I learned about Symfony's local web server when I bumped into Fabien Potencier's slides from SymfonyCon Lisbon. I previously used docker for local development but that didn't always go smoothly, especially in larger projects it tends to get rather slow.
Going through the slides, I was rather excited to try it out and to my surprise - it was a breeze to set up on macOS!
So far, I've been using it with projects using Symfony and old non-framework projects.
Download the Symfony client
To get started, go download and install the symfony client. For convenience, here's the command:
curl -sS https://get.symfony.com/cli/installer | bash
Once installed, you should be able to run
symfony in the command line.
Getting the correct PHP version
The Symfony client is able to discover which PHP versions you have installed. To get a list of installed versions, run
symfony local:php:list and you'll get an output similar to the following:
┌─────────┬──────────────────────────────────┬─────────┬──────────────┬─────────────┬─────────┐ │ Version │ Directory │ PHP CLI │ PHP FPM │ PHP CGI │ Server │ ├─────────┼──────────────────────────────────┼─────────┼──────────────┼─────────────┼─────────┤ │ 5.6.40 │ /usr/local/Cellarfirstname.lastname@example.org/5.6.40 │ bin/php │ sbin/php-fpm │ bin/php-cgi │ PHP FPM │ │ 7.1.23 │ /usr │ bin/php │ sbin/php-fpm │ │ PHP FPM │ │ 7.1.28 │ /usr/local/Cellaremail@example.com/7.1.28 │ bin/php │ sbin/php-fpm │ bin/php-cgi │ PHP FPM │ │ 7.2.15 │ /usr/local/Cellarfirstname.lastname@example.org/7.2.15 │ bin/php │ sbin/php-fpm │ bin/php-cgi │ PHP FPM │ └─────────┴──────────────────────────────────┴─────────┴──────────────┴─────────────┴─────────┘
If I recall correctly, macOS ships with PHP pre-installed, for additional versions, I suggest you take a look at Homebrew.
For completeness, let's install the latest PHP version with Homebrew:
brew install email@example.com
PHP 7.3 should now be included in the list when running
Running the local server
To run the local server,
cd into your project root and run
symfony server:start - your output should look similar to the following:
↳ symfony server:start May 9 22:01:04 |INFO | PHP listening path="/usr/local/sbin/php-fpm" php="7.3.3" port=60205 May 9 22:01:04 |DEBUG| PHP started May 9 22:01:04 |INFO | PHP 'user' directive is ignored when FPM is not running as root May 9 22:01:04 |INFO | PHP 'group' directive is ignored when FPM is not running as root May 9 22:01:04 |INFO | PHP fpm is running, pid 93955 May 9 22:01:04 |INFO | PHP ready to handle connections [OK] Web server listening on http://127.0.0.1:8000 (PHP FPM 7.3.3) WARNING unable to find the application log
Note: You might see the message
WARNING unable to find the application log here, the reason is because the
var/log/dev.log does not yet exist. To make the message go away, either create the file yourself or wait for symfony to log something to it.
You'll now be able to access your project on http://127.0.0.1:8000, it will run on PHP7.3 that we've installed earlier.
The Symfony client will always pick the highest PHP version, so you'll always want to assign a specific version to your project. To do this, you create a new file in the root of your project called
.php-version with the contents being the PHP version your project requires.
Let's try with PHP 7.2, install it with brew
brew install firstname.lastname@example.org and create the
.php-version file with
7.2 as its content:
echo "7.2" > .php-version
symfony server:start and you can see it's now using PHP 7.2.15
↳ symfony server:start May 9 22:09:31 |INFO | PHP listening path="/usr/local/Cellaremail@example.com/7.2.15/sbin/php-fpm" php="7.2.15" port=62298 May 9 22:09:31 |DEBUG| PHP started May 9 22:09:31 |INFO | PHP 'user' directive is ignored when FPM is not running as root May 9 22:09:31 |INFO | PHP 'group' directive is ignored when FPM is not running as root May 9 22:09:31 |INFO | PHP fpm is running, pid 97778 May 9 22:09:31 |INFO | PHP ready to handle connections [OK] Web server listening on http://127.0.0.1:8000 (PHP FPM 7.2.15) WARNING unable to find the application log
-d option, you can run the server as a daemon - pretty handy when you don't want multiple terminal tabs/windows running.
↳ symfony server:start -d [OK] Web server listening on http://127.0.0.1:8000 (PHP FPM 7.2.15) Stream the logs via symfony server:log.
You can always pull out the logs with symfony server:log
↳ symfony server:log May 9 22:14:45 |INFO | PHP listening path="/usr/local/Cellarfirstname.lastname@example.org/7.2.15/sbin/php-fpm" php="7.2.15" port=63583 May 9 22:14:45 |DEBUG| PHP started May 9 22:14:45 |INFO | PHP 'user' directive is ignored when FPM is not running as root May 9 22:14:45 |INFO | PHP 'group' directive is ignored when FPM is not running as root May 9 22:14:45 |INFO | PHP fpm is running, pid 344 May 9 22:14:45 |INFO | PHP ready to handle connections
And view which servers are running with symfony server:list.
↳ symfony server:list ┌────────────────────────┬────────┬─────────────────────────────────────────────────────────┐ │ URL │ Domain │ Directory │ ├────────────────────────┼────────┼─────────────────────────────────────────────────────────┤ │ http://127.0.0.1:8000 │ │ /Users/kevinvandenborne/Development/symfony-server-test │ └────────────────────────┴────────┴─────────────────────────────────────────────────────────┘
The Symfony client comes with various wrappers that take into account the PHP version defined for your project (`.php-version`).
↳ symfony help ... Available wrappers: Runs PHP (version depends on project's configuration). Environment variables to use SymfonyCloud relationships or Docker services are automatically defined. composer Runs Composer without memory limit console Runs the Symfony Console (bin/console) for current project php, pecl, pear, php-fpm, php-cgi, php-config Runs the named binary using the configured PHP version
You'll often (or always) want to use or test with
https://, the Symfony client has you covered with
symfony server:ca:install. When you restart your server, both
https:// are available.
↳ symfony server:stop Stopping web server [OK] Stopped 1 process(es) successfully ↳ symfony server:start -d [OK] Web server listening on https://127.0.0.1:8000 (PHP FPM 7.2.15) Stream the logs via symfony server:log.
Local domain names
Having https://127.0.0.1:8000 as your project address may become confusing and tedious to type, especially when you have many projects running. For this, the Symfony client also has you covered with its built-in proxy.
↳ symfony proxy:start [OK] Proxy server listening on http://127.0.0.1:7080
You'll have to configure this proxy in your network preferences. On macOS, open network preferences and go to "Advanced.." (make sure you press the lock icon to make changes). Then, click on the "Proxies" tab.
In the proxies tab, check "Automatic Proxy Configuration" and enter the url that was outputted when you started the proxy appended with
proxy.pac, in this case,
All that is left now is attaching a domain to our project, this can be done with the
↳ symfony proxy:domain:attach symfony-server-test.com The proxy is now configured with the following domains for this directory: * http://symfony-server-test.com.wip ↳ symfony server:start -d Stream the logs via symfony server:log. [OK] Web server listening on https://127.0.0.1:8000 (PHP FPM 7.2.15) https://symfony-server-test.com.wip
You should now be able to access your project using the domain you've attached, in my case that's https://symfony-server-test.com.wip
Note: You may have to restart your browser for the proxy changes to take effect!
You can configure the proxy by editing the
~/.symfony/proxy.json file. There's also a handy list available on http://127.0.0.1:7080/
You're all set now, enjoy your local development set with custom domain names and TLS, all thanks to Symfony!
For special project requirements such as elasticsearch/redis/.. I personally still use docker containers, saves me from installing all that stuff locally and isolates it from the rest of my projects. I run MySQL locally unless the production server runs another flavor of is (such as MariaDB), then I also use docker for that as there can be slight changes. Ideally, you have a staging/testing server that is identical to the production server.