Генерировать Symfony2 из БД? - PullRequest
32 голосов
/ 12 июня 2011

Можно ли генерировать приборы из существующей БД в Symfony2 / Doctrine?Как я могу это сделать?

Пример:

Я определил 15 объектов, и мое приложение symfony2 работает.Теперь некоторые люди могут просматривать приложение, и с его помощью до сих пор было вставлено около 5000 строк.Теперь я хочу, чтобы материал был вставлен как фиксатор, но я не хочу делать это вручную.Как я могу генерировать их из БД?

Ответы [ 7 ]

8 голосов
/ 24 июня 2012

Нет прямого способа в Doctrine или Symfony2, но написание генератора кода для него (внутри или вне sf2) будет тривиальнымПросто потяните каждое свойство и сгенерируйте строку кода, чтобы установить каждое свойство, а затем поместите его в свой метод загрузки прибора.Пример:

<?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
4 голосов
/ 30 августа 2012

Насколько я понимаю, у вас есть две базы данных: первая уже находится в работе и заполнена 5000 строками, вторая - новая база данных, которую вы хотите использовать для нового тестирования и разработки. Это правильно ?

Если это так, я предлагаю вам создать в вашей тестовой среде два менеджера сущностей: первый будет «по умолчанию», который будет использоваться в вашем проекте (ваших контроллерах и т. Д.). Второй будет использоваться для подключения к вашей производственной базе данных. Здесь вы найдете информацию о том, как обращаться с менеджером нескольких лиц: http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html

Затем вы должны создать класс Fixture, который будет иметь доступ к вашему контейнеру. Здесь есть «как»: http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html#using-the-container-in-the-fixtures.

Используя контейнер, вы получите доступ к обоим менеджерам сущностей. И это «волшебство»: вам придется извлечь объект из производственной базы данных и сохранить его во втором менеджере сущностей, который вставит их в вашу тестовую базу данных.

Я обращаю ваше внимание на два момента:

  • Если между объектом существуют отношения, вам придется позаботиться об этих зависимостях: сторона владельца, перевернутая сторона, ...
  • Если у вас 5000 строк, позаботьтесь о памяти, которую будет использовать ваш скрипт. Другим решением может быть использование собственного sql для извлечения всех строк из производственной базы данных и вставки их в тестовую базу данных. Или сценарий SQL ...

У меня нет кода, чтобы предложить вам, но я надеюсь, что эта идея поможет вам.

3 голосов
/ 13 сентября 2012

Я предполагаю, что вы хотите использовать фикстуры (а не просто сбросить производственную или промежуточную базу данных в базу данных разработки), потому что а) ваша схема изменится, и дампы не будут работать, если вы обновите свой код, или б) вы этого не сделаете хочу сбросить базу данных отверстий, но хочу только расширить некоторые пользовательские приборы. Пример, который я могу привести: у вас есть 206 стран в вашей промежуточной базе данных, и пользователи добавляют города в эти страны; чтобы сохранить размеры небольшими, у вас есть только 5 стран в вашей базе данных разработки, однако вы хотите добавить города, которые пользователь добавил в эти 5 стран в промежуточной базе данных, в базу данных разработки

Единственное решение, которое я могу придумать, - это использовать упомянутый DoctrineFixturesBundle и несколько менеджеров сущностей.

Прежде всего вы должны настроить два соединения с базой данных и двух менеджеров сущностей в вашем 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: ~

Как вы можете видеть, оба менеджера сущностей отображают AcmeDemoBundle (в этом пакете я добавлю код для загрузки приборов). Если вторая база данных не находится на вашем компьютере разработки, вы можете просто сбросить SQL с другого компьютера на компьютер разработки. Это должно быть возможно, поскольку речь идет о 500 строках, а не о миллионах.

Что вы можете сделать дальше, это реализовать загрузчик фикстур, который использует сервисный контейнер для извлечения второго менеджера сущностей и использования Doctrine для запроса данных из второй базы данных и сохранения их в вашей базе данных разработки (диспетчер сущностей default) ):

<?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);
    }
}

Что я сделал в методе loadCountry, так это то, что я загружаю объекты из менеджера сущностей staging, добавляю ссылку на страну прибора (ту, которая уже существует в ваших текущих приборах) и сохраняю ее, используя default менеджер сущностей (ваша база данных разработки).

Источники:

1 голос
/ 06 апреля 2017

вы можете использовать https://github.com/Webonaute/DoctrineFixturesGeneratorBundle Это добавляет возможность генерировать приборы для одного объекта, используя такие команды, как

$ php bin/console doctrine:generate:fixture --entity=Blog:BlogPost --ids="12 534 124" --name="bug43" --order="1"

Или вы можете создать полный снимок

php app/console doctrine:generate:fixture --snapshot --overwrite
0 голосов
/ 10 мая 2016

AliceBundle может помочь вам в этом. Действительно, он позволяет загружать данные из файлов YAML (или массива PHP).

Например, вы можете определить свои приборы с помощью:

Nelmio\Entity\Group:
    group1:
        name: Admins
        owner: '@user1->id'

Или с такой же структурой в массиве PHP. Это намного проще, чем генерировать рабочий код PHP.

Также поддерживаются ссылки:

Nelmio\Entity\User:
    # ...

Nelmio\Entity\Group:
    group1:
        name: Admins
        owner: '@user1'
0 голосов
/ 08 июня 2012

Doctrine Fixtures полезны, потому что они позволяют вам создавать объекты и вставлять их в базу данных.Это особенно полезно, когда вам нужно создать ассоциации или, скажем, кодировать пароль с помощью одного из кодировщиков паролей.Если у вас уже есть данные в базе данных, вам не нужно выводить их из этого формата и превращать в код PHP, только чтобы этот код PHP вставил те же данные обратно в базу данных.Возможно, вы могли бы просто сделать дамп SQL и затем снова вставить их в вашу базу данных таким образом.

Использование осветителя имело бы больше смысла, если вы начинаете свой проект, но хотите использовать пользовательский ввод для его создания.Если в вашем конфигурационном файле был пользователь по умолчанию, вы можете прочитать его и вставить объект.

0 голосов
/ 14 июня 2011

В кулинарной книге doctrine_fixture в последнем примере вы можете увидеть, как получить контейнер службы в вашей сущности.

С помощью этого контейнера службы вы можете извлечь службу doctrine, а затем менеджера сущностей.С менеджером сущностей вы сможете получить все необходимые данные из вашей базы данных.

Надеюсь, это вам поможет!

...