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.
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
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:
// 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.
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:
// 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.
You will have to create the fixture for your Achivement entity:
// 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:
php app/console doctrine:fixtures:load
Et voila, you should now be able to add/remove achievements from your users.