Populate Database using Doctrine and Zend 3

Some applications need to integrate data and using Zend and Doctrine all together requires us to do it properly.

Of course you could simply insert your entries inside the database using the Mysql command line which is pretty straight forward but how about the case you need to automate the process with a different database, that would be simpler to include the inserts right into your code once you launch an application or on a specific action.

Example of populating a database in Doctrine and Zend 3

Today we are going to show you how to achieve this directly from the configuration data using Doctrine 2 and Zend 3.

Let’s take a look at a table we would like to populate :


MyAuth\Entity\Country:
  type: entity
  table: country
  id:
    id:
      type: integer
      generator:
        strategy: AUTO
  fields:
    country_name:
      type: string
      length: 150
      unique: true
      notnull: true
    country_code:
      type: string
      length: 3
      notnull: true
      unique: true

This entity defines the table schema for a country. We already covered the integration of Yaml in a Zend project, this time we only need to populate the generated table.

Yaml

Let’s represent the entries using Yaml, however we won’t use Yaml to load the data :


Country:
Country_1:
country_name: France
country_code: FR
Country_2:
country_name: United States
country_code: US
Country_3:
country_name: United Kingdom
country_code: UK

You can add as many countries as needed.

Prerequesites

We need to install some packages before we get going, with Zend 2, we could simply install the following :

  • DoctrineDataFixtures from Hounddog

or

  • codeedu/zendexpr-doctrine-fixture

But we are with Zend 3, and the above packages don’t apply to the configuration, fortunately Zend comes with a large community and data fixtures are being widely used so we have a new package available on GitHub, check out the new DoctrineDataFixtures and install it using the following :

$ composer  require dkorsak/doctrine-data-fixture-module

Doctrine Data Fixtures Zend3

This module depends on the Doctrine2 ORM Data Fixtures Extensions. For more information about Doctrine and data fixtures, check the following url (doctrine data-fixtures).

Implementing DataFixtures with Zend 3 and Doctrine

To integrate the new package inside our project, we need to tell Zend to use them.

Now open up your modules.config.php file and update the content with the Doctrine lines :


return [
'Zend\Router',
'Zend\Validator',
'Zend\Session',
'Zend\Cache',
'Zend\Paginator',
'Zend\I18n',
'Zend\InputFilter',
'Zend\Filter',
'Zend\Hydrator',
'Zend\Mvc\Plugin\Prg',
'Zend\Mvc\Plugin\Identity',
'Zend\Mvc\Plugin\FlashMessenger',
'Zend\Mvc\Plugin\FilePrg',
'Zend\Form',
// Add the Doctrine integration modules.
'DoctrineModule',
'DoctrineORMModule',
'DoctrineDataFixtureModule',
'Application'
];

Next, in your module or application configuration file, you need to register fixtures along with doctrine as follow :


                'driver' => [
                        
                        'MyAuthYamlDriver' => array(
                                'class' => 'Doctrine\ORM\Mapping\Driver\YamlDriver',
                                'cache' => 'array',
                                'extension' => '.dcm.yml',
                                'paths' => [__DIR__ . '/yaml'
                                
                                ]
                        ),
                        'orm_default' => array(
                                'drivers' => array(
                                        __NAMESPACE__. '\Entity' => 'MyAuthYamlDriver',
                                )
                        )
                ],
                'fixture' => [
                        __NAMESPACE__ => __DIR__ . '/../src/Fixtures',
                ]
] ,

I’ve left the Yaml driver registration as well, you don’t need it for the current tutorial.

Change the directory with the one matching your configuration. I will use MyModule/src/Fixtures as the directory to add the classes and load the data. For this article I only use one file which is called CountryLoad.php.

But before I talk about the loading process, we need to build a service and its factory so they can be launched when we need the corresponding functions.

The service

Within the service folder, we will create a new class which takes care of the entries in any type of databases, so add these lines to your file :

<?php
namespace MyAuth\Service;

use MyAuth\Entity\Country;
/**
 * This service is responsible for adding/editing users
 * and changing user password.
 */
