捆绑包如何提供“默认数据”,即Symfony 2中的预填表?

时间:2014-09-06 21:32:17

标签: symfony doctrine-orm bundle

我认为我对Symfony以及捆绑的工作方式有很好的理解。

但是我从来没有找到如何解决一个简单的问题:制作一个可重复使用的捆绑包,提供数据,如表格/学说实体预先填充(即)世界上所有国家/地区名称,意大利所有省份,税率历史在英格兰等等。

当然,目的是提供依赖于此数据源的表单,服务和控制器,而无需跨项目复制和粘贴表和实体。

你会怎么做?

数据夹具IMHO不是一个选项,因为一个明显的原因:您将在数据库运行时清除它。

从静态数据源(json,YAML)读取并执行插入/更新的自定义命令?

4 个答案:

答案 0 :(得分:7)

第一步是在Bundle中声明一个Doctrine实体。我认为您应该创建DataFixtures以将数据填充到db中。

您可能应该考虑使用Seeds而不是Fixtures。

灯具是假数据,用于测试您的应用

种子是应用程序工作所需的最小数据。

从技术上讲,这些是完全相同的,你在“DataFixtures /”文件夹下声明它,然后使用“doctrine:fixtures:load”命令导入它们。

您可以在“DataFixtures”文件夹下创建文件夹“Fixtures /”和文件夹“Seeds /”,然后使用命令加载种子

php app/console doctrine:fixtures:load --fixtures=/path/to/seeds/folder --append

在评论中建议,创建自定义Symfony2命令以强制“--append”模式可能更安全,尤其是在生产环境中。如果没有此模式,您的数据库将被清除,您可能会丢失生产数据。

答案 1 :(得分:1)

这个答案假设你使用作曲家来安装你的软件包(你真的将灯具作为一个选项排除)。

您可以做的是对所需数据进行SQL导出,并确保它使用INSERT IGNORE INTO,并获得正确的唯一约束。

然后将该文件保存在捆绑包中的某个位置,并保存在"数据"或"灯具"夹。 所以你的文件路径将是: "供应商/公司/ epicbundle /数据/ countries.sql"

然后你可以做的是在composer.json中添加post-insert和post-update命令,如下所示:

"post-install-cmd": [
    "php app/console doctrine:query:sql \"$(cat vendor/company/epicbundle/data/countries.sql)\""
]

如果你只想让它在安装时运行,你只需要在那里添加它,如果你有时更新sql文件,你也可以将它添加到post-update-cmd。

请注意,此解决方案仅适用于人们不喜欢表名的情况,否则查询将失败。

如果你想要一个更加节省/稳定的解决方案,你可以在使用实体管理器的Symfony中编写自己的安装后脚本,在那里你可以使用,例如,一个csv文件,然后插入/更新它行。

答案 2 :(得分:1)

基本上,你可以实现的任何东西肯定都依赖于你的ORM / ODM /中使用的持久性机制。因此,您最终将实现典型的夹具加载机制,至少部分是:您将执行保存一些提供的数据的代码;如果它是序列化的,你可以进行XML / JSON / YAML解析(但这只是一个技术性问题)并将结果保存到数据库中。

因此,坚持使用Doctrine Fixtures并不坏。它们是可编程和可扩展的(您甚至可以在加载时从Web上获取数据)。

如@ paul-andrieux的回答所述,如果您担心数据丢失(例如,当最终用户的数据库已经启动时,您的数据包的种子已加载),您应该使用doctrine:fixtures:load --append并让约束执行他们的操作job(比如,在国家/地区名称表中,您对国家/地区名称有一个独特的约束,甚至是'slug'),以便无意中插入重复的行无法插入单个实体,以防您的包已更新国家/地区列表,以及最终用户有一个以前的版本。

如果您真的担心最终用户的数据,您可以编写doctrine:fixtures:load命令的包装器,该命令始终打开--append标志并将其注册为单独的命令。 (你也可以在那里运行所需的迁移)

@ lxg的硬编码ID问题也是可以解决的。尝试在适用的情况下使用natural keys(例如,countries表格中将有一个slug主键,对于Grean Britain来说是great-britain。这样您的搜索就会非常简单:$em->find('\MyBundle\Country', 'great-britain');。如果你不能提出一个自然键,那么最终用户可能并不真正需要该实体。

UPD。这是一篇可能有用的文章:http://www.craftitonline.com/2014/09/doctrine-migrations-with-schema-api-without-symfony-symfony-cmf-seobundle-sylius-example/

答案 3 :(得分:0)

一般来说,捆绑包嵌入了将通过ORM / ODM使用其内置命令(如doctrine:schema:updatedoctrine:migration:diff,...)加载的实体,并提供自定义命令使用ODM / ORM

加载所需的灯具

这个命令可以多种方式读取灯具(解析yaml,xml,raw sql,dql,...),这只是一个品味问题。这些任务存在捆绑,解析器......的音调。

在您的文档中,您必须明确说明开发人员必须在捆绑软件安装和架构更新后运行此命令。