在Symfony2中将Doctrine与静态YAML数据库一起使用

时间:2022-10-16 14:53:39

I am familiar with PHP, but only just learning Symfony2 and Doctrine. I am wondering what the best practice is for static data, as in data that is only ever updated when deploying a new version of the web application to production.

我熟悉PHP,但只是学习Symfony2和Doctrine。我想知道静态数据的最佳实践是什么,就像在将新版本的Web应用程序部署到生产环境时才更新的数据一样。

I would prefer to specify static data (not schemas) in YAML, because then modifying that data is easy for everyone, whether they know any PHP/Doctrine or not. I would like for non-developers to be able to add an achievement by modifying the .yml file. An example of a static YAML database that I would like to maintain is:

我更喜欢在YAML中指定静态数据(而不是模式),因为然后修改这些数据对每个人来说都很容易,无论他们是否知道任何PHP / Doctrine。我希望非开发人员能够通过修改.yml文件来添加成就。我想要维护的静态YAML数据库的示例是:

Achievements:
  Conservative:
    Difficulty: 2
    Description: >
      Description of Conservative Achievement.
  Dedicated:
    Difficulty: 3
    Description: >
      Description of Dedicated Achievement.
  Persistent:
    Difficulty: 2
    Description: > 
      Description of Persistent Achievement.

Now imagine I have an entity representing a User

现在假设我有一个代表用户的实体

// src/Paulpro/ExperimentingBundle/Entity/User.php
namespace Paulpro\ExperimentingBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;

class User {

    protected $name;
    protected $achievements;

    public function __construct(){
        // Collection of achievements as defined by achievements.yml
        // $this->achievements = new ArrayCollection();
    }

}

I want to use Doctrine as normal for Users, so that they are stored in the database and I want Users to be able to earn achievements. A user can have multiple of each achievement, so in my User entity I need some way to represent a collection of achievements with quantities. I do not want the achievements difficulties and descriptions to be stored in the database, only in the .yml file, unless there is a good reason to store the achievements themselves in the database and a good way to import the static data into the database as part of automatic deployment.

我想将Doctrine正常用于用户,以便它们存储在数据库中,我希望用户能够获得成就。用户可以拥有每个成就的多个,因此在我的用户实体中,我需要某种方式来表示具有数量的成就集合。我不希望将成就困难和描述存储在数据库中,仅存储在.yml文件中,除非有充分的理由将成就本身存储在数据库中,并且是将静态数据导入数据库的好方法。自动部署的一部分。

I have three main questions related to this problem:

我有三个与此问题相关的主要问题:

  • Is there a better way to do this, keeping in mind that I want non-developers to be able to add achievements easily and I will probably want to overwrite the achievements.yml file for different locales?

    有没有更好的方法来做到这一点,请记住,我希望非开发人员能够轻松地添加成就,我可能想要覆盖不同语言环境的achievement.yml文件?

  • Where in my Symfony2 bundle should I put the achievements.yml file(s)?

    在我的Symfony2包中应该放置achievement.yml文件?

  • How should I modify the User entity so that the resulting database can maintain quantities of achievements per user?

    我应该如何修改用户实体,以便生成的数据库可以维护每个用户的成就数量?

3 个解决方案

#1


3  

I do not want the achievements difficulties and descriptions to be stored in the database, only in the .yml file, unless there is a good reason to store the achievements themselves in the database and a good way to import the static data into the database as part of automatic deployment.

我不希望将成就困难和描述存储在数据库中,仅存储在.yml文件中,除非有充分的理由将成就本身存储在数据库中,并且是将静态数据导入数据库的好方法。自动部署的一部分。

A good reason: It will be easier to manage the relations between Users and Achievements.
A way to import the static data into the database: DoctrineFixturesBundle

一个很好的理由:管理用户和成就之间的关系会更容易。一种将静态数据导入数据库的方法:DoctrineFixturesBundle

1. Define your static configuration

The best way to do so, is to expose a semantic configuration.

最好的方法是公开语义配置。

In your case, you will have the following 2 files:

在您的情况下,您将拥有以下2个文件:

