37

私は説得し、答えを見つけることができません。アプリケーションにデータベースロールモデルがあります。ユーザーはロールを持つことができますが、このロールはデータベースに保存する必要があります。

ただし、ユーザーはデータベースからデフォルトの役割を追加する必要があります。だから私はサービスを作成しました:

<?php

namespace Alef\UserBundle\Service;

use Alef\UserBundle\Entity\Role;

/**
 * Description of RoleService
 *
 * @author oracle
 */
class RoleService {

    const ENTITY_NAME = 'AlefUserBundle:Role';

    private $em;

    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    public function findAll()
    {
        return $this->em->getRepository(self::ENTITY_NAME)->findAll();
    }

    public function create(User $user)
    {
        // possibly validation here

        $this->em->persist($user);
        $this->em->flush($user);
    }

    public function addRole($name, $role) {
        if (($newrole = findRoleByRole($role)) != null)
            return $newrole;
        if (($newrole = findRoleByName($name)) != null)
            return $newrole;

        //there is no existing role
        $newrole = new Role();
        $newrole->setName($name);
        $newrole->setRole($role);

        $em->persist($newrole);
        $em->flush();

        return $newrole;
    }

    public function getRoleByName($name) {
        return $this->em->getRepository(self::ENTITY_NAME)->findBy(array('name' => $name));
    }

    public function getRoleByRole($role) {
        return $this->em->getRepository(self::ENTITY_NAME)->findBy(array('role' => $role));
    }

}

services.ymlは:

alef.role_service:
    class: Alef\UserBundle\Service\RoleService
    arguments: [%doctrine.orm.entity_manager%]

そして今、私はそれを2つの場所で使用したいと思います: UserControllerそしてUserエンティティ。どうすればエンティティ内にそれらを取得できますか?コントローラーに関しては、私は次のことを行う必要があると思います。

$this->get('alef.role_service');

しかし、エンティティ内でサービスを取得するにはどうすればよいですか?

4

3 に答える 3

46

あなたはそうしない。これは非常に一般的な質問です。エンティティは、他のエンティティについてのみ知っている必要があり、エンティティマネージャや他の高レベルのサービスについては知らない必要があります。この開発方法に移行するのは少し難しいかもしれませんが、通常はそれだけの価値があります。

あなたがしたいのは、ユーザーをロードするときにロールをロードすることです。通常、この種のことを行うUserProviderができあがります。セキュリティに関するセクションを読みましたか?それがあなたの出発点になるはずです:

http://symfony.com/doc/current/book/security.html

于 2012-04-26T12:25:23.687 に答える
37

そもそもサービスをエンティティに取り込むことが非常に難しい理由は、Symfonyがエンティティ内でサービスを使用してはならないという意図で明示的に設計されているためです。したがって、ベストプラクティスの答えは、エンティティでサービスを使用する必要がないようにアプリケーションを再設計することです。

ただし、グローバルカーネルをいじることを伴わない方法あることがわかりました。

Doctrineエンティティには、イベントリスナーをフックできるライフサイクルイベントがあります。http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-eventsを参照してください 。この例では、エンティティが作成された直後にトリガーされるpostLoadを使用します。

EventListenersは、他のサービスを注入するサービスとして作成できます。

app / config / config.ymlに追加します:

services:
     example.listener:
           class: Alef\UserBundle\EventListener\ExampleListener
     arguments:
           - '@alef.role_service'
     tags:
           - { name: doctrine.event_listener, event: postLoad }

エンティティに追加:

 use Alef\UserBundle\Service\RoleService;

 private $roleService;

 public function setRoleService(RoleService $roleService) {
      $this->roleService = $roleService;
 }

そして、新しいEventListenerを追加します。

namespace Alef\UserBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Alef\UserBundle\Service\RoleService;

class ExampleListener
{
     private $roleService;

     public function __construct(RoleService $roleService) {
         $this->roleService = $roleService;
     }

     public function postLoad(LifecycleEventArgs $args)
     {
         $entity = $args->getEntity();
         if(method_exists($entity, 'setRoleService')) {
             $entity->setRoleService($this->roleService);
         }
     }
}

このソリューションには、これがまだ迅速で汚い方法であるという警告が伴うことを覚えておいてください。実際には、アプリケーションを適切な方法で再設計することを検討する必要があります。

于 2015-09-29T18:54:10.220 に答える
1

質問に対する上記のKaiの回答に感謝しますが、symfony5.xとは互換性がありません。

これは悪い習慣ですが、レガシーコードや悪いDB設計(スキーマ移行前の一時的な解決策として)などの特殊なケースでは必要です。

私の場合と同じように、私はこのコードをメーラーとトランスレーターで使用します。これにより、Symfony> = 5.3の場合にプライベートプロパティに問題が発生するため、最近のバージョンのsymfonyの解決策は次のとおりです。

config / services.yaml内:

services:
    Alef\UserBundle\EventListener\ExampleListener:
        tags:
           - { name: doctrine.event_listener, event: postLoad }

ExampleListener:

namespace Alef\UserBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Alef\UserBundle\Entity\Role;

class ExampleListener
{

    public function postLoad(LifecycleEventArgs $postLoad): void
    {
        $entity = $postLoad->getEntity();
        if ($entity instanceof User) {
            $repository = ;
            $entity->roleRepository(
                $postLoad->getEntityManager()->getRepository(Role::class)
            );
        }
    }
}

そしてあなたのエンティティ(またはあなたがそれを複数のエンティティで使用する場合は特性)で:


    use Alef\UserBundle\Service\RoleService;

    /** @internal bridge for legacy schema */
    public function roleRepository(?RoleRepository $repository = null) {
        static $roleRepository;
        if (null !== $repository) {
            $roleRepository = $repository;
        }
        return $roleRepository;
    }

    public function getRoleByName($name) {
        return $this->roleRepository()->findBy(array('name' => $name));
    }
于 2021-08-02T14:36:19.327 に答える