class CountryManager
{
    /**
     * Doctrine entity manager.
     * @var Doctrine\ORM\EntityManager
     */
    private $entityManager;
    
    /**
     * Constructs the service.
     */
    public function __construct($entityManager)
    {
        $this->entityManager = $entityManager;
    }
    
    /**
     * This method adds a new country.
     */
    public function addCountry($data)
    {
        // Do not allow several countries with the same address.
        if($this->checkCountryExists($data['country'])) {
            throw new \Exception("Country with country name " . $data['country'] . " already exists");
        }
        
        // Create new country entity.
        $country = new Country();
        $country->setCountryName($data['country']);
        $country->setCountryCode($data['code']);
        // Encrypt password and store the password in encrypted state.

        // Add the entity to the entity manager.
        $this->entityManager->persist($country);
        
        // Apply changes to database.
        $this->entityManager->flush();
        
        return $country;
    }
    /**
     * Checks whether an active country with given name already exists in the database.
     */
    public function checkCountryExists($name) {
        
        $country= $this->entityManager->getRepository(Country::class)
        ->findOneBy(array('country_name' => $name));
        
        return $country !== null;
    }
    
}

This class and its methods depend on the Country entity, we have covered this class during the Yaml tutorial with Doctrine 2.

The only method we need here is to add a new country entry inside our country table, we also check whether an entry is already present or not.

Now the Factory :

<?php
namespace MyAuth\Service\Factory;

use Interop\Container\ContainerInterface;
use MyAuth\Service\CountryManager;
/**
 * This is the factory class for UserManager service. The purpose of the factory
 * is to instantiate the service and pass it dependencies (inject dependencies).
 */
class CountryManagerFactory
{
    /**
     * This method creates the UserManager service and returns its instance.
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $entityManager = $container->get('doctrine.entitymanager.orm_default');
        
        return new CountryManager($entityManager);
    }
}

Register the service

Append this line into the module.config.php file of your module under service_manager :

/*...*/

        'service_manager' =&amp;gt; [
                'factories' =&amp;gt; [
/*...*/
                        Service\CountryManager::class =&amp;gt; Service\Factory\CountryManagerFactory::class,
                ],
        ],

 

The Data loader

Now the fun part where we instantiate the new Fixture module and load our data, create a new file in your new Fixture directory :


&amp;lt;?php

namespace MyAuth\DataFixtures;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineDataFixtureModule\ContainerAwareInterface;
use DoctrineDataFixtureModule\ContainerAwareTrait;
use MyAuth\Service\CountryManager;

class LoadUser implements FixtureInterface, ContainerAwareInterface
{
    use ContainerAwareTrait;
    
    /**
     * @param ObjectManager $manager
     */
    public function load(ObjectManager $manager)
    {
        $myCountry = $this-&amp;gt;container-&amp;gt;get(CountryManager::class);
        
        $data[]= array('country' =&amp;gt; 'United States','code' =&amp;gt; 'US');
        $data[]= array('country' =&amp;gt; 'France','code' =&amp;gt; 'FR');
        $data[]= array('country' =&amp;gt; 'United Kingdom','code' =&amp;gt; 'UK');
        $data[]= array('country' =&amp;gt; 'Spain','code' =&amp;gt; 'ES');

        
        foreach($data as $dd) {
            
            $myCountry-&amp;gt;addCountry($dd);
        
        }
    }
}

As you can see we instantiate the service and load the data, here we only add 4 rows in the table, you are free to load any entries.

 

Loading data from the command line

Following is the command I issued to load the data successfully :

$ php vendor/bin/doctrine-module orm:fixtures:load  -n –purge-with-truncate

Data Fixtures - Zend 3 - Loading

I hope you enjoyed the tutorial, you are now free to create new fixtures and services to automatically apply the changes to your tables. You may also use the Fixture class to load your data depending on a specific action.

If you have any questions or suggestions, feel free to comment on this page.

Leave a Reply

Want more information?

Related links will be displayed here in this section for you to pick up another good spot to get more details about Web marketing and Search Engine Optimization. There will be some sites which we selected to ease the work of any webmaster or/and web marketer on the Internet.

%d bloggers like this: