Fabien Potencier
May 02, 2017
Time to test Symfony 4… or at least let’s test the experience of developing Symfony 4 projects with Symfony 3.3. Keep in mind that all the tools are in preview mode. Features might evolve over time. I’m waiting for your feedback! The first stable version of Symfony Flex will not be released before Symfony 4 at the end of November 2017. It gives the community plenty of time to discuss the changes I have described in this series of blog posts.
Creating a new Project
The first step is to create a project. Currently, this needs to be done via composer create-project
. We might release a tool to bootstrap a project faster.
Let’s go:
composer create-project "symfony/skeleton:^3.3" demo
cd demo
3.3
is the only currently available version and uses the yet-to-be-released Symfony 3.3. Versions like , 4.0
, lts
, or latest
will be available later on (but not before the release of Symfony 4.0 of course).
The command downloads the Symfony skeleton which consists of just onecomposer.json
file.
Then, it extracts the file into the demo
directory and automatically runs composer install
. symfony/flex
is the first package to be installed so that it can hook into the Composer process. When Composer installs (or updates) other dependencies, Symfony Flex looks for an associated recipe on the Symfony Flex server, and executes it. You can see Symfony Flex in action via the logs it adds to the Composer output.
When finished, you should see a “What’s next?” section that explains the possible next steps, like running make serve
to start the PHP built-in web server. Before going further, go to the project’s directory: cd demo
.
serve
is one of the tasks added to the local Makefile
, as described in thesymfony/framework-bundle
recipe.
Note that some commands were automatically installed and run at the end of the process:
Again, those scripts were added to the project’s composer.json
file as defined by the symfony/framework-bundle
recipe. The second script did not run because the console tool (available via symfony/console
) is not installed by default (we will see how to “fix” this issue later on).
Now is a good time to initialize Git:
git init
git add .
git commit -m "initial set of files"
Using git add .
works well as Symfony took care of creating a “good” .gitignore
file.
Remember that the skeleton only has one file, composer.json
. Check the demo/
directory now; some more files have been created. Those files were added by Symfony Flex based on the installed packages, as described in recipes.
Let’s examine the directory structure now. Most files has been added because of the symfony/framework-bundle
dependency.
The .env
file defines the APP_ENV
and APP_DEBUG
environment variables:
###> symfony/framework-bundle ###
APP_ENV=dev
APP_DEBUG=1
APP_SECRET=ODtvoHW6pn3bE2rHgTa2MjkjwefzlsJH
###< symfony/framework-bundle ###
The comments allows Symfony Flex to “manage” this section. This is useful when those variables needs to be removed when the package is removed. If you remove the comments, Symfony Flex will not be able to automatically manage these variables anymore. Have a look at .gitignore
for a similar example.
If you’re curious, check public/index.php
, the new web front controller.
The most interesting files are under config/
. The main entry points are the empty container.yaml
and routing.yaml
files; this is where you can add services, parameters, and routes for your project. A default configuration has been installed as well for symfony/framework-bundle
under config/packages/
. Feel free to tweak installed configuration files or add more for your own needs.
Last, but not least, FrameworkBundle
is now registered in bundles.php
:
return [
'Symfony\Bundle\FrameworkBundle\FrameworkBundle' => ['all' => true],
];
Even if a bundle does not have a recipe, Symfony detects Composer packages with the symfony-bundle
type and automatically enable them for all environments. This avoids the creation of recipes when registration is just a matter of enabling the bundle.
The src/
directory is where you can store your PHP classes. Under the App\
namespace as registered in composer.json
. Note that this is where Kernel.php
was also installed as App\Kernel
.
Now, it is time to install some new dependencies via Composer. Let’s start by adding a more powerful web server for your project:
composer req webserver
And install Symfony console support via:
composer req cli
Note: req
is a shortcut for require
(the Composer CLI supports any shortcut that is not ambiguous; use rem
to remove a Package).
webserver
is an alias for symfony/web-server-bundle
, and cli
is an alias for symfony/console
. That works because Symfony Flex knows how to convert those aliases into full package names: cli
is equivalent to console
, which is equivalent to symfony/console
. The symfony/
prefix is always optional. Try composer req workflow
or composer req ldap
. web-server-bundle
is too cumbersome, so use webserver
or just server
.
For Symfony dependencies, Symfony Flex also recognizes a few more versions than the usual Composer ones, mainly next
, previous
, lts
, and stable
(they don’t all work yet though).
composer req cli:next
After executing composer req cli
, notice how the assets:install
command automatically ran. The bin/console
file has also been added to your project.
Aliases work when removing dependency as well:
composer rem cli
… which also removes the bin/console
binary (for fun, try this: composer rem framework-bundle
).
Remember I wrote about the developer experience when installing a Symfony bundle? Let’s go wild and install something really “complex” like an admin generator based on Doctrine. How many steps to make it work? It might be fewer than you expect, and definitely more fun.
First, let’s install EasyAdminBundle:
composer req admin
Besides installing the admin generator bundle, it also installs all its transitive dependencies and auto-configures them all: TwigBundle
, SecurityBundle
, FrameworkExtraBundle
, and DoctrineBundle
.
admin
is a “generic” word. This is why I wrote about Symfony Flex recipes being opinionated. There can only be one package aliased to admin
. orm
is another generic word that is currently aliased to the Doctrine ORM.
Run the PHP built-in web-server via make serve
or bin/console server:start
and go to http://localhost:8000/admin/
. You should get an error as no Doctrine entities exist yet. Let’s create one in src/Entity/Product.php
:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="product")
*/
class Product
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @ORM\Column(type="string", length=100)
*/
public $name;
/**
* @ORM\Column(type="decimal", scale=2)
*/
public $price;
/**
* @ORM\Column(type="text")
*/
public $description;
}
Tweak the database configuration in .env
:
###> doctrine/doctrine-bundle ###
DB_URL=mysql://root@127.0.0.1:3306/symfony?charset=utf8mb4
###< doctrine/doctrine-bundle ###
Run the following commands to initialize the database:
./bin/console doctrine:database:create
./bin/console doctrine:schema:update --force
Finally, add the Product
entity to the list of entities managed by the admin generator (config/packages/easy_admin.yaml
):
easy_admin:
entities:
- App\Entity\Product
Try http://localhost:8000/admin/
again. If everything worked well, you should be able to manage products.
Instead of installing an admin generator, have a look at this small screencast where I’m using the api
alias to bootstrap an API project quickly and easily:
Here are some nice aliases you can try:
sec-checker
to install the SensioLabs Security Checker;req-checker
to install the Symfony requirements checks;log
to install MonologBundle and all its dependencies;template
for Twig;mailer
for Swiftmailer;profiler
for the profiler;- … you get the point 🙂
As symfony/symfony
is not required anymore, you get more fine-grained dependencies, but it might be cumbersome to install each Symfony component one by one. To ease the pain, I’m experimenting with a new concept: “packs”. A pack is nothing more than a regular Git repository registered on Composer that contains a composer.json
that references a set of related packages. As an example, I have created a debug-pack
pack that can be installed via composer req debug-pack
. Have a look at the ORM pack or the API pack. Imagine a web-pack
that references nothing in composer.json
but is associated with a recipe that installs a set of default files under public/
like favicons, a robots.txt
, and so on. Nice? Imagine the same for Travis, Blackfire, or Docker. Or a pack that installs the exact same dependencies as the current Symfony Standard Edition? Your imagination is the limit. Compose your applications with off-the-shelf packages, packs, and their associated recipes.
Symfony Flex enables distribution composition instead of inheritance. The new way is easier, more flexible, and more powerful at the same time.
The first version of the Symfony Flex server is quite simple, but over time, more features will be implemented.
Now, it is probably time for you to write some code. What about some controllers and templates? Hold on. Even if you can do what you are used to, Symfony 3.3 and Symfony 4.0 proposes a much smoother experience that you might like better. This is a great topic for my next post about Symfony 4.
Remember that the recipes repositories at https://github.com/symfony/recipes andhttps://github.com/symfony/recipes-contrib are also public now. Feel free to look around. And keep in mind that what you see is experimental. Current choices might change.