32 votes

Appareils Symfony2 de DB?

Est-il possible de générer des fixtures à partir d'une base de données existante dans Symfony2 / Doctrine? Comment pourrais-je faire ça?

Exemple:

J'ai défini 15 entités et mon application symfony2 fonctionne. Maintenant, certaines personnes peuvent accéder à l'application et en l'utilisant, elle avait inséré environ 5000 lignes jusqu'à présent. Maintenant, je veux que les trucs soient insérés en tant que luminaires, mais je ne veux pas le faire à la main. Comment puis-je les générer à partir de la base de données?

8voto

Lusitanian Points 6910

Il n'y a pas de manière directe dans Doctrine ou Symfony2, mais écrire un générateur de code pour cela (à l'intérieur ou à l'extérieur de sf2) serait trivial. Tirez simplement chaque propriété et générez une ligne de code pour définir chaque propriété, puis placez-la dans votre méthode de chargement des appareils. Exemple:

 <?php
$i = 0;
$entities = $em->getRepository('MyApp:Entity')->findAll();
foreach($entities as $entity)
{
   $code .= "$entity_{$i} = new MyApp\Entity();\n";
   $code .= "$entity_{$i}->setMyProperty('" . addslashes($entity->getMyProperty()); . "'); \n");
   $code .= "$manager->persist($entity_{$i}); \n $manager->flush();";
   ++$i;
}
// store code somewhere with file_put_contents
 

4voto

Julien Fastré Points 177

Comme je comprends votre question, vous avez deux bases de données: la première est déjà en production et rempli de 5000 lignes, la seconde est une nouvelle base de données que vous souhaitez utiliser pour de nouveaux test et de développement. Est ce que le droit ?

Si elle l'est, je vous suggère de créer en vous un environnement de test de deux entité gestionnaire: le premier sera le "par défaut", qui sera utilisé dans votre projet (votre contrôleurs, etc.). Le second sera utilisé pour se connecter à votre base de données de production. Vous trouverez ici comment faire face à de multiples gestionnaire d'entité : http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html

Ensuite, vous devez créer un Luminaire de classe qui auront accès à votre conteneur. Il y a un "comment" ici : http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html#using-the-container-in-the-fixtures.

En utilisant le conteneur, vous aurez accès à la fois gestionnaire d'entités. Et c'est la "magie": vous aurez pour récupérer l'objet à partir de votre base de données de production, et de les conserver dans la seconde entité gestionnaire, ce qui permettra de les insérer dans votre base de données de test.

Je attirer votre attention sur deux points:

  • Si il y a relation entre l'objet, vous aurez à prendre soin de ces dépendances: propriétaire de côté, inversé côté, ...
  • Si vous avez 5000 lignes, prendre soin sur la mémoire de votre script à utiliser. Une autre solution peut être d'utiliser natif sql pour récupérer toutes les lignes de votre base de données de production et les insérer dans votre base de données de test. Ou un script SQL...

Je n'ai pas de code à suggérer pour vous, mais j'espère que cette idée va vous aider.

3voto

Je suppose que vous voulez utiliser luminaires (et pas seulement de vidage de la production ou de la mise en scène de la base de données dans la base de données de développement) a) parce que vos modifications de schéma et les décharges ne fonctionnerait pas si vous mettez à jour votre code ou b) vous ne voulez pas vider le trou de la base de données mais qui ne veulent étendre certaines installations personnalisées. Un exemple est, je pense: vous avez 206 pays dans votre mise en scène de la base de données et les utilisateurs d'ajouter des villes de ces pays, afin de conserver les appareils petits, vous ne disposez que de 5 pays dans le développement de votre base de données, toutefois, vous souhaitez ajouter des villes que l'utilisateur ajoute à ces 5 pays dans la mise en scène de la base de données pour le développement de la base de données

La seule solution que je vois est d'utiliser le mentionné DoctrineFixturesBundle et plusieurs gestionnaires d'entités.

