webgriffe/doctrine-fixtures-loader

There is no license information available for the latest version (dev-master) of this package.

Base loader for your project's object fixtures, with all their dependencies, using Doctrine and closures.

dev-master 2013-11-28 16:46 UTC

This package is auto-updated.

Last update: 2024-04-07 19:51:51 UTC


README

Base loader for your project's object fixtures, with all their dependencies, using Doctrine and closures.

Introduction

Typically in a real project that uses Doctrine, you have tons of entities related with each others that needs to be loaded during functional tests using doctrine/data-fixtures library. This base loader helps you to mantain a fixtures loader for your project that can give to the caller an instance of an object with all related dependencies loaded. See the example below.

Usage

Suppose that your project has the following entities:

  • Order
  • Product
  • Customer

Suppose that for every Order you have many Products and one Customer. Suppose that you need a fixture that loads an Order with a specific payment method. Suppose that your application requires that an Order must have all dependencies set. In this case, what you have to do is to instantiate an Order, with all of its dependencies, like as follows:

<?php

namespace MyProject\Tests\Fixtures;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\Persistence\ObjectManager;

class MyFixture extends AbstractFixture
{
	public function load(ObjectManager $manager)
	{
		$customer = new Customer();
		// set Customer's properties
		
		$product1 = new Product();
		// set Product's properties
		
		$product2 = new Product();
		// set Product's properties
		
		$order = new Order();
		$order->setProducts(array($product1, $product2));
		$order->setCustomer($customer);
		// set other Order's properties
		
		$order->setPaymentMethod('my_specific_payment_method');
		
		$manager->persist($order);
		$manager->flush();
	}
}

And that's ok but the code to build an Order with all of its dependencies will be probably repeated in every fixture that needs an Order. This is really uncomfortable, especially in a real project with much more entities and dependencies, because when you need an Order you don't want to worry about all of its dependencies; you just want an Order so you can set specific properties for the specific test case.

The solution proposed is to maintain a fixture loader (that extends this base loader) specific for your project as the following:

<?php

namespace MyProject\Tests\Fixtures;

use Webgriffe\DoctrineFixturesLoader\Loader as BaseLoader;
use MyProject\Entity\Order;
use MyProject\Entity\Customer;
use MyProject\Entity\Product;

class Loader extends BaseLoader
{
	public function loadCustomer($referenceName = null, $forcePersist = true)
	{
		$objectLoader = function (
			Loader $loader,
			$referenceName
		) {
			$customer = new Customer();
			// set Customer's properties
			
			return $customer;
		};
		
		$this->load($referenceName, $forcePersist, $objectLoader, 'default-customer');
	}
	
	public function loadProduct($referenceName = null, $forcePersist = true)
	{
		$objectLoader = function (
			Loader $loader,
			$referenceName
		) {
			$product = new Product();
			// set Product's properties
			
			return $product;
		};
		
		$this->load($referenceName, $forcePersist, $objectLoader, 'default-product');
	}
	
	public function loadOrder($referenceName = null, $forcePersist = true)
	{
		$objectLoader = function (
			Loader $loader,
			$referenceName
		) {		
			$order = new Order();
			$order->setProducts(
				array($loader->loadProduct(), $loader->loadProduct('another-product'))
			);
			$order->setCustomer($loader->loadCustomer());
			// set other Order's properties
			
			return $order;
		};
		
		$this->load($referenceName, $forcePersist, $objectLoader, 'default-order');
	}				
}

Note that you can add any loader methods as you want, if needed. For example here we could add a loadEmptyOrder() method that creates an Order without Produts. So, with a fixture loader like the above one, the previous MyFixture become as follows:

<?php

namespace MyProject\Tests\Fixtures;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\Persistence\ObjectManager;
use MyProject\Tests\Fixtures\Loader;

class MyFixture extends AbstractFixture
{
	public function load(ObjectManager $manager)
	{
		$loader = new Loader($manager, $this->referenceRepository);

		$order = $loader->loadOrder();
		$order->setPaymentMethod('my_specific_payment_method');

		$manager->flush();
	}
}

That's all.

Credits

This base loader has been developed by Webgriffe®. Please, report to us any bug or suggestion by GitHub issues.