last modified March 4, 2025
Symfony Entity tutorial shows how to create entities in Symfony application.
Symfony is one of the leading PHP frameworks. It is a set of reusable PHP components and a PHP framework for web projects. Symfony was published as free software in 2005. Symfony was inspired by Django, RoR, and Spring frameworks.
An entity is a lightweight domain object which is to be persisted. Typically, an entity represents a table in a relational database, and each entity instance corresponds to a row in the table.
A repository is an abstraction of the persistence functionality. It allows to store, retrieve and search for entity objects. In essence, a repository is a collection of entity objects.
In the following example, we work with the City entity.
$ symfony new syment –version=7.2 –webapp $ cd syment
We create a new Symfony 7.2 project with the –webapp option, which includes common bundles for web applications, and navigate to the project directory.
$ php bin/console –version Symfony 7.2.0 (env: dev, debug: true)
We work with Symfony 7.2.0 version.
$ composer require symfony/orm-pack
We install the Doctrine ORM pack, which includes annotations and other necessary dependencies. The annot package is no longer needed separately as it’s bundled with symfony/orm-pack.
$ composer require –dev orm-fixtures maker
We install the fixtures and maker bundles for development purposes. Fixtures load fake data into the database, and the maker bundle assists with scaffolding.
.env
DATABASE_URL=“sqlite:///%kernel.project_dir%/var/ydb.db”
In the .env file, we define the database URL. We use SQLite for simplicity in this example.
$ php bin/console doctrine:database:create
The doctrine:database:create command creates a new database based on the provided URL.
$ php bin/console make:entity
Using the make:entity command, we create a new City entity. This generates src/Entity/City.php and src/Repository/CityRepository.php. We add two properties: name (string, 255 characters) and population (integer).
src/Entity/City.php
<?php
namespace App\Entity;
use App\Repository\CityRepository; use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: CityRepository::class)] #[ORM\Table(name: ‘cities’)] class City { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column]
private ?int $population = null;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getPopulation(): ?int
{
return $this->population;
}
public function setPopulation(int $population): static
{
$this->population = $population;
return $this;
}
}
This is the City entity updated for Symfony 7.2. We use PHP 8 attribute syntax (e.g., #[ORM\Entity]) instead of PHPDoc annotations. The entity maps to the cities table.
src/Repository/CityRepository.php
<?php
namespace App\Repository;
use App\Entity\City; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry;
/**
The CityRepository remains largely the same but uses modern PHP type hints and docblock notation.
$ php bin/console make:migration
We generate a migration with make:migration to version the database schema changes.
$ php bin/console doctrine:migrations:migrate
This applies the migration, creating a file like Version20250304120000.php (timestamp will vary).
src/Migrations/Version20250304120000.php
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration;
final class Version20250304120000 extends AbstractMigration { public function getDescription(): string { return ‘Create cities table’; }
public function up(Schema $schema): void
{
$this->addSql('CREATE TABLE cities (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name VARCHAR(255) NOT NULL, population INTEGER NOT NULL)');
}
public function down(Schema $schema): void
{
$this->addSql('DROP TABLE cities');
}
}
The migration file now includes a description and simplified SQLite-specific SQL.
$ php bin/console make:fixtures
We create a CityFixtures class with make:fixtures to load sample data.
src/DataFixtures/CityFixtures.php
<?php
namespace App\DataFixtures;
use App\Entity\City; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Persistence\ObjectManager;
class CityFixtures extends Fixture { public function load(ObjectManager $manager): void { $cities = [ [’name’ => ‘Bratislava’, ‘population’ => 432000], [’name’ => ‘Budapest’, ‘population’ => 1759000], [’name’ => ‘Prague’, ‘population’ => 1280000], [’name’ => ‘Warsaw’, ‘population’ => 1748000], [’name’ => ‘Los Angeles’, ‘population’ => 3971000], [’name’ => ‘New York’, ‘population’ => 8550000], [’name’ => ‘Edinburgh’, ‘population’ => 464000], [’name’ => ‘Berlin’, ‘population’ => 3671000], ];
foreach ($cities as $data) {
$city = new City();
$city->setName($data['name']);
$city->setPopulation($data['population']);
$manager->persist($city);
}
$manager->flush();
}
}
The CityFixtures class is updated with a more concise structure using an array and a loop.
$ php bin/console doctrine:fixtures:load
This command loads the fixture data into the cities table.
src/Controller/CityController.php
<?php
namespace App\Controller;
use App\Repository\CityRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route;
class CityController extends AbstractController { #[Route(’/cities’, name: ‘cities’)] public function index(CityRepository $cityRepository): JsonResponse { $cities = $cityRepository->findAll();
if (empty($cities)) {
return new JsonResponse(['message' => 'No data found'], Response::HTTP_NOT_FOUND);
}
return $this->json($cities);
}
}
The CityController uses the new #[Route] attribute syntax and returns a JsonResponse directly. The response handling is streamlined.
$ symfony serve
We start the Symfony development server.
$ curl localhost:8000/cities [{“id”:1,“name”:“Bratislava”,“population”:432000}, {“id”:2,“name”:“Budapest”,“population”:1759000}, {“id”:3,“name”:“Prague”,“population”:1280000}, {“id”:4,“name”:“Warsaw”,“population”:1748000}, {“id”:5,“name”:“Los Angeles”,“population”:3971000}, {“id”:6,“name”:“New York”,“population”:8550000}, {“id”:7,“name”:“Edinburgh”,“population”:464000}, {“id”:8,“name”:“Berlin”,“population”:3671000}]
We test the endpoint with curl and retrieve the JSON data.
In this tutorial, we worked with an entity in a Symfony 7.2 application using modern PHP and Symfony features.
List all Symfony tutorials.