Merge branch 'hotfix/#1336-handle-custom-object-type-identifiers-in-uow'
Close #1336
This commit is contained in:
commit
da72f3e62c
@ -13,44 +13,50 @@ you wish. Here is an example skeleton of such a custom type class:
|
||||
|
||||
<?php
|
||||
namespace My\Project\Types;
|
||||
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
|
||||
|
||||
/**
|
||||
* My custom datatype.
|
||||
*/
|
||||
class MyType extends Type
|
||||
{
|
||||
const MYTYPE = 'mytype'; // modify to match your type name
|
||||
|
||||
|
||||
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
|
||||
{
|
||||
// return the SQL used to create your column type. To create a portable column type, use the $platform.
|
||||
}
|
||||
|
||||
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
// This is executed when the value is read from the database. Make your conversions here, optionally using the $platform.
|
||||
}
|
||||
|
||||
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
// This is executed when the value is written to the database. Make your conversions here, optionally using the $platform.
|
||||
}
|
||||
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return self::MYTYPE; // modify to match your constant name
|
||||
}
|
||||
}
|
||||
|
||||
The following assumptions are applied to mapping types by the ORM:
|
||||
.. note::
|
||||
|
||||
- If the value of the field is *NULL* the method
|
||||
``convertToDatabaseValue()`` is not called.
|
||||
- The ``UnitOfWork`` never passes values to the database convert
|
||||
method that did not change in the request.
|
||||
The following assumptions are applied to mapping types by the ORM:
|
||||
|
||||
- If the value of the field is *NULL* the method
|
||||
``convertToDatabaseValue()`` is not called.
|
||||
- The ``UnitOfWork`` never passes values to the database convert
|
||||
method that did not change in the request.
|
||||
- The ``UnitOfWork`` internally assumes that entity identifiers are
|
||||
castable to string. Hence, when using custom types that map to PHP
|
||||
objects as IDs, such objects must implement the ``__toString()`` magic
|
||||
method.
|
||||
|
||||
When you have implemented the type you still need to let Doctrine
|
||||
know about it. This can be achieved through the
|
||||
|
@ -1566,15 +1566,17 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*
|
||||
* @ignore
|
||||
*
|
||||
* @param string $idHash
|
||||
* @param mixed $idHash (must be possible to cast it to string)
|
||||
* @param string $rootClassName
|
||||
*
|
||||
* @return object|bool The found entity or FALSE.
|
||||
*/
|
||||
public function tryGetByIdHash($idHash, $rootClassName)
|
||||
{
|
||||
if (isset($this->identityMap[$rootClassName][$idHash])) {
|
||||
return $this->identityMap[$rootClassName][$idHash];
|
||||
$stringIdHash = (string) $idHash;
|
||||
|
||||
if (isset($this->identityMap[$rootClassName][$stringIdHash])) {
|
||||
return $this->identityMap[$rootClassName][$stringIdHash];
|
||||
}
|
||||
|
||||
return false;
|
||||
|
44
tests/Doctrine/Tests/DbalTypes/CustomIdObject.php
Normal file
44
tests/Doctrine/Tests/DbalTypes/CustomIdObject.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\Tests\DbalTypes;
|
||||
|
||||
class CustomIdObject
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
*/
|
||||
public function __construct($id)
|
||||
{
|
||||
$this->id = (string) $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
}
|
63
tests/Doctrine/Tests/DbalTypes/CustomIdObjectType.php
Normal file
63
tests/Doctrine/Tests/DbalTypes/CustomIdObjectType.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\Tests\DbalTypes;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
class CustomIdObjectType extends Type
|
||||
{
|
||||
const NAME = 'CustomIdObject';
|
||||
const CLASSNAME = __CLASS__;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
return $value->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
||||
{
|
||||
$idObject = new CustomIdObject($value);
|
||||
|
||||
return $idObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
|
||||
{
|
||||
return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\Tests\Models\CustomType;
|
||||
|
||||
use Doctrine\Tests\DbalTypes\CustomIdObject;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="custom_id_type_child")
|
||||
*/
|
||||
class CustomIdObjectTypeChild
|
||||
{
|
||||
const CLASSNAME = __CLASS__;
|
||||
|
||||
/**
|
||||
* @Id @Column(type="CustomIdObject")
|
||||
*
|
||||
* @var CustomIdObject
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @ManyToOne(targetEntity="Doctrine\Tests\Models\CustomType\CustomIdObjectTypeParent", inversedBy="children")
|
||||
*/
|
||||
public $parent;
|
||||
|
||||
/**
|
||||
* @param CustomIdObject $id
|
||||
* @param CustomIdObjectTypeParent $parent
|
||||
*/
|
||||
public function __construct(CustomIdObject $id, CustomIdObjectTypeParent $parent)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->parent = $parent;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\Tests\Models\CustomType;
|
||||
|
||||
use Doctrine\Tests\DbalTypes\CustomIdObject;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
/**
|
||||
* @Entity
|
||||
* @Table(name="custom_id_type_parent")
|
||||
*/
|
||||
class CustomIdObjectTypeParent
|
||||
{
|
||||
const CLASSNAME = __CLASS__;
|
||||
|
||||
/**
|
||||
* @Id @Column(type="CustomIdObject")
|
||||
*
|
||||
* @var CustomIdObject
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @OneToMany(targetEntity="Doctrine\Tests\Models\CustomType\CustomIdObjectTypeChild", cascade={"persist", "remove"}, mappedBy="parent")
|
||||
*/
|
||||
public $children;
|
||||
|
||||
/**
|
||||
* @param CustomIdObject $id
|
||||
*/
|
||||
public function __construct(CustomIdObject $id)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->children = new ArrayCollection();
|
||||
}
|
||||
}
|
110
tests/Doctrine/Tests/ORM/Functional/CustomIdObjectTypeTest.php
Normal file
110
tests/Doctrine/Tests/ORM/Functional/CustomIdObjectTypeTest.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
use Doctrine\Tests\DbalTypes\CustomIdObject;
|
||||
use Doctrine\Tests\DbalTypes\CustomIdObjectType;
|
||||
use Doctrine\Tests\Models\CustomType\CustomIdObjectTypeChild;
|
||||
use Doctrine\Tests\Models\CustomType\CustomIdObjectTypeParent;
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use Doctrine\DBAL\Types\Type as DBALType;
|
||||
|
||||
class CustomIdObjectTypeTest extends OrmFunctionalTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
if (DBALType::hasType(CustomIdObjectType::NAME)) {
|
||||
DBALType::overrideType(CustomIdObjectType::NAME, CustomIdObjectType::CLASSNAME);
|
||||
} else {
|
||||
DBALType::addType(CustomIdObjectType::NAME, CustomIdObjectType::CLASSNAME);
|
||||
}
|
||||
|
||||
$this->useModelSet('custom_id_object_type');
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testFindByCustomIdObject()
|
||||
{
|
||||
$parent = new CustomIdObjectTypeParent(new CustomIdObject('foo'));
|
||||
|
||||
$this->_em->persist($parent);
|
||||
$this->_em->flush();
|
||||
|
||||
$result = $this->_em->find(CustomIdObjectTypeParent::CLASSNAME, $parent->id);
|
||||
|
||||
$this->assertSame($parent, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3622
|
||||
* @group 1336
|
||||
*/
|
||||
public function testFetchJoinCustomIdObject()
|
||||
{
|
||||
$parent = new CustomIdObjectTypeParent(new CustomIdObject('foo'));
|
||||
|
||||
$parent->children->add(new CustomIdObjectTypeChild(new CustomIdObject('bar'), $parent));
|
||||
|
||||
$this->_em->persist($parent);
|
||||
$this->_em->flush();
|
||||
|
||||
$result = $this
|
||||
->_em
|
||||
->createQuery(
|
||||
'SELECT parent, children FROM '
|
||||
. CustomIdObjectTypeParent::CLASSNAME
|
||||
. ' parent LEFT JOIN parent.children children'
|
||||
)
|
||||
->getResult();
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertSame($parent, $result[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-3622
|
||||
* @group 1336
|
||||
*/
|
||||
public function testFetchJoinWhereCustomIdObject()
|
||||
{
|
||||
$parent = new CustomIdObjectTypeParent(new CustomIdObject('foo'));
|
||||
|
||||
$parent->children->add(new CustomIdObjectTypeChild(new CustomIdObject('bar'), $parent));
|
||||
|
||||
$this->_em->persist($parent);
|
||||
$this->_em->flush();
|
||||
|
||||
// note: hydration is willingly broken in this example:
|
||||
$result = $this
|
||||
->_em
|
||||
->createQuery(
|
||||
'SELECT parent, children FROM '
|
||||
. CustomIdObjectTypeParent::CLASSNAME
|
||||
. ' parent LEFT JOIN parent.children children '
|
||||
. 'WHERE children.id = ?1'
|
||||
)
|
||||
->setParameter(1, $parent->children->first()->id)
|
||||
->getResult();
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
$this->assertSame($parent, $result[0]);
|
||||
}
|
||||
}
|
@ -257,7 +257,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
'Doctrine\Tests\Models\GeoNames\Admin1',
|
||||
'Doctrine\Tests\Models\GeoNames\Admin1AlternateName',
|
||||
'Doctrine\Tests\Models\GeoNames\City'
|
||||
)
|
||||
),
|
||||
'custom_id_object_type' => array(
|
||||
'Doctrine\Tests\Models\CustomType\CustomIdObjectTypeParent',
|
||||
'Doctrine\Tests\Models\CustomType\CustomIdObjectTypeChild',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
@ -496,6 +500,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
||||
$conn->executeUpdate('DELETE FROM geonames_country');
|
||||
}
|
||||
|
||||
if (isset($this->_usedModelSets['custom_id_object_type'])) {
|
||||
$conn->executeUpdate('DELETE FROM custom_id_type_child');
|
||||
$conn->executeUpdate('DELETE FROM custom_id_type_parent');
|
||||
}
|
||||
|
||||
$this->_em->clear();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user