// src/Paulpro/ExperimentingBundle/DependencyExtension/Configuration.php

<?php

namespace Paulpro\ExperimentingBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
    /**
     * Defines the configuration tree for the bundle
     * 
     * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('paulpro_experimenting');

        $rootNode
            ->children()
                ->arrayNode('Achievements')->addDefaultsIfNotSet()
                    ->children()
                        ->arrayNode('Conservative')->addDefaultsIfNotSet()
                            ->children()
                                ->integerNode('Difficulty')->defaultValue(2)->end()
                                ->scalarNode('Description')->defaultValue('Description of Conservative Achievement.')->end()
                            ->end()
                        ->end()
                        ->arrayNode('Dedicated')->addDefaultsIfNotSet()
                            ->children()
                                ->integerNode('Difficulty')->defaultValue(3)->end()
                                ->scalarNode('Description')->defaultValue('Description of Dedicated Achievement.')->end()
                            ->end()
                        ->end()
                        ->arrayNode('Persistent')->addDefaultsIfNotSet()
                            ->children()
                                ->integerNode('Difficulty')->defaultValue(2)->end()
                                ->scalarNode('Description')->defaultValue('Description of Persistent Achievement.')->end()
                            ->end()
                        ->end();

        return $treeBuilder;
    }
}

and:

<?php

namespace Paulpro\ExperimentingBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class PaulproExperimentingExtension extends Extension
{
    /**
     * Load the configuration for the bundle
     * 
     * @param array $configs
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        foreach($config as $key => $value)
        {
            $container->setParameter('paulpro_experimenting.'.$key, $value);
        }
    }
}

Doing so, you will be able to have a better way to manage how your users are using the config. To see a sample of the default config result, you can use the command:

这样,您就可以更好地管理用户使用配置的方式。要查看默认配置结果的示例,可以使用以下命令:

php app/console config:dump-reference PaulProExperimentingBundle

That should result as following:

这应该如下:

Default configuration for "PaulProExperimentingBundle"
paulpro_experimenting:
    Achievements:
        Conservative:
            Difficulty:           2
            Description:          Description of Conservative Achievement.
        Dedicated:
            Difficulty:           3
            Description:          Description of Dedicated Achievement.
        Persistent:
            Difficulty:           2
            Description:          Description of Persistent Achievement.

This means your users can put this sample in the config.yml under the app\config folder and change it depending on their need. The only condition is that whatever information they put in this file has to be validate by the Configuration tree you have defined.

这意味着您的用户可以将此示例放在app \ config文件夹下的config.yml中,并根据需要进行更改。唯一的条件是它们放在此文件中的任何信息都必须由您定义的配置树进行验证。

2. Define your entities

Define the Achievement entity as it best fits your need. You could for example use:

定义成就实体,因为它最符合您的需求。你可以使用例如:

// src/Paulpro/ExperimentingBundle/Entity/Achievement.php
namespace Paulpro\ExperimentingBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;

class Achievement{

    protected $name;
    protected $difficulty;
    protected $description;    
    /**
     * @ManyToMany(targetEntity="User", mappedBy="achievements")
     * @JoinTable(name="users_achievements")
     **/
    private $users;

    public function __construct() {
        $this->users = new ArrayCollection();
    }

}

You will keep your User entity the way it is except you have to add the relation to Achievement:

您将保持用户实体的方式,除非您必须添加与Achievement的关系:

// src/Paulpro/ExperimentingBundle/Entity/User.php
namespace Paulpro\ExperimentingBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;

class User {

    protected $name;
    /**
     * @ManyToMany(targetEntity="Achivement", mappedBy="users")
     **/
    protected $achievements;

    public function __construct(){
        $this->achievements = new ArrayCollection();
    }

}

3. Fill up the database when deploying the app

This is the last step and it uses exclusively the DoctrineFixturesBundle.

这是最后一步,它只使用DoctrineFixturesBundle。

You will have to create the fixture for your Achivement entity:

您必须为Achivement实体创建夹具:

// src/Paulpro/ExperimentingBundle/DataFixtures/ORM/LoadAchivementData.php

<?php

