Directory Structure

The previous page listed the top-level folders — config/, src/, templates/, public/, and var/. Here we go one level deeper into src/ and config/ and look at why Symfony organizes things this way, not just what the folders are called.

Inside src/: Controller, Entity, Repository

A default Symfony project splits your application code into three folders under src/ that work together on every database-backed page:

FolderRole
src/Entity/Plain PHP classes that model one row of a database table — an Article entity models one article
src/Repository/The query layer for one Entity — fetching, filtering, and searching Article rows lives in ArticleRepository
src/Controller/Handles incoming requests and orchestrates the response — it asks a Repository for data, then hands it to a template

In practice the flow is: a request hits a Controller, the Controller asks a Repository for the Entities it needs, and the Repository returns Entity objects built from database rows. Each layer has exactly one job.

config/packages/ and config/services.yaml

config/packages/ holds one configuration file per installed bundle — for example config/packages/twig.yaml configures the Twig bundle, and config/packages/doctrine.yaml configures Doctrine. Symfony Flex is what creates most of these files automatically when you install a package, as covered on the previous page.

config/services.yaml is different: it's where your own services and any manual container tweaks are configured, rather than a specific bundle's settings. Most of the time Symfony's autowiring handles this for you without edits, but the file is there when you need to be explicit.

.env and .env.local

Symfony reads environment configuration from .env files at the project root. .env is committed to version control and holds sane defaults that work for every developer on the team. .env.local is not committed — it's where each developer overrides values for their own machine, most commonly the database connection string.

# .env (committed — safe defaults, no real secrets)
DATABASE_URL="mysql://app:app@127.0.0.1:3306/app_dev"

# .env.local (ignored by git — your machine's real values)
DATABASE_URL="mysql://root:secret@127.0.0.1:3306/my_project"
Note: These are real Symfony configuration conventions to copy into your own project — this website itself has no Symfony installation, so there's nothing to run live here. We'll set up a real database connection on the Database Configuration page.

bin/console: The Command-Line Entry Point

Every Symfony CLI command you'll run from inside your project — clearing the cache, creating a controller, running database migrations, or any custom command you write — goes through one script: bin/console.

php bin/console cache:clear
php bin/console make:controller

We'll come back to bin/console in depth, including how to write your own commands, on the Console Commands page later in this track.

Up next: Head to Routing to see how URLs get mapped to the controllers we just talked about.