gheb/doctrine-cross-bundle-mapping-bundle

此Bundle提供了跨Bundle的映射

dev-master / 1.0.x-dev 2015-06-18 13:52 UTC

This package is auto-updated.

Last update: 2024-09-28 00:54:44 UTC


README

此Bundle是解决跨Bundle关联映射的解决方案。

此Bundle为您提供一种将属于两个不同Bundle的两个实体关联起来的方法,同时不破坏解耦并独立运行。

Build Status

用例

假设我们有一个UserBundle和一个ForumBundle。如果一个用户可以是发布者,发布者可以作为独立的实体使用。在这种情况下,我非常希望这两个实体之间不共享任何硬链接。

从User实体到Publisher实体的关联映射创建了一个硬依赖。一旦禁用ForumBundle,Doctrine会抛出错误,指出Publisher不在其注册的任何命名空间中。

由于Doctrine是连接实体和数据库的桥梁,我们可以操纵它理解信息存储的方式,并添加动态映射。

安装

更新您的composer.json

{
     ...
    "require": {
        ...
        "gheb/doctrine-cross-bundle-mapping-bundle": "^1.0@dev"
    }
     ...
}

然后

$ composer update

或者

$ composer require gheb/doctrine-cross-bundle-mapping-bundle

配置

使用此Bundle有两种方式。

第一种称为resolve_target_entities,这是由doctrine提供的。使用示例可以在这里找到。唯一的区别是,如果目标实体不存在,则不创建映射。不会抛出错误。

第二种方式略有不同。您不是在您的整个实体映射配置中设置映射配置,而是在您的config.yml中设置它。您可能希望将额外的配置放在您的app/config.yml中,但将其放在Bundle中更有意义。(Acme/UserBundle/Resources/config/config.yml)

以下是一个配置示例

您有一个UserBundle和一个ForumBundle。它们都可以独立使用。但到目前为止,我想让它们能够通信。我想从User获取Publisher(然后获取他发布的一切),或者从Publisher获取User(然后获取他的邮件或他的名字)

#app/config/config.yml

doctrine_cross_bundle_mapping:
    mapping:
        Acme\UserBundle\Entity\User:
            oneToOne:
                publisher:
                    targetEntity: Acme\ForumBundle\Entity\Publisher
                    mappedBy: user
        Acme\ForumBundle\Entity\Publisher:
            oneToOne:
                user:
                    targetEntity: Acme\UserBundle\Entity\User
                    inversedBy: publisher
                    joinColumn:
                        name: user_id
                        referenceColumnName: id

设置完成后,Doctrine知道映射关联。但您需要更新您的模式。检查一下 ;)

$ php app/console doctrine:schema:update --dump-sql
$ php app/console doctrine:schema:update --force

属性访问

到目前为止,我们实际上不需要做任何事情。但我们将进一步扩展。

PHP非常(过于?)灵活,允许我们这样做

$object = new Class();

$object->randomAttribute = 'myValue';
var_dump($object->randomAttribute); // myValue

但到目前为止,我们一直被教导这样做

$object = new Class();

$object->setRandomAttribute('myValue');
var_dump($object->getRandomAttribute()); // myValue

从User可能链接到Publisher的角度来看,没有必要在其中编写任何访问器。

因此,为了保持解耦,只需使用一个Trait。

namespace Acme\UserBundle\Entity;

use Gheb\Bundle\DoctrineCrossBundleMappingBundle\Traits\CrossBundleMappingTrait;

class User {
    use CrossBundleMappingTrait;
    ...
}

然后您可以像通常那样做

$object = new Class();


// Scalar and Object

var_dump($object->getScalarAttribute()); // null
$object->setScalarAttribute('myValue');
var_dump($object->getScalarAttribute()); // myValue



// Boolean

var_dump($object->getBooleanAttribute()); // false
$object->setBooleanAttribute(true);
var_dump($object->getBooleanAttribute()); // true
var_dump($object->isBooleanAttribute()); // true

$object->setBooleanAttribute('test');
var_dump($object->getBooleanAttribute()); // test
var_dump($object->isBooleanAttribute()); // false



// Array

var_dump($object->getArrayAttributes()); // null
$object->setArrayAttributes(array(1,2,3));
var_dump($object->getArrayAttributes()); // array(1,2,3)

// When using addArrayAttribute, recognize the add and transform ArrayAttribute in arrayAttributes
$object->addArrayAttribute('test');
var_dump($object->getArrayAttributes()); // array(1,2,3,'test')

$object->addArrayAttribute('test2');
var_dump($object->getArrayAttributes()); // array(1,2,3,'test','test2)

$object->addArrayAttribute('test');
var_dump($object->getArrayAttributes()); // array(1,2,3,'test','test2,'test')

// When using removeArrayAttribute, recognize the remove and transform ArrayAttribute in arrayAttributes
$object->removeArrayAttribute('test');
var_dump($object->getArrayAttributes()); // array(0=>1, 1=>2, 2=>3, 4=>'test2, 5=>'test')

$object->removeArrayAttribute('test');
var_dump($object->getArrayAttributes()); // array(0=>1, 1=>2, 2=>3, 4=>'test2)



// ArrayCollection (or anything Traversable)

var_dump($object->getTraversableAttributes()); // null
$object->setTraversableAttributes(new ArrayCollection(array(1,2,3)));
var_dump($object->getTraversableAttributes()); // ArrayCollection(array(1,2,3))

// When using addArrayAttribute, recognize the add and transform ArrayAttribute in arrayAttributes
$object->addTraversableAttribute('test');
var_dump($object->getTraversableAttributes()); // ArrayCollection(array(1,2,3,'test'))

$object->addTraversableAttribute('test2');
var_dump($object->getTraversableAttributes()); // ArrayCollection(array(1,2,3,'test','test2))

$object->addTraversableAttribute('test');
var_dump($object->getTraversableAttributes()); // ArrayCollection(array(1,2,3,'test','test2))

// When using removeArrayAttribute, recognize the remove and transform ArrayAttribute in arrayAttributes
$object->removeTraversableAttribute('test');
var_dump($object->getTraversableAttributes()); // ArrayCollection(array(1,2,3,'test2))

警告

力量越大,责任越大... 这可以防止任何未声明的Method的误用。

因此,您可能需要扩展您的基本类并定义这些访问器。

namespace Acme\UserBundle\Entity;

use User as BaseUser;

class User extends BaseUser 
{
    protected $publisher;
    
    public function getPublisher();
    
    public function setPublisher();
    ...
}