namespace Paulpro\ExperimentingBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Paulpro\ExperimentingBundle\Entity\Achivement;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class LoadTypesData implements FixtureInterface, ContainerAwareInterface
{
    private $container;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    public function load(ObjectManager $manager)
    {
        foreach($this->container->getParameter('paulpro_experimenting.Achievements') as $key => $value)
        {
            $achivement = new Achivement();
            $achivement->setName($key);
            $achivement->setDifficulty($value['Difficulty']);
            $achivement->setDescription($value['Description']);

            $manager->persist($achivement);
        }
        $manager->flush();
    }
}

This fixture will go through the config for paulpro_experimenting.Achievements and load the defined Achievements from here.
Lastly, to load the data in the database, you will have to run the following command:

该夹具将通过paulpro_experimenting.Achievements的配置并从此处加载已定义的成就。最后,要在数据库中加载数据,您必须运行以下命令:

php app/console doctrine:fixtures:load

Et voila, you should now be able to add/remove achievements from your users.

此外,您现在应该能够添加/删除用户的成就。

#2


2  

First things first,

首先,

If you are concerned about what the achievement thing say or the language used, you can use the translator component. Basically what it does is to store your strings in translation files (YAML). So, where you want to add some string, say the achievement name you add some key achievement.name and the translator looks for the string for that key. You can have multiple translations and Symfony automatically picks the right one based on the locale of the client. The translator is built into the templates so there is nothing to add but you can use it as well anywhere on the framework.

如果您关注成就的内容或使用的语言,您可以使用翻译器组件。基本上它的作用是将您的字符串存储在翻译文件(YAML)中。所以,在你想要添加一些字符串的地方,比如成就名称你添加了一些关键的achievement.name,翻译器会查找该键的字符串。您可以拥有多个翻译,Symfony会根据客户端的区域设置自动选择正确的翻译。翻译器内置于模板中,因此无需添加任何内容,但您可以在框架的任何位置使用它。

If you want to get data from files (maybe you want not only the translation but also some structured data), there are some things you can do, you don't actually need Doctrine for this.

如果你想从文件中获取数据(也许你不仅需要翻译而且还需要一些结构化数据),你可以做一些事情,你实际上并不需要Doctrine。

1) Using config.ini

1)使用config.ini

On every Symfony2 project there is a fille called config.ini (on newer versions of the framework it changed to config.yaml) in the app/config/ directory. That file is where things like database configuration values are meant to be stored BUT you can add as many options as you want, just adding them to the file:

在每个Symfony2项目中,在app / config /目录中都有一个名为config.ini的文件(在更新为config.yaml的框架的较新版本上)。该文件是存储数据库配置值之类的内容,但您可以根据需要添加任意数量的选项,只需将它们添加到文件中:

[parameters]
database_driver="pdo_mysql" 
database_host="192.168.1.1"
...
secret="..."

my_param= "my value"

Getting those values is easy, from a controller just call:

从控制器调用获取这些值很容易:

$this->container->getParameter('my_param'); // returns "my value"

It might work for you, but depending on what kind of data you want to store (for ini files there is just key/value way to go, and for the newer versions using yaml files, I'm just not sure if the framework would parse a hierarchical structure for you (it might, give it a try)). Other thing to keep in mind is that if someone deletes a configuration value your system will come down (probably after the cache is manually cleared) and there is sensitive data (a.k.a. passwords) that we generally don't want everybody to know!

它可能适合您,但取决于您要存储的数据类型(对于ini文件,只有键/值方式,对于使用yaml文件的较新版本,我只是不确定框架是否会为您解析一个层次结构(它可能会尝试))。要记住的其他事项是,如果有人删除配置值,您的系统将会关闭(可能是在手动清除缓存之后)并且存在我们通常不希望每个人都知道的敏感数据(a.k.a.密码)!

2) Using YAML component of Symfony2

2)使用Symfony2的YAML组件

First create your YAML file in whatever way it makes sense to you, then place it somewhere on your server (maybe in "resources" or "config" dir?) Then, if you are on a controller, just write something like:

