use*_*531 7 php attributes doctrine symfony doctrine-orm
如何在父类中定义 Doctrine 属性并覆盖扩展父类的类中的关联?当使用注释时,这是通过使用AssociationOverride实现的,但是,我认为它们在使用 PHP 8 属性时不可用
为什么我想:
我有一个类,AbstractTenantEntity其目的是将数据访问限制为Tenant拥有数据的给定(即帐户、所有者等),并且扩展该类的任何实体将tenant_id在创建时插入到数据库中,并且所有其他请求将添加tenant_id到 WHERE 子句。 Tenant通常没有扩展的各种实体的集合AbstractTenantEntity,但有一些有。当使用注释时,我通过将 Doctrine 的AssociationOverride注释应用到扩展类来处理它,这些扩展类应该在 中具有集合Tenant,但我不知道在使用 PHP 8 属性时如何实现这一点?
下面描述的我的尝试是不成功的,因为我错误地认为如果进行适当的修改,注释类将神奇地与属性一起工作,但现在我看到其他代码必须能够基于属性应用适当的逻辑。因此,我放弃了这种方法,只是将属性保护起来并在具体类中复制它们。
我的尝试:
租户实体
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
#[Entity()]
class Tenant
{
#[Id, Column(type: "integer")]
#[GeneratedValue]
private ?int $id = null;
#[OneToMany(targetEntity: Asset::class, mappedBy: 'tenant')]
private array|Collection|ArrayCollection $assets;
// Other properties and typical getters and setters
}
Run Code Online (Sandbox Code Playgroud)
AbstractTenantEntity 实体
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\JoinColumn;
abstract class AbstractTenantEntity implements TenantInterface
{
/**
* inversedBy performed in child where required
*/
#[ManyToOne(targetEntity: Tenant::class)]
#[JoinColumn(nullable: false)]
protected ?Tenant $tenant = null;
// Typical getters and setters
}
Run Code Online (Sandbox Code Playgroud)
这是让我陷入困境的部分。当使用注释时,我的代码如下:
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\AssociationOverrides({
* @ORM\AssociationOverride(name="tenant", inversedBy="assets")
* })
*/
class Asset extends AbstractTenantEntity
{
// Various properties and typical getters and setters
}
Run Code Online (Sandbox Code Playgroud)
但AssociationOverrides尚未修改为使用属性,因此基于官方类,我创建了自己的类,类似于 Doctrine 更新的其他类:
namespace App\Mapping;
use Attribute;
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
use Doctrine\ORM\Mapping\Annotation;
/**
* This annotation is used to override association mapping of property for an entity relationship.
*
* @Annotation
* @NamedArgumentConstructor()
* @Target("ANNOTATION")
*/
#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]
final class AssociationOverride implements Annotation
{
/**
* The name of the relationship property whose mapping is being overridden.
*
* @var string
*/
public $name;
/**
* The join column that is being mapped to the persistent attribute.
*
* @var array<\Doctrine\ORM\Mapping\JoinColumn>
*/
public $joinColumns;
/**
* The join table that maps the relationship.
*
* @var \Doctrine\ORM\Mapping\JoinTable
*/
public $joinTable;
/**
* The name of the association-field on the inverse-side.
*
* @var string
*/
public $inversedBy;
/**
* The fetching strategy to use for the association.
*
* @var string
* @Enum({"LAZY", "EAGER", "EXTRA_LAZY"})
*/
public $fetch;
public function __construct(
?string $name = null,
?array $joinColumns = null,
?string $joinTable = null,
?string $inversedBy = null,
?string $fetch = null
) {
$this->name = $name;
$this->joinColumns = $joinColumns;
$this->joinTable = $joinTable;
$this->inversedBy = $inversedBy;
$this->fetch = $fetch;
//$this->debug('__construct',);
}
private function debug(string $message, string $file='test.json', ?int $options = null)
{
$content = file_exists($file)?json_decode(file_get_contents($file), true):[];
$content[] = ['message'=>$message, 'object_vars'=>get_object_vars($this), 'debug_backtrace'=>debug_backtrace($options)];
file_put_contents($file, json_encode($content, JSON_PRETTY_PRINT));
}
}
Run Code Online (Sandbox Code Playgroud)
在验证映射时,Doctrine 抱怨 target-entity 不包含所需的inversedBy. 我花了一些时间浏览 Doctrine 源代码,但没有取得太大进展。
我目前的方法是否有优点,如果有,请填补空白。但是,如果没有,您建议如何满足这一需求?
小智 2
此pr已解决: https: //github.com/doctrine/orm/pull/9241
ps:需要 PHP 8.1
#[AttributeOverrides([
new AttributeOverride(
name: "id",
column: new Column(name: "guest_id", type: "integer", length: 140)
),
new AttributeOverride(
name: "name",
column: new Column(name: "guest_name", nullable: false, unique: true, length: 240)
)]
)]
Run Code Online (Sandbox Code Playgroud)