[英]Configurable dynamic Doctrine database entities in Symfony 2
I have been researching this for the past few days without much success but I stumbled across this answer which seems quite related to what I am trying to achieve. 过去几天我一直在研究这个问题而没有太大的成功,但我偶然发现了这个与我想要达到的目标非常相关的答案 。
I have registered and added the loadClassMetadata listener which maps the field foo : 我已注册并添加了loadClassMetadata侦听器,该侦听器映射字段foo :
// src/DynamicMappingTest/AdminBundle/EventListener/MappingListener.php
namespace DynamicMappingTest\AdminBundle\EventListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
class MappingListener
{
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
$classMetadata = $eventArgs->getClassMetadata();
if ($classMetadata->getName() != 'DynamicMappingTest\\AdminBundle\\Entity\\CustomNode')
{
// Not the CustomNode test class. Do not alter the class metadata.
return;
}
$table = $classMetadata->table;
$oldName = $table['name']; // ... or $classMetaData->getTableName()
// your logic here ...
$table['name'] = 'custom_node';
$classMetadata->setPrimaryTable($table);
$reflClass = $classMetadata->getReflectionClass();
dump($reflClass);
// ... or add a field-mapping like this
$fieldMapping = array(
'fieldName' => 'foo',
'type' => 'string',
'length' => 255
);
$classMetadata->mapField($fieldMapping);
}
}
Now, this all works as long as I have the foo property declared in the DynamicMappingTest\\AdminBundle\\Entity\\CustomNode class: 现在,只要我在DynamicMappingTest \\ AdminBundle \\ Entity \\ CustomNode类中声明了foo属性,这一切都有效:
// src/DynamicMappingTest/AdminBundle/Entity/CustomNode.php
namespace DynamicMappingTest\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* CustomNode
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="DynamicMappingTest\AdminBundle\Entity\CustomNodeRepository")
*/
class CustomNode
{
...
private $foo;
}
However, there is no way for me to know what properties the users will define for their custom entities. 但是,我无法知道用户将为其自定义实体定义哪些属性。 If I remove the foo property from the CustomNode class, the ReflectionClass that I get from the ClassMetadata will naturally not include the foo property and so I get the following exception whenever the mapField() in MappingListener is executed:
如果我删除从CustomNode类foo的属性,则ReflectionClass,我从了ClassMetadata得到自然不会包括foo的财产,所以我得到每当执行在MappingListener的MapField可()以下异常:
ReflectionException: Property DynamicMappingTest\AdminBundle\Entity\CustomNode::$foo does not exist
in vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php at line 80
77. */
78. public function getAccessibleProperty($class, $property)
79. {
80. $reflectionProperty = new ReflectionProperty($class, $property);
81.
82. if ($reflectionProperty->isPublic()) {
83. $reflectionProperty = new RuntimePublicReflectionProperty($class, $property);
Doctrine generates proxy classes for you entities. Doctrine为您的实体生成代理类。 That means that doctrine generates PHP code with class, which extends your Entity class and overrides the methods - puts some custom logic and then calls the parent method.
这意味着doctrine生成带有类的PHP代码,它扩展了您的Entity类并覆盖了方法 - 放置一些自定义逻辑然后调用父方法。
So, I think that the only way to make this really happen is to generate the PHP code for entities in your code. 因此,我认为实现这一目标的唯一方法是为代码中的实体生成PHP代码。 That is, every time entity is created in your website, you should generate PHP file with that entity, then run migrations.
也就是说,每次在您的网站中创建实体时,您应该使用该实体生成PHP文件,然后运行迁移。
I don't think that you should use Doctrine ORM at all in this case, at least in the way you're trying to do that. 在这种情况下,我认为你根本不应该使用Doctrine ORM,至少在你尝试这样做的方式。
Generally, ORM is used for easier/more manageable programming. 通常,ORM用于更容易/更易于管理的编程。 That is, you can set relations, use lazy-loading, unit of work (change entity properties and then just flush) etc. If your entities are generated dynamically, what features will you use at all?
也就是说,您可以设置关系,使用延迟加载,工作单元(更改实体属性,然后只刷新)等。如果您的实体是动态生成的,那么您将使用哪些功能? Developer will not write code for these entities, because, as you've said, there is no way to know what fields it will have.
开发人员不会为这些实体编写代码,因为正如您所说,无法知道它将具有哪些字段。
You haven't provided concrete use-case - why do you want to do that in the first place. 你还没有提供具体的用例 - 你为什么要这样做呢? But I imagine that it could be really done in some easier way.
但我想它可以通过一些更简单的方式完成。
If users can store any structure at all, should you use MySQL at all? 如果用户可以存储任何结构,你应该使用MySQL吗? ElasticSearch or similar solutions could be really much better in such cases.
在这种情况下,ElasticSearch或类似解决方案可能会更好。
As I've mentioned - yes. 正如我所说 - 是的。 Unless you would want to override or replace some of Doctrine code, but I imagine it could be lots of it (proxy classes etc.)
除非你想覆盖或替换一些Doctrine代码,但我想它可能是很多(代理类等)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.