首先以任何对你有意义的方式创建你的YAML文件,然后将它放在服务器上的某个地方(可能在“资源”或“配置”目录中?)然后,如果你在控制器上,只需写下如下内容:

//This line goes at the begining of your file where all the *use*s are
use Symfony\Component\Yaml\Yaml;

$file = __DIR__.'/../Path/To/file.yml'; //case sensitive on Unix-like systems 
if(!file_exists($file)){
    throw new HttpException(404, "File not found.");
}
//This line does the magic
$index = Yaml::parse(file_get_contents($file));

//Now $index contain an associative array containing all your data.

And you're done! I've used this to load things like menus or generating new sections on a website without touching the code or the database, let your imagination fly!

而且你已经完成了!我用它来加载菜单或在网站上生成新的部分而不触及代码或数据库,让你的想象力飞翔!

You can create a console command that import data (from any source you can imagine) to your database and then use that command in some script as part of your deployment process, it's up to you decide if it's worth the effort.

您可以创建一个控制台命令,将数据(从您可以想象的任何来源)导入数据库,然后在某个脚本中使用该命令作为部署过程的一部分,由您决定是否值得付出努力。

Finally let's just talk about the entity relations thing.

最后,我们来谈谈实体关系的事情。

It's not all clear what you are trying to do, but there is no (clean/nice) way to add relationships between a Doctrine entity and a random configuration file. The problem is that they are meant to perform different roles in the app.

并不是很清楚你想要做什么,但是没有(干净/好的)方法来添加Doctrine实体和随机配置文件之间的关系。问题是它们意味着在应用程序中执行不同的角色。

I'd suggest you do something like this:

我建议你这样做:

  1. On your database:

    在您的数据库上:

    • Add a table "achievements" with an id and a column called nameKey and maybe descriptionKey ... These __Key columns will contain translator keys (as mentioned before). I.e:
    • 添加一个表“achievement”,其中包含一个id和一个名为nameKey的列,也许还有descriptionKey ...这些__Key列将包含翻译键(如前所述)。即:

    "ID":1, "nameKey":"achievement.1.name", "descriptionKey":"achievement.1.description" "ID":2, "nameKey":"achievement.2.name", "descriptionKey":"achievement.2.description" "ID":3, "nameKey":"achievement.3.name", "descriptionKey":"achievement.3.description"

    “ID”:1,“nameKey”:“achievement.1.name”,“descriptionKey”:“achievement.1.description”“ID”:2,“nameKey”:“achievement.2.name”,“descriptionKey” :“achievement.2.description”“ID”:3,“nameKey”:“achievement.3.name”,“descriptionKey”:“achievement.3.description”

    • Then modify your User so it links to the achievements table. Keeping this in your database will help you and enable you to use some other nice Symfony tools (like forms, validators, ...) and help you keep integrity in your data.
    • 然后修改您的用户,以便链接到成就表。将它保存在您的数据库中将帮助您并使您能够使用其他一些不错的Symfony工具(如表单,验证器......)并帮助您保持数据的完整性。

  2. Using translator

    • Create a translation file for each lang. you are interested, they will look like:
    • 为每个lang创建翻译文件。你有兴趣,他们会看起来像:

    achievement.1.name: "Best player ever" achievement.1.description: "Blah blah blah" achievement.2.name: "Better than average" achievement.2.description: "Blah blah blah"

    achievement.1.name:“有史以来最好的球员”成就.1。描述:“Blah blah blah blah”achievement.2.name:“胜过平均水平”成就.2。描述:“Blah blah blah blah”

just follow the documentation to see how to output your strings translated wherever you want to put them.

只需按照文档查看如何将字符串翻译到任何想要放置它们的位置。

To add new records you would need to add a record on the database (if you want to make it easier, just write a small web form for that) and the translation keys.

要添加新记录,您需要在数据库中添加记录(如果您想更轻松,只需为其编写一个小型Web表单)和翻译键。

Symfony is so powerful yet easy that will make you lazy and productive at the same time

Symfony非常强大而且容易让你在同一时间变得懒惰和富有成效

#3


1  

