Symfony Привязка новой записи к сторонней сущности

bars80081

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

Допустим, есть блог с постами. Есть поле blog.creator int, которое несёт в себе id пользователя (таблица user.id). Соответственно, хочется, чтобы при создании записи в таблице blog, в поле blog.creator проставлялось id авторизованного пользователя.

сущности:
PHP:
namespace App\Entity;

use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ORM\Table(name="user")
 */
class User extends BaseUser implements UserInterface
{
PHP:
<?php
// src/Blogger/BlogBundle/Entity/Blog.php

namespace App\Blogger\BlogBundle\Entity;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\User;

/**
 * @ORM\Entity(repositoryClass="App\Blogger\BlogBundle\Entity\Repository\BlogRepository")
 * @ORM\Table(name="blog")
 * @ORM\HasLifecycleCallbacks
 */
class Blog
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="integer")
     */
    protected $creator_id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User")
     * @ORM\JoinColumn(name="creator_id", referencedColumnName="id")
     */
    protected $user;
...
    /**
     * Set creator_id
     * @param integer $creator_id
     * @return Blog
     */
    public function setCreatorId($creator_id)
    {
        $this->creator_id = $creator_id;
        $this->setUser();
        return $this;
    }

    /**
     * Get creator_id
     * @return integer
     */
    public function getCreatorId()
    {
        return $this->creator_id;
    }

    /**
     * Set user.
     * @param integer $creator_id
     * @return Blog
     */
    private function setUser()
    {
        if(empty($this->creator_id)) {
            $this->user = new User();
        } elseif($this->em && !empty($this->creator_id)) {
            $this->user = $this->em->getRepository('User')->find($this->creator_id);
        }
        return $this;
    }

    /**
     * Get user.
     * @return \App\Entity\User|null
     */
    public function getUser()
    {
        return $this->user;
    }
    /**
     * @ORM\PostLoad
     * @ORM\PostPersist
     */
    public function fetchEntityManager(LifecycleEventArgs $args)
    {
        if(is_null($this->em)) {
            $this->em = $args->getEntityManager();
        }
        if(is_null($this->user)) {
            $this->setUser();
        }
    }
}
в чём вопрос? как это ПРАВИЛЬНО сделать?

вопрос 1:
если я сам формирую форму и обрабатываю её, то само собой напрашивается решение на валидации формы:
PHP:
class BlogController extends AbstractController
{
    private $security;
    public function __construct(Security $security)
    {
        $this->security = $security;
    }

    public function createAction(Request $request)
    {
        $blog  = new Blog();
        $form    = $this->createForm(BlogType::class, $blog);
        $form->handleRequest($request);

        if ($form->isValid()) {
            
            $blog->setCreatorId($this->security->getUser()->getId());
            
            $em = $this->getDoctrine()
                ->getManager();
            $em->persist($blog);
            $em->flush();
правильно ли это? или я горожу велосипед там, где есть волшебная команда?

вопрос 2:
если я установил EasyAdminBundle, который очень удачно лёг и позволяет легко просматривать записи Blog, редактировать и добавлять их.
Каким образом там надо задать конфигурацию, чтобы поле creator заполнялось пользователем?
В теории ответ должен был быть прописан в EasyAdminBundle/book/edit-new-configuration , но почему-то ни там, ни в прочих разделах ничего не обнаружил.
Возникает ощущение, что это надо делать через подачу опций, которые будут переданы в createFormBuilder:
Код:
# config/packages/easy_admin.yaml
easy_admin:
    entities:
        Customer:
            class: App\Entity\Customer
            form:
                form_options: { validation_groups: ['Default', 'my_validation_group'] }
    # ...
PHP:
$form = $this->createFormBuilder($entity, array(
    'data_class' => 'App\Entity\Customer',
    'validation_groups' => array('Default', 'my_validation_group'),
))
-> ...
но что указывать в этих опциях? если можно, ткните в нужное место документации тогда.
Или надо указывать автозаполнение этого поля при создании сущности (прямо в классе сущности)? Но ведь тогда я отягащу сущность функционалом, которого вроде как следует избегать
 

AmdY

Пью пиво
Команда форума
Забудь о creator_id, доктрина сама с ним разберётся, тебе надо работать только с user.
 

bars80081

Новичок
ммм, как?
удалить поле creator? как тогда будет обеспечено указание на автора?
а если мне в user захочется указать не авторизованного пользователя, а просто любого выбранного из БД?
 

AmdY

Пью пиво
Команда форума
нет же, я говорил лишь о creator_id, а не о creator. тебе не надо манипулировать ИД
и убери из модели fetchEntityManager и прочие обращения к репозиторию, зачем ты это делаешь?
Моделька у тебя должна быть простой, зачем ты её так нагрузил непонятной логикой?

Вот же пример в доке, никакой лишней логики https://symfony.com/doc/current/doctrine/associations.html
 

bars80081

Новичок
Наконец ткнули в нужное место! Спасибо!
как всегда, очень не хватает разжёванного примера или чтобы ткнули лицом в конкретное место документации

Теперь конечно гораздо всё проще:
поле в таблице blog.creator_id,
свойство в сущности:
PHP:
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User")
     */
    protected $creator;
сохранение в контроллере просто:
PHP:
    public function createAction(Request $request)
    {
        $blog  = new Blog();
        $form    = $this->createForm(BlogType::class, $blog);
        $form->handleRequest($request);

        if ($form->isValid()) {
            $blog->setCreator($this->getUser());

            $em = $this->getDoctrine()
                ->getManager();
            $em->persist($blog);
            $em->flush();

            return $this->redirect($this->generateUrl('BloggerBlogBundle_blog_show', array(
                    'id'    => $blog->getId()))
            );
        }

        return $this->render('@BloggerBlog/Blog/form.html.twig', array(
            'form'    => $form->createView()
        ));
    }
 

bars80081

Новичок
ещё один вопрос. если не секрет и работали с EasyAdmin, каким образом там можно сохранить пользователя?
 

bars80081

Новичок
уверен, что это делается прямо через конфигурацию, но не хватает мозгов увидеть это в доках.
вот как установить список из существующих пользователей на выбор:
Код:
easy_admin:
    entities:
        Blog:
            class: App\Blogger\BlogBundle\Entity\Blog
            form:
                fields:
                    - title
                    - blog
                    - { property: 'creator', type_options: { class: 'App\Entity\User' } }
но как определить установку по умолчанию без возможности выбора или запихнуть авторизованного пользователя, где это, хоть убей не вижу
 

bars80081

Новичок
В общем, решение есть, описано в Customization Based on Overriding the Default AdminController
PHP:
// src/Controller/AdminController.php

namespace App\Controller;

use App\Blogger\BlogBundle\Entity\Blog;
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;

class AdminController extends EasyAdminController
{
    /**
     * @param Blog $entity
     */
    public function persistBlogEntity($entity)
    {
        $entity->setCreator($this->getUser());
        parent::persistEntity($entity);
    }
}
YAML:
# config/routes/easy_admin.yaml
easy_admin_bundle:
    resource: 'App\Controller\AdminController'
    prefix: /admin
    type: annotation
однако, попахивает мракобесием. всё использование easyadmin построено на создании комплекса директив в конфигурации. а чтобы определить такую обыденную вещь приходится использовать чёрный ход (исключение из общего хода). да мне почти в каждой таблице надо сохранять параметры окружения, которые пользователь не должен иметь возможность править.

по-прежнему подозреваю, что где-то жёстко туплю
 
Сверху