ManyToManySelfReferentialAssociationTest.php 4.65 KB
Newer Older
1 2 3 4 5
<?php

namespace Doctrine\Tests\ORM\Functional;

use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
6
use Doctrine\ORM\Mapping\AssociationMapping;
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

require_once __DIR__ . '/../../TestInit.php';

/**
 * Tests a self referential many-to-many association mapping (from a model to the same model, without inheritance).
 * For simplicity the relation duplicates entries in the association table
 * to remain simmetrical.
 */
class ManyToManySelfReferentialAssociationTest extends AbstractManyToManyAssociationTestCase
{
    protected $_firstField = 'product_id';
    protected $_secondField = 'related_id';
    protected $_table = 'ecommerce_products_related';
    private $firstProduct;
    private $secondProduct;
    private $firstRelated;
    private $secondRelated;

    protected function setUp()
    {
        $this->useModelSet('ecommerce');
        parent::setUp();
        $this->firstProduct = new ECommerceProduct();
        $this->secondProduct = new ECommerceProduct();
        $this->firstRelated = new ECommerceProduct();
        $this->firstRelated->setName("Business");
        $this->secondRelated = new ECommerceProduct();
        $this->secondRelated->setName("Home");
    }

    public function testSavesAManyToManyAssociationWithCascadeSaveSet()
    {
        $this->firstProduct->addRelated($this->firstRelated);
        $this->firstProduct->addRelated($this->secondRelated);
romanb's avatar
romanb committed
41
        $this->_em->persist($this->firstProduct);
42 43 44 45 46 47 48 49 50 51 52 53
        $this->_em->flush();
        
        $this->assertForeignKeysContain($this->firstProduct->getId(),
                                   $this->firstRelated->getId());
        $this->assertForeignKeysContain($this->firstProduct->getId(),
                                   $this->secondRelated->getId());
    }

    public function testRemovesAManyToManyAssociation()
    {
        $this->firstProduct->addRelated($this->firstRelated);
        $this->firstProduct->addRelated($this->secondRelated);
romanb's avatar
romanb committed
54
        $this->_em->persist($this->firstProduct);
55 56 57 58 59 60 61 62 63 64 65 66 67
        $this->firstProduct->removeRelated($this->firstRelated);

        $this->_em->flush();

        $this->assertForeignKeysNotContain($this->firstProduct->getId(),
                                   $this->firstRelated->getId());
        $this->assertForeignKeysContain($this->firstProduct->getId(),
                                   $this->secondRelated->getId());
    }

    public function testEagerLoadsOwningSide()
    {
        $this->_createLoadingFixture();
68 69 70 71 72 73 74 75 76 77 78 79
        $products = $this->_findProducts();
        $this->assertLoadingOfOwningSide($products); 
    }

    public function testLazyLoadsOwningSide()
    {
        $this->_createLoadingFixture();

        $metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\ECommerce\ECommerceProduct');
        $metadata->getAssociationMapping('related')->fetchMode = AssociationMapping::FETCH_LAZY;

        $query = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p');
80
        $products = $query->getResult();
81 82 83 84 85 86
        $this->assertLoadingOfOwningSide($products); 
    }

    public function assertLoadingOfOwningSide($products)
    {
        list ($firstProduct, $secondProduct) = $products;
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
        $this->assertEquals(2, count($firstProduct->getRelated()));
        $this->assertEquals(2, count($secondProduct->getRelated()));
        
        $categories = $firstProduct->getRelated();        
        $firstRelatedBy = $categories[0]->getRelated();
        $secondRelatedBy = $categories[1]->getRelated();
        
        $this->assertEquals(2, count($firstRelatedBy));
        $this->assertEquals(2, count($secondRelatedBy));

        $this->assertTrue($firstRelatedBy[0] instanceof ECommerceProduct);
        $this->assertTrue($firstRelatedBy[1] instanceof ECommerceProduct);
        $this->assertTrue($secondRelatedBy[0] instanceof ECommerceProduct);
        $this->assertTrue($secondRelatedBy[1] instanceof ECommerceProduct);
        
        $this->assertCollectionEquals($firstRelatedBy, $secondRelatedBy);
    }

    protected function _createLoadingFixture()
    {
        $this->firstProduct->addRelated($this->firstRelated);
        $this->firstProduct->addRelated($this->secondRelated);
        $this->secondProduct->addRelated($this->firstRelated);
        $this->secondProduct->addRelated($this->secondRelated);
romanb's avatar
romanb committed
111 112
        $this->_em->persist($this->firstProduct);
        $this->_em->persist($this->secondProduct);
113 114 115 116 117 118 119 120
        
        $this->_em->flush();
        $this->_em->clear();
    }

    protected function _findProducts()
    {
        $query = $this->_em->createQuery('SELECT p, r FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p LEFT JOIN p.related r ORDER BY p.id, r.id');
121
        return $query->getResult();
122 123
    }
}