I would propose to use a class to represent your Achievements. I would also propose to use a relational database to store relations between Users and Achievements (logic :) ) I mean that I would prefer to store achievement in database. Using alice it's quite easy, and your yaml file has not that much to change.

我建议用一堂课代表你的成就。我还建议使用关系数据库来存储用户和成就之间的关系(逻辑:))我的意思是我更愿意将成就存储在数据库中。使用alice非常简单,你的yaml文件没有那么多改变。

It's a 2 steps process:

这是一个两步的过程:

  • modifiy yaml to fit alice needs
  • 修改yaml以适应爱丽丝的需要

  • create an Achievement entity and add relations between user and it
  • 创建一个Achievement实体并添加用户与它之间的关系

Achievement:
  Conservative:
    id: 1
    Difficulty: 2
    Description: >
      Description of Conservative Achievement.    
<?php

class Achievement
{
    public $id;
    public $difficulty;
    public $description;
}

Follow then the alice steps, and you have a working solution.

然后按照爱丽丝的步骤,你就有了一个有效的解决方案。

Another possibility is to simply store the Achievement keys as serialized array in your user entity:

另一种可能性是将Achievement键作为序列化数组存储在您的用户实体中:

<?php

class User
{
    /** @ORM\Column(type="array") **/
    protected $achievements = array();

    public function addAchievementByName($name)
    {
        $this->achievements[] = $name;
    }

    function getAchievements()
    {
        $self = $this;
        $allAchievements = Yaml::load(__DIR__.'/path/yo/yaml/file');
        return array_flip(array_filter(array_flip($allAchievements), function($achievement) use ($self) {
            return in_array($achievement, $self->achievements);
        }));
    }
}

#1


3  

I do not want the achievements difficulties and descriptions to be stored in the database, only in the .yml file, unless there is a good reason to store the achievements themselves in the database and a good way to import the static data into the database as part of automatic deployment.

我不希望将成就困难和描述存储在数据库中,仅存储在.yml文件中,除非有充分的理由将成就本身存储在数据库中,并且是将静态数据导入数据库的好方法。自动部署的一部分。

A good reason: It will be easier to manage the relations between Users and Achievements.
A way to import the static data into the database: DoctrineFixturesBundle

一个很好的理由:管理用户和成就之间的关系会更容易。一种将静态数据导入数据库的方法:DoctrineFixturesBundle

1. Define your static configuration

The best way to do so, is to expose a semantic configuration.

最好的方法是公开语义配置。

In your case, you will have the following 2 files:

在您的情况下,您将拥有以下2个文件:

// src/Paulpro/ExperimentingBundle/DependencyExtension/Configuration.php

<?php

