Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Диплом.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.2 Mб
Скачать

1.5.3. Сущности Doctrine

Одной из наиболее распространенных и сложных задач для любого приложения является сохранение и чтение информации в базу данных и из нее. Symfony Framework не интегрирует какой-либо компонент для работы с базами данных, но обеспечивает тесную интеграцию с сторонней библиотекой под названием Doctrine. Единственная цель Doctrine - предоставить мощные инструменты для легкого и гибкого взаимодействия с базами данных. Он сопоставляет объекты с реляционной базой данных (например, MySQL, PostgreSQL или Microsoft SQL). Также имеется возможность сохранения данных в NoSQL базе данных MongoDB с помощью Doctrine ODM library.

Далее в этом подпункте будет приведён пример создания конкретной базы данных под названием test_project и объекта Product.

Информация о подключении к базе данных описывается в файле конфигурации parameters.yml в виде переменных параметров, которые будут использованы в главном файле конфигурации.

# app/config/config.yml

doctrine:

dbal:

driver: pdo_mysql

host: '%database_host%'

dbname: '%database_name%'

user: '%database_user%'

password: '%database_password%'

Листинг 4. Параметры подключения к базе данных

После настроек подключения Doctrine имеет возможность подключиться к базе данных. С помощью команды «php bin/console doctrine:database:create» Doctrine автоматически сгенерирует пустую базу данных. При использовании SQLite в качестве базы данных, необходимо указать путь, в котором должен храниться файл базы данных. Для этого используется параметр doctrine.dbal.path.

Следующим этапом является создание сущности, а именно класса, расположенного в папке Entity внутри каталога бандла. Данный класс может быть сгенерирован автоматически, с помощью команды «php bin/console doctrine:generate:entity». Данная команда задаёт интерактивные вопросы, которые помогают создать разработчику любой объект.

Doctrine позволяет работать с базами данных гораздо более продуктивным способом, чем просто набор строк скалярных данных в массиве. Вместо этого Doctrine позволяет извлекать целые объекты из базы данных и сохранять целые объекты в базе данных. Чтобы Doctrine мог это сделать, необходимо сопоставить таблицы базы данных с определенными классами PHP, а столбцы этих таблиц должны быть сопоставлены определенным свойствам в соответствующих классах PHP.

Рис. 6. Пример сопоставления таблицы БД с PHP-объектом

Эта информация представляется в виде «метаданных», набора правил, который сообщает Doctrine, как именно класс и его свойства должны быть сопоставлены с конкретной таблицей базы данных. Эти метаданные могут быть указаны в нескольких разных форматах, включая YAML, XML или непосредственно внутри класса с помощью DocBlock аннотаций. Разработчик имеет возможность выбрать наиболее удобный способ определения метаданных, но наиболее распространённым вариантом является использование аннотаций. Бандл может принимать только один формат определения метаданных. Например, невозможно сопоставить определения метаданных YAML с аннотированными определениями сущностей PHP. Имя таблицы является необязательным и, если оно опущено, будет определяться автоматически на основе имени класса сущности.

<? namespace AppBundle\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")

*/

private $id;

/**

* @ORM\Column(type="string", length=100)

*/

private $name;

/**

* @ORM\Column(type="decimal", scale=2)

*/

private $price;

/**

* @ORM\Column(type="text")

*/

private $description;

}

Листинг 5. Пример ORM-сущности Doctrine с описанием в виде аннотаций

После создания сущностей необходимо проверить её описание с помощью команды «php bin/console doctrine:schema:validate».

Не смотря на то, что Doctrine имеет представление о том, как сохранить объект в базе данных, класс приведённый в листинге 5 является бесполезным. Поскольку Product - это обычный PHP-класс со private свойствами, необходимо создать public методы getter и setter (например getName(), setName($name)), чтобы получить доступ к его свойствам в остальном коде приложения. Команда «php bin/console doctrine:generate:entities AppBundle/Entity/Product» может автоматически генерировать эти шаблонные методы. Эта команда гарантирует, что все геттеры и сеттеры будут созданы для класса. Это безопасная команда – имеется возможность запускать её неограниченное количество раз: она генерирует только геттеры и сеттеры, которые не существуют (т. е. не заменяют существующие методы). Генератор сущности Doctrine создает простые геттеры/сеттеры. При необходимости можно добавить любую логику в соответствии с потребностями создаваемого приложения.

Для автоматического создания всех таблиц базы данных, необходимых для каждого известного объекта используется команда «php bin/console doctrine:schema:update –force». Эта команда сравнивает, как должна выглядеть база данных (на основе информации о сопоставлении сущностей) с тем, как она выглядит на самом деле, и выполняет инструкции SQL, необходимые для обновления схемы базы данных. Другими словами, если добавить новое свойство с метаданными сопоставления в класс сущности и запустить эту команду, она выполнит инструкцию «ALTER TABLE», необходимую для добавления этого нового столбца в существующую таблицу.

