php 与学说的一对一关系
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php 与学说的一对一关系相关的知识,希望对你有一定的参考价值。
<?php
// namespace ...
/**
* Class VineAccess
*
* Represent an Access over a Vine
*
* @ORM\Entity
*/
class VineAccess extends AbstractAccess
{
const SCOPE_PRODUCER = 'SCOPE_VINE_PRODUCER';
const SCOPE_DRINKER = 'SCOPE_VINE_DRINKER';
/**
* @var Beer
*
* @ORM\ManyToOne(targetEntity="...\Entity\Vine")
*/
protected $object;
/**
* @param User $user
* @param string $scope A vine scope (constant)
* @param Vine $beer The Beer to be secured
*/
public function __construct(User $user, $scope, Vine $vine)
{
parent::__construct($user, $scope);
$this->object = $vine;
}
/**
* {@inheritdoc}
*
* @return AbstractContract
*/
public function getObject()
{
return $this->object;
}
}
<?php
// namespace ...
/**
* Class UpdateSchemaCommand
*
* This command is a hack for the Doctrine Schema Tool.
* Actually the Access classes use a one-to-ANY (different target entities per sub classes).
*
* While the entity manager is able to deal with this schema thanks to the single-table inheritance
* The schema tool doesn't understand this architecture.
*
* Only for this command, we add a special listener (AccessSchemaListener)
* which fakes a simple integer column instead of an association
*/
class UpdateSchemaCommand extends UpdateSchemaDoctrineCommand
{
public function configure()
{
parent::configure();
$this->setName('...:schema:update');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$evm = $this->getApplication()->getKernel()->getContainer()->get('doctrine')->getManager()->getEventManager();
$evm->addEventListener(Events::loadClassMetadata, new AccessSchemaListener());
parent::execute($input, $output);
}
}
<?php
// namespace ...
/**
* Class BeerAccess
*
* Represent an Access over a Beer
*
* @ORM\Entity
*/
class BeerAccess extends AbstractAccess
{
const SCOPE_BARTENDER = 'SCOPE_BEER_BARTENDER';
const SCOPE_CUSTOMER = 'SCOPE_BEER_CUSTOMER';
/**
* @var Beer
*
* @ORM\ManyToOne(targetEntity="...\Entity\Beer")
*/
protected $object;
/**
* @param User $user
* @param string $scope A Beer scope (constant)
* @param Beer $beer The Beer to be secured
*/
public function __construct(User $user, $scope, Beer $beer)
{
parent::__construct($user, $scope);
$this->object = $beer;
}
/**
* {@inheritdoc}
*
* @return AbstractContract
*/
public function getObject()
{
return $this->object;
}
}
<?php
// namespaces ...
/**
* Class AccessSchemaListener
*
* This listener is used with the Doctrine Schema Tool
* It fakes a simple integer doctrine column instead of an association:
*
* - it removes all association to each secured object in the sub access classes (BeerAccess, SodaAccess...)
* - it adds a mapping on the parent/root abstract class AbstractAccess
* - it adds an indexe on this emulated integer column
*/
class AccessSchemaListener
{
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
if ($classMetadata->rootEntityName === '...\\Entity\\Security\\AbstractAccess') {
if ($classMetadata->name === '...\\Entity\\Security\\AbstractAccess') {
// For the AbstractAccess:
// - fake a simple integer column on AbstractAccess::$object (that's why we need the protected object declaration)
$classMetadata->fieldMappings['object'] = [
'fieldName' => 'object',
'type' => 'integer',
'scale' => 0,
'length' => null,
'unique' => false,
'nullable' => false,
'precision' => 0,
'columnName' => 'object_id'
];
// - keep the existing SQL index used for the foreign key
if (!isset($classMetadata->table['indexes'])) {
$classMetadata->table['indexes'] = [];
}
$classMetadata->table['indexes']['IDX_1C52E62232D562B'] = ['columns' => ['object_id']];
} else {
// For the access subclasses: remove the association
unset($classMetadata->associationMappings['object']);
}
}
}
}
<?php
// namespace ...
/**
* Abstract class access
*
* Represent any access for a user on a resource
*
* @ORM\Entity(repositoryClass="...\Entity\Security\AccessRepository")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="object_type", type="string")
* @ORM\DiscriminatorMap({
* "...\Entity\BeerClass" = "...\Entity\Security\BeerAccess",
* "...\Entity\WaterClass" = "...\Entity\Security\WaterAccess",
* "...\Entity\SodaClass" = "...\Entity\Security\SodaAccess"
* })
*/
abstract class AbstractAccess implements AccessInterface
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var DateTime
*
* @ORM\Column(type="date")
* @Assert\NotNull()
* @Assert\Date()
*/
private $grantedAt;
/**
* @var string
*
* @ORM\Column(type="string")
* @Assert\NotNull()
*/
private $scope;
/**
* @var \...\UserBundle\Entity\User
*
* @ORM\ManyToOne(targetEntity="...\UserBundle\Entity\User")
*/
private $user;
/**
* @var object The secured object
*
* We do not map doctrine association here to the secured object
* because the single-table inheritance doesn't support different types for a relation
* Since we need to secure different object types (beer, vine, soda...) the association is defined in the sub classes
*
* Yet we need this property to avoid doctrine schema tool to throw some exception on the update command
* @see AccessSchemaListener which is an hack for the schema tool
*/
protected $object;
/**
* @param User $user
* @param string $scope
*/
public function __construct(User $user, $scope)
{
$this->user = $user;
$this->scope = $scope;
$this->grantedAt = new DateTime();
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return \DateTime
*/
public function getGrantedAt()
{
return $this->grantedAt;
}
/**
* @return string
*/
public function getScope()
{
return $this->scope;
}
/**
* @return \...\UserBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
}
以上是关于php 与学说的一对一关系的主要内容,如果未能解决你的问题,请参考以下文章