namespace Paulpro\ExperimentingBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
    /**
     * Defines the configuration tree for the bundle
     * 
     * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('paulpro_experimenting');

        $rootNode
            ->children()
                ->arrayNode('Achievements')->addDefaultsIfNotSet()
                    ->children()
                        ->arrayNode('Conservative')->addDefaultsIfNotSet()
                            ->children()
                                ->integerNode('Difficulty')->defaultValue(2)->end()
                                ->scalarNode('Description')->defaultValue('Description of Conservative Achievement.')->end()
                            ->end()
                        ->end()
                        ->arrayNode('Dedicated')->addDefaultsIfNotSet()
                            ->children()
                                ->integerNode('Difficulty')->defaultValue(3)->end()
                                ->scalarNode('Description')->defaultValue('Description of Dedicated Achievement.')->end()
                            ->end()
                        ->end()
                        ->arrayNode('Persistent')->addDefaultsIfNotSet()
                            ->children()
                                ->integerNode('Difficulty')->defaultValue(2)->end()
                                ->scalarNode('Description')->defaultValue('Description of Persistent Achievement.')->end()
                            ->end()
                        ->end();

        return $treeBuilder;
    }
}

and:

<?php

namespace Paulpro\ExperimentingBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class PaulproExperimentingExtension extends Extension
{
    /**
     * Load the configuration for the bundle
     * 
     * @param array $configs
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        foreach($config as $key => $value)
        {
            $container->setParameter('paulpro_experimenting.'.$key, $value);
        }
    }
}

Doing so, you will be able to have a better way to manage how your users are using the config. To see a sample of the default config result, you can use the command:

这样,您就可以更好地管理用户使用配置的方式。要查看默认配置结果的示例,可以使用以下命令:

php app/console config:dump-reference PaulProExperimentingBundle

That should result as following:

这应该如下:

Default configuration for "PaulProExperimentingBundle"
paulpro_experimenting:
    Achievements:
        Conservative:
            Difficulty:           2
            Description:          Description of Conservative Achievement.
        Dedicated:
            Difficulty:           3
            Description:          Description of Dedicated Achievement.
        Persistent:
            Difficulty:           2
            Description:          Description of Persistent Achievement.

This means your users can put this sample in the config.yml under the app\config folder and change it depending on their need. The only condition is that whatever information they put in this file has to be validate by the Configuration tree you have defined.

这意味着您的用户可以将此示例放在app \ config文件夹下的config.yml中,并根据需要进行更改。唯一的条件是它们放在此文件中的任何信息都必须由您定义的配置树进行验证。

2. Define your entities

Define the Achievement entity as it best fits your need. You could for example use:

定义成就实体,因为它最符合您的需求。你可以使用例如:

// src/Paulpro/ExperimentingBundle/Entity/Achievement.php
namespace Paulpro\ExperimentingBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;

class Achievement{

    protected $name;
    protected $difficulty;
    protected $description;    
    /**
     * @ManyToMany(targetEntity="User", mappedBy="achievements")
     * @JoinTable(name="users_achievements")
     **/
    private $users;

    public function __construct() {
        $this->users = new ArrayCollection();
    }

}

You will keep your User entity the way it is except you have to add the relation to Achievement:

您将保持用户实体的方式,除非您必须添加与Achievement的关系:

// src/Paulpro/ExperimentingBundle/Entity/User.php
namespace Paulpro\ExperimentingBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;

class User {

    protected $name;
    /**
     * @ManyToMany(targetEntity="Achivement", mappedBy="users")
     **/
    protected $achievements;

    public function __construct(){
        $this->achievements = new ArrayCollection();
    }

}

3. Fill up the database when deploying the app

This is the last step and it uses exclusively the DoctrineFixturesBundle.

这是最后一步,它只使用DoctrineFixturesBundle。

You will have to create the fixture for your Achivement entity:

您必须为Achivement实体创建夹具:

// src/Paulpro/ExperimentingBundle/DataFixtures/ORM/LoadAchivementData.php

<?php

namespace Paulpro\ExperimentingBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Paulpro\ExperimentingBundle\Entity\Achivement;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class LoadTypesData implements FixtureInterface, ContainerAwareInterface
{
    private $container;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    public function load(ObjectManager $manager)
    {
        foreach($this->container->getParameter('paulpro_experimenting.Achievements') as $key => $value)
        {
            $achivement = new Achivement();
            $achivement->setName($key);
            $achivement->setDifficulty($value['Difficulty']);
            $achivement->setDescription($value['Description']);

            $manager->persist($achivement);
        }
        $manager->flush();
    }
}

This fixture will go through the config for paulpro_experimenting.Achievements and load the defined Achievements from here.
Lastly, to load the data in the database, you will have to run the following command:

该夹具将通过paulpro_experimenting.Achievements的配置并从此处加载已定义的成就。最后,要在数据库中加载数据,您必须运行以下命令:

php app/console doctrine:fixtures:load

Et voila, you should now be able to add/remove achievements from your users.

此外,您现在应该能够添加/删除用户的成就。

#2


2  

First things first,

首先,

If you are concerned about what the achievement thing say or the language used, you can use the translator component. Basically what it does is to store your strings in translation files (YAML). So, where you want to add some string, say the achievement name you add some key achievement.name and the translator looks for the string for that key. You can have multiple translations and Symfony automatically picks the right one based on the locale of the client. The translator is built into the templates so there is nothing to add but you can use it as well anywhere on the framework.