Tout d'abord, vous devez configurer deux connexions de base de données et de deux gestionnaires de l'entité dans votre config.yml

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:   %database_driver%
                host:     %database_host%
                port:     %database_port%
                dbname:   %database_name%
                user:     %database_user%
                password: %database_password%
                charset:  UTF8
            staging:
                ...

    orm:
        auto_generate_proxy_classes: %kernel.debug%
        default_entity_manager:   default
        entity_managers:
            default:
                connection:       default
                mappings:
                    AcmeDemoBundle: ~
            staging:
                connection:       staging
                mappings:
                    AcmeDemoBundle: ~

Comme vous pouvez le voir à la fois les gestionnaires de l'entité de la carte le AcmeDemoBundle (dans ce bundle, je vais mettre le code pour charger les appareils). Si la deuxième base de données n'est pas sur votre machine de développement, vous avez juste à vider le SQL à partir de l'autre machine pour la machine de développement. Cela devrait être possible puisque nous parlons de 500 lignes et non sur des millions de lignes.

Ce que vous pouvez faire est de mettre en œuvre un dispositif de fixation, chargeur qui utilise le service de conteneur pour récupérer la seconde entité gestionnaire et de la Doctrine de l'usage pour interroger les données de la deuxième base de données et l'enregistrer dans votre base de données de développement (l' default gestionnaire d'entité):

<?php

namespace Acme\DemoBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Acme\DemoBundle\Entity\City;
use Acme\DemoBundle\Entity\Country;

class LoadData implements FixtureInterface, ContainerAwareInterface
{
    private $container;
    private $stagingManager;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
        $this->stagingManager = $this->container->get('doctrine')->getManager('staging');
    }

    public function load(ObjectManager $manager)
    {
        $this->loadCountry($manager, 'Austria');
        $this->loadCountry($manager, 'Germany');
        $this->loadCountry($manager, 'France');
        $this->loadCountry($manager, 'Spain');
        $this->loadCountry($manager, 'Great Britain');
        $manager->flush();
    }

    protected function loadCountry(ObjectManager $manager, $countryName)
    {
        $country = new Country($countryName);
        $cities = $this->stagingManager->createQueryBuilder()
            ->select('c')
            ->from('AcmeDemoBundle:City', 'c')
            ->leftJoin('c.country', 'co')
            ->where('co.name = :country')
            ->setParameter('country', $countryName)
            ->getQuery()
            ->getResult();
        foreach ($cities as $city) {
            $city->setCountry($country);
            $manager->persist($city);
        }
        $manager->persist($country);
    }
}

Ce que j'ai fait dans l' loadCountry méthode a été que j'ai charger les objets de la staging gestionnaire d'entités, ajouter une référence à l'appareil de pays (celui qui existe déjà dans votre accessoires) et persistent à l'aide de l' default gestionnaire d'entité (le développement de votre base de données).

Sources:

0voto

Isometriks Points 9

La Doctrine appareils sont utiles car ils vous permettent de créer des objets et de les insérer dans la base de données. Ceci est particulièrement utile lorsque vous avez besoin de créer des associations ou dire, d'encoder un mot de passe à l'aide de l'un des mot de passe des encodeurs. Si vous avez déjà les données dans une base de données, vous ne devriez pas vraiment besoin de sortir de ce format et de le transformer en code PHP, pour que le code PHP à insérer les mêmes données dans la base de données. Vous pourriez probablement juste de faire un dump SQL et puis réinsérez-les dans votre base de données de nouveau de cette façon.

À l'aide d'un luminaire aurait plus de sens si vous avez été de commencer votre projet mais je voulais utiliser la saisie de l'utilisateur à créer. Si vous aviez dans votre fichier de configuration par défaut de l'utilisateur, vous avez pu lire ça et l'insertion de l'objet.

-1voto

J'ai écrit un bundle pour transformer les données de la base de données existante en appareils de données.

Vous pouvez le trouver ici sur GitHub

J'espère que cela vous aidera!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X