Еще один способ воспользоваться этой функциональностью - это миграции, которые позволяют создавать операторы SQL и сохранять их в классах миграции, которые можно систематически запускать на производственном сервере, чтобы безопасно и надежно обновлять и отслеживать изменения в схеме базы данных.

Независимо от того, используются ли возможности миграции, команда «doctrine:schema:update» должна использоваться только во время разработки. Она не должна использоваться в производственной среде.

После того как объект стал соответствовать таблице, появляется возможность сохранять объект в базе данных. Внутри контроллера это можно сделать, как указано в листинге 6.

<?

// src/AppBundle/Controller/DefaultController.php

use AppBundle\Entity\Product;

use Symfony\Component\HttpFoundation\Response;

use Doctrine\ORM\EntityManagerInterface;

use Doctrine\Common\Persistence\ManagerRegistry;

public function createAction(EntityManagerInterface $em)

{

// создание нового объекта класса Product

$product = new Product();

// устанавливает значения свойств

$product->setName('Keyboard');

$product->setPrice(19.99);

$product->setDescription('Ergonomic and stylish!');

// сообщение Doctrine, о намерении сохранить объект

$em->persist($product);

// фактическое выполнение запроса INSERT

$em->flush();

// возвращение ответа

return new Response('Saved new product with id '.$product->getId());

}

Листинг 6. Сохранение объекта в базу данных

Метод flush() использует механизмы кэширования и подготавливает единый запрос к базе в независимости от количества создаваемых объектов.

Для получения объекта из базы данных используются механизмы, аналогичные тем, что указаны в листинге 7.

<?

use Doctrine\ORM\EntityManagerInterface;

public function showAction($productId, EntityManagerInterface $em)

{

// получение репозитория объекта и запрос сущности по её ID

$product = $em->getRepository('AppBundle:Product')

->find($productId);

// вывод сообщения об ошибке в случае отсутствия сущности с указанным ID

if (!$product) {

throw $this->createNotFoundException(

'No product found for id '.$productId

);

}

}

Листинг 7. Получение сущности из базы данных

Для запроса объектов из базы можно использовать различные методы репозитория. Таковыми могут быть как стандартные методы (findBy, find, findAll, findOneBy и т. д.), так и методы, которые определены в репозитории сущности самим разработчиком.

При рендеринге страницы, панель инструментов веб-отладки внизу страницы отображает количество запросов и время, необходимое для их выполнения.

Если количество запросов к базе данных слишком велико, значок станет желтым, указывая на то, что что-то может быть неверным. При нажатии на значок, можно открыть Symfony Profiler и посмотреть конкретные запросы, которые были выполнены.

После получения объекта, имеется возможность его обновить, как это указано в листинге 8.

<?

use Doctrine\ORM\EntityManagerInterface;

public function updateAction($productId, EntityManagerInterface $em)

{

// получение репозитория объекта и запрос сущности по её ID

$product = $em->getRepository('AppBundle:Product')->find($productId);

// вывод сообщения об ошибке в случае отсутствия сущности с указанным ID

if (!$product) {

throw $this->createNotFoundException(

'No product found for id '.$productId

);

}

// установка нового значения свойства

$product->setName('New product name!');

// фактическое выполнение запроса INSERT

$em->flush();

// перенапрваление на главную страницу

return $this->redirectToRoute('homepage');

}

Листинг 8. Обновление объекта в базе данных

Для удаления объекта используются метод $em->remove(). Для фактического удаления используется метод $em->flush();

В случае необходимости использования более сложных запросов используется DQL – родной язык Doctrine. Он очень схож с языком SQL, за одним большим отличием – при построении запросов необходимо думать с точки зрения выбора объектов PHP, а не строк в базе данных. Такие запросы можно создавать непосредственно внутри методов классов контроллеров, но для организации Doctrine предоставляются специальные классы репозитория, которые позволяют хранить всю логику запросов в одном централизованном месте.

<?

$query = $em->createQuery(

'SELECT p

FROM AppBundle:Product p

WHERE p.price > :price

ORDER BY p.price ASC'

)->setParameter('price', 19.99);

$products = $query->getResult();

Листинг 9. Пример построения запроса на языке DQL

Doctrine позволяет сосредоточиться на объектах и на том, как они используются в приложении, и обеспечивает сохранность базы данных. Это связано с тем, что Doctrine позволяет использовать любой объект PHP для хранения данных и полагается на информацию метаданных для сопоставления данных объекта с конкретной таблицей базы данных.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]