如果您关注成就的内容或使用的语言,您可以使用翻译器组件。基本上它的作用是将您的字符串存储在翻译文件(YAML)中。所以,在你想要添加一些字符串的地方,比如成就名称你添加了一些关键的achievement.name,翻译器会查找该键的字符串。您可以拥有多个翻译,Symfony会根据客户端的区域设置自动选择正确的翻译。翻译器内置于模板中,因此无需添加任何内容,但您可以在框架的任何位置使用它。

If you want to get data from files (maybe you want not only the translation but also some structured data), there are some things you can do, you don't actually need Doctrine for this.

如果你想从文件中获取数据(也许你不仅需要翻译而且还需要一些结构化数据),你可以做一些事情,你实际上并不需要Doctrine。

1) Using config.ini

1)使用config.ini

On every Symfony2 project there is a fille called config.ini (on newer versions of the framework it changed to config.yaml) in the app/config/ directory. That file is where things like database configuration values are meant to be stored BUT you can add as many options as you want, just adding them to the file:

在每个Symfony2项目中,在app / config /目录中都有一个名为config.ini的文件(在更新为config.yaml的框架的较新版本上)。该文件是存储数据库配置值之类的内容,但您可以根据需要添加任意数量的选项,只需将它们添加到文件中:

[parameters]
database_driver="pdo_mysql" 
database_host="192.168.1.1"
...
secret="..."

my_param= "my value"

Getting those values is easy, from a controller just call:

从控制器调用获取这些值很容易:

$this->container->getParameter('my_param'); // returns "my value"

It might work for you, but depending on what kind of data you want to store (for ini files there is just key/value way to go, and for the newer versions using yaml files, I'm just not sure if the framework would parse a hierarchical structure for you (it might, give it a try)). Other thing to keep in mind is that if someone deletes a configuration value your system will come down (probably after the cache is manually cleared) and there is sensitive data (a.k.a. passwords) that we generally don't want everybody to know!

它可能适合您,但取决于您要存储的数据类型(对于ini文件,只有键/值方式,对于使用yaml文件的较新版本,我只是不确定框架是否会为您解析一个层次结构(它可能会尝试))。要记住的其他事项是,如果有人删除配置值,您的系统将会关闭(可能是在手动清除缓存之后)并且存在我们通常不希望每个人都知道的敏感数据(a.k.a.密码)!

2) Using YAML component of Symfony2

2)使用Symfony2的YAML组件

First create your YAML file in whatever way it makes sense to you, then place it somewhere on your server (maybe in "resources" or "config" dir?) Then, if you are on a controller, just write something like:

首先以任何对你有意义的方式创建你的YAML文件,然后将它放在服务器上的某个地方(可能在“资源”或“配置”目录中?)然后,如果你在控制器上,只需写下如下内容:

//This line goes at the begining of your file where all the *use*s are
use Symfony\Component\Yaml\Yaml;

$file = __DIR__.'/../Path/To/file.yml'; //case sensitive on Unix-like systems 
if(!file_exists($file)){
    throw new HttpException(404, "File not found.");
}
//This line does the magic
$index = Yaml::parse(file_get_contents($file));

//Now $index contain an associative array containing all your data.

And you're done! I've used this to load things like menus or generating new sections on a website without touching the code or the database, let your imagination fly!

而且你已经完成了!我用它来加载菜单或在网站上生成新的部分而不触及代码或数据库,让你的想象力飞翔!

You can create a console command that import data (from any source you can imagine) to your database and then use that command in some script as part of your deployment process, it's up to you decide if it's worth the effort.

您可以创建一个控制台命令,将数据(从您可以想象的任何来源)导入数据库,然后在某个脚本中使用该命令作为部署过程的一部分,由您决定是否值得付出努力。

Finally let's just talk about the entity relations thing.

最后,我们来谈谈实体关系的事情。

It's not all clear what you are trying to do, but there is no (clean/nice) way to add relationships between a Doctrine entity and a random configuration file. The problem is that they are meant to perform different roles in the app.

并不是很清楚你想要做什么,但是没有(干净/好的)方法来添加Doctrine实体和随机配置文件之间的关系。问题是它们意味着在应用程序中执行不同的角色。

I'd suggest you do something like this:

