diff --git a/dev/FixtureBlueprint.php b/dev/FixtureBlueprint.php
index e74bdee11..532c16b56 100644
--- a/dev/FixtureBlueprint.php
+++ b/dev/FixtureBlueprint.php
@@ -128,27 +128,48 @@ class FixtureBlueprint {
 			// Populate all relations
 			if($data) foreach($data as $fieldName => $fieldVal) {
 				if($obj->many_many($fieldName) || $obj->has_many($fieldName)) {
+					$obj->write();
+
 					$parsedItems = array();
-					$items = preg_split('/ *, */',trim($fieldVal));
-					foreach($items as $item) {
-						// Check for correct format: =><relationname>.<identifier>.
-						// Ignore if the item has already been replaced with a numeric DB identifier
-						if(!is_numeric($item) && !preg_match('/^=>[^\.]+\.[^\.]+/', $item)) {
-							throw new InvalidArgumentException(sprintf(
-								'Invalid format for relation "%s" on class "%s" ("%s")',
-								$fieldName,
-								$class,
-								$item
-							));
+
+					if(is_array($fieldVal)) {
+						// handle lists of many_many relations. Each item can
+						// specify the many_many_extraFields against each 
+						// related item.
+						foreach($fieldVal as $relVal) {
+							$item = key($relVal);
+							$id = $this->parseValue($item, $fixtures);
+							$parsedItems[] = $id;
+
+							array_shift($relVal);
+
+							$obj->getManyManyComponents($fieldName)->add(
+								$id, $relVal
+							);
+						}
+					} else {
+						$items = preg_split('/ *, */',trim($fieldVal));
+
+						foreach($items as $item) {
+							// Check for correct format: =><relationname>.<identifier>.
+							// Ignore if the item has already been replaced with a numeric DB identifier
+							if(!is_numeric($item) && !preg_match('/^=>[^\.]+\.[^\.]+/', $item)) {
+								throw new InvalidArgumentException(sprintf(
+									'Invalid format for relation "%s" on class "%s" ("%s")',
+									$fieldName,
+									$class,
+									$item
+								));
+							}
+
+							$parsedItems[] = $this->parseValue($item, $fixtures);
 						}
 
-						$parsedItems[] = $this->parseValue($item, $fixtures);
-					}
-					$obj->write();
-					if($obj->has_many($fieldName)) {
-						$obj->getComponents($fieldName)->setByIDList($parsedItems);
-					} elseif($obj->many_many($fieldName)) {
-						$obj->getManyManyComponents($fieldName)->setByIDList($parsedItems);
+						if($obj->has_many($fieldName)) {
+							$obj->getComponents($fieldName)->setByIDList($parsedItems);
+						} elseif($obj->many_many($fieldName)) {
+							$obj->getManyManyComponents($fieldName)->setByIDList($parsedItems);
+						}
 					}
 				} elseif($obj->has_one($fieldName)) {
 					// Sets has_one with relation name
diff --git a/docs/en/topics/testing/fixtures.md b/docs/en/topics/testing/fixtures.md
index 77a1886c2..5053cd143 100644
--- a/docs/en/topics/testing/fixtures.md
+++ b/docs/en/topics/testing/fixtures.md
@@ -2,38 +2,42 @@
 
 ## Overview
 
-You will often find the need to test your functionality with some consistent data.
-If we are testing our code with the same data each time,
-we can trust our tests to yeild reliable results.
-In Silverstripe we define this data via 'fixtures' (so called because of their fixed nature).
-The `[api:SapphireTest]` class takes care of populating a test database with data from these fixtures -
-all we have to do is define them, and we have a few ways in which we can do this.
+You will often find the need to test your functionality with some consistent 
+data. If we are testing our code with the same data each time, we can trust our 
+tests to yield reliable results.
+
+In Silverstripe we define this data via 'fixtures' (so called because of their 
+fixed nature). The `[api:SapphireTest]` class takes care of populating a test 
+database with data from these fixtures - all we have to do is define them, and 
+we have a few ways in which we can do this.
 
 ## YAML Fixtures
 
-YAML is a markup language which is deliberately simple and easy to read,
-so it is ideal for fixture generation.
+YAML is a markup language which is deliberately simple and easy to read, so it 
+is ideal for fixture generation.
 
 Say we have the following two DataObjects:
 
 	:::php
 	class Player extends DataObject {
-		static $db = array (
+		
+		private static $db = array (
 			'Name' => 'Varchar(255)'
 		);
 
-		static $has_one = array(
+		private static $has_one = array(
 			'Team' => 'Team'
 		);
 	}
 
 	class Team extends DataObject {
-		static $db = array (
+
+		private static $db = array (
 			'Name' => 'Varchar(255)',
 			'Origin' => 'Varchar(255)'
 		);
 
-		static $has_many = array(
+		private static $has_many = array(
 			'Players' => 'Player'
 		);
 	}
@@ -59,31 +63,42 @@ We can represent multiple instances of them in `YAML` as follows:
 			Name: The Crusaders
 			Origin: Bay of Plenty
 
-Our `YAML` is broken up into three levels, signified by the indentation of each line.
-In the first level of indentation, `Player` and `Team`,
-represent the class names of the objects we want to be created for the test.
+Our `YAML` is broken up into three levels, signified by the indentation of each 
+line. In the first level of indentation, `Player` and `Team`, represent the 
+class names of the objects we want to be created for the test.
 
-The second level, `john`/`joe`/`jack` & `hurricanes`/`crusaders`, are identifiers.
-These are what you pass as the second argument of `SapphireTest::objFromFixture()`.
-Each identifier you specify represents a new object.
+The second level, `john`/`joe`/`jack` & `hurricanes`/`crusaders`, are 
+identifiers. These are what you pass as the second argument of 
+`SapphireTest::objFromFixture()`. Each identifier you specify represents a new 
+object.
 
 The third and final level represents each individual object's fields.
-A field can either be provided with raw data (such as the Names for our Players),
-or we can define a relationship, as seen by the fields prefixed with `=>`.
 
-Each one of our Players has a relationship to a Team,
-this is shown with the `Team` field for each `Player` being set to `=>Team.` followed by a team name.
-Take the player John for example, his team is the Hurricanes which is represented by `=>Team.hurricanes`.
-This is tells the system that we want to set up a relationship for the `Player` object `john` with the `Team` object `hurricanes`.
+A field can either be provided with raw data (such as the names for our 
+Players), or we can define a relationship, as seen by the fields prefixed with 
+`=>`.
+
+Each one of our Players has a relationship to a Team, this is shown with the 
+`Team` field for each `Player` being set to `=>Team.` followed by a team name.
+
+Take the player John for example, his team is the Hurricanes which is 
+represented by `=>Team.hurricanes`.
+
+This is tells the system that we want to set up a relationship for the `Player` 
+object `john` with the `Team` object `hurricanes`.
+
 It will populate the `Player` object's `TeamID` with the ID of `hurricanes`,
 just like how a relationship is always set up.
 
 <div class="hint" markdown='1'>
-Note that we use the name of the relationship (Team), and not the name of the database field (TeamID).
+Note that we use the name of the relationship (Team), and not the name of the 
+database field (TeamID).
 </div>
 
-This style of relationship declaration can be used for both a `has-one` and a `many-many` relationship.
-For `many-many` relationships, we specify a comma separated list of values.
+This style of relationship declaration can be used for both a `has-one` and a 
+`many-many` relationship. For `many-many` relationships, we specify a comma 
+separated list of values.
+
 For example we could just as easily write the above as:
 
 	:::yml
@@ -104,27 +119,97 @@ For example we could just as easily write the above as:
 			Origin: Bay of Plenty
 			Players: =>Player.joe,=>Player.jack
 
-A crucial thing to note is that **the YAML file specifies DataObjects, not database records**.
-The database is populated by instantiating DataObject objects and setting the fields declared in the YML,
-then calling write() on those objects.
-This means that any `onBeforeWrite()` or default value logic will be executed as part of the test.
-The reasoning behind this is to allow us to test the `onBeforeWrite` functionality of our objects.
-You can see this kind of testing in action in the `testURLGeneration()` test from the example in
-[Creating a SilverStripe Test](creating-a-silverstripe-test).
+A crucial thing to note is that **the YAML file specifies DataObjects, not 
+database records**.
+
+The database is populated by instantiating DataObject objects and setting the 
+fields declared in the YML, then calling write() on those objects. This means 
+that any `onBeforeWrite()` or default value logic will be executed as part of 
+the test. The reasoning behind this is to allow us to test the `onBeforeWrite` 
+functionality of our objects.
+
+You can see this kind of testing in action in the `testURLGeneration()` test 
+from the example in [Creating a SilverStripe Test](creating-a-silverstripe-test).
+
+### Defining many_many_extraFields
+
+`many_many` relations can have additional database fields attached to the 
+relationship. For example we may want to declare the role each player has in the
+team.
+
+	:::php
+	class Player extends DataObject {
+		
+		private static $db = array (
+			'Name' => 'Varchar(255)'
+		);
+
+		private static $belongs_many_many = array(
+			'Teams' => 'Team'
+		);
+	}
+
+	class Team extends DataObject {
+
+		private static $db = array (
+			'Name' => 'Varchar(255)'
+		);
+
+		private static $many_many = array(
+			'Players' => 'Player'
+		);
+
+		private static $many_many_extraFields = array(
+			"Players" => array(
+				"Role" => "Varchar"
+			);
+		);	
+	}
+
+To provide the value for the many_many_extraField use the YAML list syntax.
+
+	:::yml
+	Player:
+	  john:
+	    Name: John
+	  joe:
+	    Name: Joe
+	  jack:
+	    Name: Jack
+	Team:
+	  hurricanes:
+	    Name: The Hurricanes
+	    Players: 
+	      - =>Player.john:
+ 	        Role: Captain
+
+	  crusaders:
+	    Name: The Crusaders
+	    Players: 
+	      - =>Player.joe:
+	        Role: Captain
+	      - =>Player.jack:
+	        Role: Winger
 
 ## Test Class Definition
 
 ### Manual Object Creation
 
-Sometimes statically defined fixtures don't suffice. This could be because of the complexity of the tested model,
-or because the YAML format doesn't allow you to modify all of a model's state.
-One common example here is publishing pages (page fixtures aren't published by default).
+Sometimes statically defined fixtures don't suffice. This could be because of 
+the complexity of the tested model, or because the YAML format doesn't allow you 
+to modify all of a model's state.
+
+One common example here is publishing pages (page fixtures aren't published by 
+default).
 
 You can always resort to creating objects manually in the test setup phase.
-Since the test database is cleared on every test method, you'll get a fresh set of test instances every time.
+
+Since the test database is cleared on every test method, you'll get a fresh set 
+of test instances every time.
 
 	:::php
 	class SiteTreeTest extends SapphireTest {
+
 		function setUp() {
 			parent::setUp();
 
@@ -140,16 +225,20 @@ Since the test database is cleared on every test method, you'll get a fresh set
 
 ### Why Factories?
 
-While manually defined fixtures provide full flexibility, they offer very little in terms of structure and convention.
-Alternatively, you can use the `[api:FixtureFactory]` class, which allows you to set default values,
-callbacks on object creation, and dynamic/lazy value setting.
+While manually defined fixtures provide full flexibility, they offer very little 
+in terms of structure and convention. Alternatively, you can use the 
+`[api:FixtureFactory]` class, which allows you to set default values, callbacks 
+on object creation, and dynamic/lazy value setting.
 
 <div class="hint" markdown='1'>
-SapphireTest uses FixtureFactory under the hood when it is provided with YAML based fixtures.
+SapphireTest uses FixtureFactory under the hood when it is provided with YAML 
+based fixtures.
 </div>
 
-The idea is that rather than instantiating objects directly, we'll have a factory class for them.
-This factory can have so called "blueprints" defined on it, which tells the factory how to instantiate an object of a specific type. Blueprints need a name, which is usually set to the class it creates.
+The idea is that rather than instantiating objects directly, we'll have a 
+factory class for them. This factory can have so called "blueprints" defined on 
+it, which tells the factory how to instantiate an object of a specific type. 
+Blueprints need a name, which is usually set to the class it creates.
 
 ### Usage
 
diff --git a/tests/dev/FixtureBlueprintTest.php b/tests/dev/FixtureBlueprintTest.php
index a5613d85f..591ab6e36 100644
--- a/tests/dev/FixtureBlueprintTest.php
+++ b/tests/dev/FixtureBlueprintTest.php
@@ -12,6 +12,58 @@ class FixtureBlueprintTest extends SapphireTest {
 		'FixtureFactoryTest_DataObjectRelation'
 	);
 
+	public function testCreateWithRelationshipExtraFields() {
+		$blueprint = new FixtureBlueprint('FixtureFactoryTest_DataObject');
+
+		$relation1 = new FixtureFactoryTest_DataObjectRelation();
+		$relation1->write();
+		$relation2 = new FixtureFactoryTest_DataObjectRelation();
+		$relation2->write();
+
+		// in YAML these look like
+		// RelationName:
+		//   - =>Relational.obj:
+		//     ExtraFieldName: test
+		//   - =>..
+		$obj = $blueprint->createObject(
+			'one',
+			array(
+				'ManyMany' => 
+					array(
+						array(
+							"=>FixtureFactoryTest_DataObjectRelation.relation1" => array(), 
+							"Label" => 'This is a label for relation 1'
+						),
+						array(
+							"=>FixtureFactoryTest_DataObjectRelation.relation2" => array(),
+							"Label" => 'This is a label for relation 2'
+						)
+					)
+			),
+			array(
+				'FixtureFactoryTest_DataObjectRelation' => array(
+					'relation1' => $relation1->ID,
+					'relation2' => $relation2->ID
+				)
+			)
+		);
+
+		$this->assertEquals(2, $obj->ManyMany()->Count());
+		$this->assertNotNull($obj->ManyMany()->find('ID', $relation1->ID));
+		$this->assertNotNull($obj->ManyMany()->find('ID', $relation2->ID));
+
+		$this->assertEquals(
+			array('Label' => 'This is a label for relation 1'),
+			$obj->ManyMany()->getExtraData('ManyMany', $relation1->ID)
+		);
+
+		$this->assertEquals(
+			array('Label' => 'This is a label for relation 2'),
+			$obj->ManyMany()->getExtraData('ManyMany', $relation2->ID)
+		);
+	}
+
+
 	public function testCreateWithoutData() {
 		$blueprint = new FixtureBlueprint('FixtureFactoryTest_DataObject');
 		$obj = $blueprint->createObject('one');
@@ -28,6 +80,7 @@ class FixtureBlueprintTest extends SapphireTest {
 		$this->assertEquals('My Name', $obj->Name);
 	}
 
+
 	public function testCreateWithRelationship() {
 		$blueprint = new FixtureBlueprint('FixtureFactoryTest_DataObject');
 
@@ -127,7 +180,7 @@ class FixtureBlueprintTest extends SapphireTest {
 		$this->assertEquals(99, $obj->ID);
 	}
 
-	function testCallbackOnBeforeCreate() {
+	public function testCallbackOnBeforeCreate() {
 		$blueprint = new FixtureBlueprint('FixtureFactoryTest_DataObject');
 		$this->_called = 0;
 		$self = $this;
@@ -144,7 +197,7 @@ class FixtureBlueprintTest extends SapphireTest {
 		$this->_called = 0;
 	}
 
-	function testCallbackOnAfterCreate() {
+	public function testCallbackOnAfterCreate() {
 		$blueprint = new FixtureBlueprint('FixtureFactoryTest_DataObject');
 		$this->_called = 0;
 		$self = $this;
@@ -161,7 +214,7 @@ class FixtureBlueprintTest extends SapphireTest {
 		$this->_called = 0;
 	}
 
-	function testDefineWithDefaultCustomSetters() {
+	public function testDefineWithDefaultCustomSetters() {
 		$blueprint = new FixtureBlueprint(
 			'FixtureFactoryTest_DataObject', 
 			null,
diff --git a/tests/dev/FixtureFactoryTest.php b/tests/dev/FixtureFactoryTest.php
index 2dd7685e2..a08d87ef7 100644
--- a/tests/dev/FixtureFactoryTest.php
+++ b/tests/dev/FixtureFactoryTest.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * @package framework
  * @subpackage tests
@@ -151,19 +152,37 @@ class FixtureFactoryTest extends SapphireTest {
 
 }
 
+/**
+ * @package framework
+ * @subpackage tests
+ */
 class FixtureFactoryTest_DataObject extends DataObject implements TestOnly {
+	
 	private static $db = array(
 		"Name" => "Varchar"
 	);
+	
 	private static $many_many = array(
 		"ManyMany" => "FixtureFactoryTest_DataObjectRelation"
 	);
+
+	private static $many_many_extraFields = array(
+		"ManyMany" => array(
+			"Label" => "Varchar"
+		)
+	);
 }
 
+/**
+ * @package framework
+ * @subpackage tests
+ */
 class FixtureFactoryTest_DataObjectRelation extends DataObject implements TestOnly {
+	
 	private static $db = array(
 		"Name" => "Varchar"
 	);
+	
 	private static $belongs_many_many = array(
 		"TestParent" => "FixtureFactoryTest_DataObject"
 	);