ZetCode

Symfony 实体

最后修改时间:2025 年 3 月 4 日

Symfony 实体教程展示了如何在 Symfony 应用程序中创建实体。

Symfony

Symfony 是领先的 PHP 框架之一。它是一套可重用的 PHP 组件,也是一个用于 Web 项目的 PHP 框架。Symfony 于 2005 年作为免费软件发布。Symfony 的灵感来自于 Django、RoR 和 Spring 框架。

实体

实体是一个需要持久化的轻量级领域对象。通常,实体代表关系数据库中的一个表,每个实体实例对应表中的一行。

存储库是对持久化功能的抽象。它允许存储、检索和搜索实体对象。本质上,存储库是实体对象的集合。

Symfony 实体示例

在下面的示例中,我们将处理 City 实体。

$ symfony new syment --version=7.2 --webapp
$ cd syment

我们使用 --webapp 选项创建一个新的 Symfony 7.2 项目,该选项包含 Web 应用程序的常用捆绑包,然后导航到项目目录。

$ php bin/console --version
Symfony 7.2.0 (env: dev, debug: true)

我们使用的是 Symfony 7.2.0 版本。

$ composer require symfony/orm-pack

我们安装 Doctrine ORM 捆绑包,其中包含注解和其他必要的依赖项。annot 捆绑包不再需要单独安装,因为它已包含在 symfony/orm-pack 中。

$ composer require --dev orm-fixtures maker

为了开发目的,我们安装了 fixtures 和 maker 捆绑包。Fixtures 将假数据加载到数据库中,而 maker 捆绑包则有助于脚手架的生成。

.env
DATABASE_URL="sqlite:///%kernel.project_dir%/var/ydb.db"

.env 文件中,我们定义了数据库 URL。在此示例中,为简化起见,我们使用 SQLite。

$ php bin/console doctrine:database:create

doctrine:database:create 命令会根据提供的 URL 创建一个新数据库。

$ php bin/console make:entity

使用 make:entity 命令,我们创建了一个新的 City 实体。这将生成 src/Entity/City.phpsrc/Repository/CityRepository.php。我们添加了两个属性:name(字符串,255 个字符)和 population(整数)。

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;
    }
}

这是更新到 Symfony 7.2 的 City 实体。我们使用 PHP 8 属性语法(例如 #[ORM\Entity]),而不是 PHPDoc 注解。该实体映射到 cities 表。

src/Repository/CityRepository.php
<?php

namespace App\Repository;

use App\Entity\City;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

/**
 * @extends ServiceEntityRepository<City>
 *
 * @method City|null find($id, $lockMode = null, $lockVersion = null)
 * @method City|null findOneBy(array $criteria, array $orderBy = null)
 * @method City[]    findAll()
 * @method City[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class CityRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, City::class);
    }
}

CityRepository 在很大程度上保持不变,但使用了现代 PHP 类型提示和 docblock 约定。

$ php bin/console make:migration

我们使用 make:migration 生成迁移,以便为数据库模式更改添加版本控制。

$ php bin/console doctrine:migrations:migrate

这将应用迁移,创建一个类似 Version20250304120000.php 的文件(时间戳会有所不同)。

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');
    }
}

迁移文件现在包含描述和简化的特定于 SQLite 的 SQL。

$ php bin/console make:fixtures

我们使用 make:fixtures 创建一个 CityFixtures 类来加载示例数据。

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();
    }
}

CityFixtures 类已更新为更简洁的结构,使用了数组和循环。

$ php bin/console doctrine:fixtures:load

此命令将 fixture 数据加载到 cities 表中。

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);
    }
}

CityController 使用新的 #[Route] 属性语法,并直接返回 JsonResponse。响应处理得到了简化。

$ symfony serve

我们启动 Symfony 开发服务器。

$ 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}]

我们使用 curl 测试端点并检索 JSON 数据。

在本教程中,我们使用现代 PHP 和 Symfony 功能,在 Symfony 7.2 应用程序中处理了实体。

列出 所有 Symfony 教程