Mapping сущностей на таблицы в БД

Конфигурирование мэппинга сущностей и агрегатов на таблицы в БД. Создание собственных типов. Работа со вложенными объектами и коллекциями.

  • 00:01:18 - Переименование класса Network
  • 00:02:13 - Какие таблицы нам нужны в базе данных
  • 00:05:46 - Привязка к таблице
  • 00:10:33 - Мэппинг примитивных типов
  • 00:12:27 - Кастомные типы для простых объектов-значений
  • 00:23:38 - Embedded для сложных объектов-значений токенов
  • 00:32:34 - Мэппинг коллекции объектов-значений networks через сущность-носитель
  • 00:47:40 - Промежуточные итоги
  • 00:49:35 - Устройство сохранения и поиска в Doctrine
  • 00:52:20 - Реализация UserRepository
  • 01:02:54 - Реализация Flusher
  • 01:03:05 - Почему не используем напрямую EntityManager и наследование
Скрытый контент
Комментарии (34)
Arunas
2020-02-25 19:31

Да, спасибо.

Ответить
Роман
2020-02-25 20:39

Как то все уж очень сложно получается. Свой велосипед что ли.. Кто как думает?

Ответить
Arunas
2020-02-26 15:08

Думаю доверять Дмитрию, падождать результата - задействие Doctrine ORM на практике. Свой велосипед лучше, чем чужой неизвестный.

Ответить
elmut
2020-04-04 16:12

EntityManagerFactory Класс буду внедрять луче чем zend.

    public function getDoctrine(): array
    {
        return [
                'configuration' => [
                    'orm_default' => [
                        'result_cache' => getenv('DOCTRINE_CACHE_TYPE'),
                        'metadata_cache' => getenv('DOCTRINE_CACHE_TYPE'),
                        'query_cache' => getenv('DOCTRINE_CACHE_TYPE'),
                        'hydration_cache' => getenv('DOCTRINE_CACHE_TYPE'),
                    ],
                ],
                'connection' => [
                    'orm_default' => [
                        'driver_class' => Doctrine\DBAL\Driver\PDOPgSql\Driver::class,
                        'params' => [
                            'host' => getenv('POSTGRES_HOST'),
                            'port' => getenv('POSTGRES_PORT'),
                            'user' => getenv('POSTGRES_USER'),
                            'password' => getenv('POSTGRES_PASSWORD'),
                            'dbname' => getenv('POSTGRES_DB_NAME'),
                        ],
                    ],
                ],
                'types' => [
                    UuidType::NAME => UuidType::class,
                ],
                'driver' => [
                    'orm_default' => [
                        'class' => Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::class,
                        'drivers' => [],
                    ],
                ],
        ];
    }

ModelUser

    public function getDoctrineEntities(): array
    {
        return [
            'driver' => [
                __NAMESPACE__.'_driver' => [
                    'class' => \Doctrine\ORM\Mapping\Driver\AnnotationDriver::class,
                    'cache' => getenv('DOCTRINE_CACHE_TYPE'),
                    'paths' => [__DIR__.'/Model/Entity'],
                ],
                'orm_default' => [
                    'drivers' => [
                        __NAMESPACE__ => __NAMESPACE__.'_driver',
                    ],
                ],
            ],
            'types' => [
                RoleType::NAME => RoleType::class,
                StatusType::NAME => StatusType::class,
                \Ramsey\Uuid\Doctrine\UuidType::NAME => \Ramsey\Uuid\Doctrine\UuidType::class,
            ],
        ];
    }
Ответить
Arunas
2020-02-27 18:25

не заметил, где получаем вошедший-зарегистрированный в систему пользователь - его id?

Ответить
Deworker Pro
2020-02-28 22:09

Контроллеров ещё нет, так что пока нигде.

Ответить
Arunas
2020-02-27 18:49

сегодня папробовал composer update (в Makefile вместо composer install). Make init: всё вроди обновлялось, но застрял vimeo/psalm: ошибка Updating vimeo/psalm (3.8.0 => 3.9.3): Update failed (Could not delete /app/vendor/vimeo/psalm/src/Psalm/Issue:) Это очень плохо?

Ответить
Deworker Pro
2020-02-28 22:10

Удалите целиком папку vendor и запустите снова.

Ответить
Arunas
2020-02-29 08:58

да, спасибо.

Ответить
Shaitan
2020-02-28 09:23

Дмитрий здравствуйте! Вопрос немного не по теме урока, но все же очень интересно. Нужно ли оборачивать в транзакцию при сохранении? Есть ли в данном действии смысл? На одном из собеседований, меня в этом убеждали. Хотя я не совсем понимаю зачем, разве доктрина даст произвести модификацию в бд, если вылетит какая-либо ошибка? Заранее спасибо!

Ответить
Deworker Pro
2020-02-28 22:21

Вручную не нужно, Doctrine внутри $em->flush() сама оборачивает всё в транзакцию.

Ответить
Shaitan
2020-02-28 09:47

