0

symfony2 の「クラス テーブル継承」モデルを使用して、継承を伴うデータベース モデルがあります。

Employee は、最上位の継承モデルである抽象クラスです。

秘書は従業員を拡張する子です。Technician は、Employee を拡張する子でもあります。

秘書が技術者のためにいくつかのことを管理できるアプリケーションを構築しているため、秘書にはフォームなどを備えた管理パネルがあります。

SecretRepository は、秘書がアプリケーションを介して認証できるようにする UserProvider インターフェイスでもあります。

私が抱えている問題は、認証クエリが識別子を気にしないことです...

認証 SQL クエリのデバッグ

SELECT e0_.*, s1_.*
FROM secretaries s1_
INNER JOIN employees e0_ ON s1_.id = e0_.id
WHERE e0_.removed_at IS NULL AND e0_.is_hidden = ? AND e0_.email = ?

秘書と従業員の関係を管理する方法がわかりませんか?秘書から従業員への外部キーを手動で含める必要がありますか? または、認証クエリの識別子を手動で処理する必要がありますか?

私のモデルの基本を見てみましょう:

クラスの従業員

abstract class Employee
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="email", type="string", length=255, nullable=true)
     */
    protected $email;

    // [...] some other fields
}

クラス書記

class Secretary extends Employee
{
    /**
     * @var string
     *
     * @ORM\Column(name="password", type="string", length=255, nullable=true)
     * @Assert\NotBlank()
     */
    private $password;

    /**
     * @var string
     *
     * @ORM\Column(name="salt", type="string", length=40)
     */
    private $salt;

    /**
     * @var array
     *
     * @ORM\Column(name="roles", type="array")
     */
    private $roles;

    // [...] some other fields
}

UserProviderInterfaceクラスのSecretRepository

class SecretaryRepository extends EntityRepository implements UserProviderInterface
{
    public function loadUserByUsername($username)
    {
        $secretary = null;

        $qb = $this->_em->createQueryBuilder();

        $qb->select('s')
            ->from('HygieCoreBundle:Secretary', 's')
            ->where($qb->expr()->isNull('s.removedAt'))
            ->andWhere($qb->expr()->eq('s.isHidden', ':isHidden'))
            ->andWhere($qb->expr()->eq('s.email', ':email'))
            ->setParameter('isHidden', false)
            ->setParameter('email', $username)
        ;

        try {
            $secretary = $qb->getQuery()->getSingleResult();
        }
        catch (NoResultException $e) {
            throw new UsernameNotFoundException(sprintf('Aucune secrétaire ne possède l\'adresse e-mail : "%s".', $username), 0, $e);
        }

        return $secretary;
    }

    // [...] some other methods
}

問題は単純です。INNER JOIN 句は正しくありません。なぜなら、秘書から従業員への外部キーを使用せず、技術者 ID にもなり得る直接 ID を使用するからです。

これは私のテーブルのいくつかの行のエクスポートです:

INSERT INTO `technicians` (`id`, `speciality`) VALUES
(1, 'Communication')

INSERT INTO `employees` (`id`, `created_at`, `updated_at`, `removed_at`, `is_hidden`, `firstname`, `name`, `entityName`) VALUES
(1, '**sometime**', '**sometime**', NULL, 0, '**TechnicianFirstname**', '**TechnicianName**', 'technician'),
(2, '**sometime**', '**sometime**', NULL, 0, '**SecretaryFirstName**', '**SecretaryName**', 'secretary');

INSERT INTO `secretaries` (`id`, `password`, `salt`, `roles`) VALUES
(1, '**HashedPassword**', '**HashedSalt**', 'O:43:"Doctrine\\Common\\Collections\\ArrayCollection":1:{s:54:"\0Doctrine\\Common\\Collections\\ArrayCollection\0_elements";a:1:{i:0;s:10:"ROLE_ADMIN";}}');

ALTER TABLE `technicians` ADD CONSTRAINT `FK_1DCF6554BF396750` FOREIGN KEY (`id`) REFERENCES `employees` (`id`) ON DELETE CASCADE;

ALTER TABLE `secretaries` ADD CONSTRAINT `FK_ACB3412BF396750` FOREIGN KEY (`id`) REFERENCES `employees` (`id`) ON DELETE CASCADE;
4

1 に答える 1

1

テーブルから直接データを選択してsecretariesいるため、誤って技術者を選択する可能性はありません。このコードで安全です。

同じクエリで秘書役と技術者の両方を選択する場合、つまり、クエリがテーブルから選択する場合に、ディスクリミネーターが必要になりますemployees

于 2014-05-25T17:21:09.140 に答える