我建议你这样做:

  1. On your database:

    在您的数据库上:

    • Add a table "achievements" with an id and a column called nameKey and maybe descriptionKey ... These __Key columns will contain translator keys (as mentioned before). I.e:
    • 添加一个表“achievement”,其中包含一个id和一个名为nameKey的列,也许还有descriptionKey ...这些__Key列将包含翻译键(如前所述)。即:

    "ID":1, "nameKey":"achievement.1.name", "descriptionKey":"achievement.1.description" "ID":2, "nameKey":"achievement.2.name", "descriptionKey":"achievement.2.description" "ID":3, "nameKey":"achievement.3.name", "descriptionKey":"achievement.3.description"

    “ID”:1,“nameKey”:“achievement.1.name”,“descriptionKey”:“achievement.1.description”“ID”:2,“nameKey”:“achievement.2.name”,“descriptionKey” :“achievement.2.description”“ID”:3,“nameKey”:“achievement.3.name”,“descriptionKey”:“achievement.3.description”

    • Then modify your User so it links to the achievements table. Keeping this in your database will help you and enable you to use some other nice Symfony tools (like forms, validators, ...) and help you keep integrity in your data.
    • 然后修改您的用户,以便链接到成就表。将它保存在您的数据库中将帮助您并使您能够使用其他一些不错的Symfony工具(如表单,验证器......)并帮助您保持数据的完整性。

  2. Using translator

    • Create a translation file for each lang. you are interested, they will look like:
    • 为每个lang创建翻译文件。你有兴趣,他们会看起来像:

    achievement.1.name: "Best player ever" achievement.1.description: "Blah blah blah" achievement.2.name: "Better than average" achievement.2.description: "Blah blah blah"

    achievement.1.name:“有史以来最好的球员”成就.1。描述:“Blah blah blah blah”achievement.2.name:“胜过平均水平”成就.2。描述:“Blah blah blah blah”

just follow the documentation to see how to output your strings translated wherever you want to put them.

只需按照文档查看如何将字符串翻译到任何想要放置它们的位置。

To add new records you would need to add a record on the database (if you want to make it easier, just write a small web form for that) and the translation keys.

要添加新记录,您需要在数据库中添加记录(如果您想更轻松,只需为其编写一个小型Web表单)和翻译键。

Symfony is so powerful yet easy that will make you lazy and productive at the same time

Symfony非常强大而且容易让你在同一时间变得懒惰和富有成效

#3


1  

I would propose to use a class to represent your Achievements. I would also propose to use a relational database to store relations between Users and Achievements (logic :) ) I mean that I would prefer to store achievement in database. Using alice it's quite easy, and your yaml file has not that much to change.

我建议用一堂课代表你的成就。我还建议使用关系数据库来存储用户和成就之间的关系(逻辑:))我的意思是我更愿意将成就存储在数据库中。使用alice非常简单,你的yaml文件没有那么多改变。

It's a 2 steps process:

这是一个两步的过程:

  • modifiy yaml to fit alice needs
  • 修改yaml以适应爱丽丝的需要

  • create an Achievement entity and add relations between user and it
  • 创建一个Achievement实体并添加用户与它之间的关系

Achievement:
  Conservative:
    id: 1
    Difficulty: 2
    Description: >
      Description of Conservative Achievement.    
<?php

class Achievement
{
    public $id;
    public $difficulty;
    public $description;
}

Follow then the alice steps, and you have a working solution.

然后按照爱丽丝的步骤,你就有了一个有效的解决方案。

Another possibility is to simply store the Achievement keys as serialized array in your user entity:

另一种可能性是将Achievement键作为序列化数组存储在您的用户实体中:

<?php

class User
{
    /** @ORM\Column(type="array") **/
    protected $achievements = array();

    public function addAchievementByName($name)
    {
        $this->achievements[] = $name;
    }

    function getAchievements()
    {
        $self = $this;
        $allAchievements = Yaml::load(__DIR__.'/path/yo/yaml/file');
        return array_flip(array_filter(array_flip($allAchievements), function($achievement) use ($self) {
            return in_array($achievement, $self->achievements);
        }));
    }
}