Дмитрий, спасибо за вебинар, вопрос есть еще такого плана. Репозиторий же можно отнаследовать от доктриновского репозитория(EntityRepository), а в анотации к ентити дописать наш репозиторий. Почему вы не использовали такой вариант репозитория?

Ответить
Deworker Pro
2020-02-28 22:33

Ответили в четырёх последних минутах видео, что при этом из EntityRepository будет наследоваться куча его методов, которые нам не нужны и которые мы никак не контролируем. У программистов будет соблазн дёрнуть напрямую findOneBy([...]) или createQueryBuilder('t') и понаписать кучу запросов в обход наших методов. Наш же репозиторий от этого защищён.

Ответить
Arunas
2020-02-29 09:40

привет, не на тему, но случилось такой курьез: сегодня скачал код с репозитория. После make init на ВМ Вагранта (Ubuntu 16.04.6 LTS) все порядки: саит показывает и тесты проходят. Но в линуксовом компютере (Ubuntu 18.04.4 LTS) только тесты проходят, но в браузере localhost:8080 (Chrome): ошибка 403 Forbidden, nginx/1.17.8 - Auction сайт не работает. Как это исправить?

Ответить
Deworker Pro
2020-03-01 13:14

А localhost:8081 открывается?

Ответить
Arunas
2020-03-01 14:51

при localhost:8081 тоже не работает, но пишет: File not found.

Ответить
fedot
2020-03-02 10:12

Скорее всего что-то с доступом, посмотри логи веб сервера

Ответить
Arunas
2020-03-04 17:30

помогите решить этот 403 Forbidden при localhost:8080.

Ответить
Deworker Pro
2020-03-04 19:01

Чего-то в системе не хватает. Как именно помочь?

Ответить
Arunas
2020-03-04 19:52

Да, и project-manager на Линуксовом ПК также не запускается, логи nginx:

manager-nginx_1         | 2020/03/04 19:40:07 [crit] 7#7: *1 stat() "/app/public/" failed (13: Permission denied), client: 172.18.0.1, server: , request: "GET / HTTP/1.1", host: "localhost:8080"
manager-nginx_1         | 2020/03/04 19:40:07 [crit] 7#7: *1 stat() "/app/public/" failed (13: Permission denied), client: 172.18.0.1, server: , request: "GET / HTTP/1.1", host: "localhost:8080"
manager-nginx_1         | 2020/03/04 19:40:07 [error] 7#7: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 172.18.0.1, server: , request: "GET / HTTP/1.1", upstream: "fastcgi://172.18.0.12:9000", host: "localhost:8080"
Ответить
Arunas
2020-03-07 17:44

Переинсталировал весь линуксовый компютер, теперь всё ок, спасибо за намёк.

Ответить
Сергей
2020-03-04 10:10

Дмитрий, у нас есть модуль Auth, где определен entity User. Если мы создадим другой модуль, внутри которого будет связь другой entity с пользователями, то модули не будет изолированы друг от друга. Насколько это правильно?

Ответить
Deworker Pro
2020-03-04 11:39

В другом модуле не будет связи с User. Там для связи будет уже своя сущность, но с тем же ID.

Ответить
Shaitan
2020-03-04 13:44

Дмитрий, вопрос следующий, оправдано ли хранение токенов в отдельной таблице? Или токены лучше хранить в таблице с юзерами? Интересует общепринятая практика. Ну и мне кажется отдельное хранение токенов упрощают сущность юзера? В чем минусы и плюсы обоих подходов? Спасибо!

Ответить
Deworker Pro
2020-03-04 18:58

Можно хранить и в отдельной таблице. И даже в отдельном хранилище вроде Redis. Сущность упрощается, но придётся ходить в оба места для каждой операции.

Ответить
Arunas
2020-03-14 09:27

какую и как завести быструю, легковестную БД на клиетскую часть для хранении параметров (всяких default value, интервалов времени) и для полноценной работы, когда интернет исчезает (при исчезновение связи с материнской базой).

Ответить
Deworker Pro
2020-03-14 11:54

Мобильные приложения часто используют SQLite.

Ответить
Arunas
2020-03-15 06:14

спасибо.

Ответить
Валентин
2020-04-01 20:01

Доброго времени суток! Дмитрий, могли бы вы объяснить, почему в нашем случае мы сделали прослойку UserNetwork для маппинга, а не использовали "One-To-Many, Unidirectional with Join Table" из документации доктрины, в подходе из документации есть какие-то подводные камни?

Ответить
Валентин
2020-04-01 20:01

Извиняюсь, если невнимательно посмотрел видел и упустил этот момент)

Ответить
Deworker Pro
2020-04-04 07:32

Да, можно так сделать по аналогии Many-To-Many. Но для этого также нужно будет добавить первичный ключ id и потом потребуется делать более сложные JOIN-запросы через эту промежуточную таблицу.

Ответить
Артём
2020-04-18 11:48

Прекрасные уроки - с каждым уроком сознание расширяется. Спасибо!

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий