doctrine2 - seeder - Generar accesorios Symfony2 de DB?
symfony load data fixture (7)
En el libro de cocina doctrine_fixture, puede ver en el último ejemplo cómo obtener el contenedor de servicio en su entidad.
Con este contenedor de servicios, puede recuperar el servicio de doctrina, luego el administrador de entidades. Con el administrador de la entidad, podrá obtener todos los datos de la base de datos que necesita.
¡Espero que esto te ayudará!
¿Es posible generar fixtures desde un DB existente en Symfony2 / Doctrine? ¿Cómo podría hacer eso?
Ejemplo:
He definido 15 entidades y mi aplicación symfony2 está funcionando. Ahora algunas personas pueden navegar a la aplicación y al usarla había insertado unas 5000 filas hasta ahora. Ahora quiero que las cosas se inserten como accesorios, pero no quiero hacerlo a mano. ¿Cómo puedo generarlos desde el DB?
Los accesorios Doctrine son útiles porque te permiten crear objetos e insertarlos en la base de datos. Esto es especialmente útil cuando necesita crear asociaciones o decir, codificar una contraseña usando uno de los codificadores de contraseña. Si ya tiene los datos en una base de datos, no debería realmente sacarlos de ese formato y convertirlos en código PHP, solo para que ese código PHP inserte los mismos datos en la base de datos. Probablemente puedas simplemente hacer un volcado de SQL y luego volver a insertarlos en tu base de datos de esa manera.
Usar un accesorio tendría más sentido si estuviera iniciando su proyecto pero quería usar la entrada del usuario para crearlo. Si tenía en su archivo de configuración el usuario predeterminado, podría leerlo e insertar el objeto.
No hay una manera directa en Doctrine o Symfony2, pero escribir un generador de código para él (ya sea dentro o fuera de sf2) sería trivial. Simplemente extraiga cada propiedad y genere una línea de código para establecer cada propiedad, luego colóquela en su método de carga de dispositivos. Ejemplo:
<?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
Según entiendo su pregunta, tiene dos bases de datos: la primera ya está en producción y llena con 5000 filas, la segunda es una nueva base de datos que desea usar para nuevas pruebas y desarrollo. Está bien ?
Si es así, le sugiero que cree en su entorno de prueba dos administradores de entidades: el primero será el ''predeterminado'', que se usará en su proyecto (sus controladores, etc.). El segundo se usará para conectarse a su base de datos de producción. Aquí encontrará cómo tratar con el administrador de múltiples entidades: http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html
Luego, debe crear una clase de Aparato que tendrá acceso a su contenedor. Hay un "cómo hacerlo" aquí: http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html#using-the-container-in-the-fixtures .
Usando el contenedor, tendrás acceso a ambos administrador de entidades. Y esta es la ''magia'': tendrá que recuperar el objeto de su base de datos de producción y conservarlo en el segundo administrador de entidades, que lo insertará en su base de datos de prueba.
Señalo tu atención a dos puntos:
- Si hay relación entre objeto, deberás cuidar esas dependencias: lado del propietario, lado invertido, ...
- Si tiene 5000 filas, tenga cuidado con la memoria que usará su script. Otra solución puede ser el uso de sql nativo para recuperar todas las filas de su base de datos de producción e insertarlas en su base de datos de prueba. O una secuencia de comandos SQL ...
No tengo ningún código para sugerirte, pero espero que esta idea te ayude.
Supongo que desea utilizar dispositivos (y no solo volcar la base de datos de producción o de ensayo en la base de datos de desarrollo) porque a) su esquema cambia y los volcados no funcionarían si actualiza su código ob) no desea volcar la base de datos de agujeros, pero solo desea extender algunos accesorios personalizados. Un ejemplo en el que puedo pensar es: usted tiene 206 países en su base de datos de etapas y los usuarios agregan ciudades a esos países; para mantener los dispositivos pequeños, solo tienes 5 países en tu base de datos de desarrollo, sin embargo, deseas agregar las ciudades que el usuario agregó a esos 5 países en la base de datos provisional a la base de datos de desarrollo.
La única solución en la que puedo pensar es usar el DoctrineFixturesBundle mencionado y múltiples administradores de entidades.
En primer lugar, debe configurar dos conexiones de base de datos y dos administradores de entidades en su 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: ~
Como puede ver, ambos administradores de entidades mapean el AcmeDemoBundle (en este paquete pondré el código para cargar los dispositivos). Si la segunda base de datos no está en su máquina de desarrollo, puede simplemente volcar el SQL de la otra máquina a la máquina de desarrollo. Eso debería ser posible ya que estamos hablando de 500 filas y no de millones de filas.
Lo que puede hacer a continuación es implementar un cargador de dispositivos que use el contenedor de servicios para recuperar el segundo administrador de entidades y usar Doctrine para consultar los datos de la segunda base de datos y guardarlos en su base de datos de desarrollo (el default
entidades 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);
}
}
Lo que hice en el método loadCountry
fue que loadCountry
los objetos del gestor de entidades de staging
, agregué una referencia al país del dispositivo (el que ya existe en tus dispositivos actuales) y lo mantuve usando el default
entidades default
(tu base de datos de desarrollo) .
Fuentes:
podrías usar https://github.com/Webonaute/DoctrineFixturesGeneratorBundle Añade la habilidad de generar aparatos para una sola entidad usando comandos como
$ php bin/console doctrine:generate:fixture --entity=Blog:BlogPost --ids="12 534 124" --name="bug43" --order="1"
O puede crear una instantánea completa
php app/console doctrine:generate:fixture --snapshot --overwrite
AliceBundle puede ayudarte a hacer esto. De hecho, permite cargar dispositivos con archivos YAML (o PHP Array).
Por ejemplo, puedes definir tus accesorios con:
Nelmio/Entity/Group:
group1:
name: Admins
owner: ''@user1->id''
O con la misma estructura en una matriz de PHP. Es MUCHO MÁS FÁCIL que generar código PHP que funcione.
También admite referencias:
Nelmio/Entity/User:
# ...
Nelmio/Entity/Group:
group1:
name: Admins
owner: ''@user1''