zoz*_*ozo 6 php doctrine symfony doctrine-orm
我有以下问题:
原则是要更新已更改的实体。问题是由于某种原因(也许是传统的32位系统?),bigint数据类型被视为字符串(如您在下面看到的那样-这是主义中的bigint类型类,在主义代码中也有许多其他的字符串转换) )。
<?php
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps a database BIGINT to a PHP string.
*/
class BigIntType extends Type implements PhpIntegerMappingType
{
/**
* {@inheritdoc}
*/
public function getName()
{
return Type::BIGINT;
}
/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getBigIntTypeDeclarationSQL($fieldDeclaration);
}
/**
* {@inheritdoc}
*/
public function getBindingType()
{
return ParameterType::STRING;
}
/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return $value === null ? null : (string) $value;
}
}
Run Code Online (Sandbox Code Playgroud)
这将导致更新不应更新的数据,因为工作单元检查器会比较严格(应按要求)比较数据,从而导致差异(下面的代码)。
// skip if value haven't changed
if ($orgValue === $actualValue) { // $orgValue = "3829784117300", $actualValue = 3829784117300
continue;
}
Run Code Online (Sandbox Code Playgroud)
最终结果是以下代码:
$product = $productRepo->find($id);
$product->setOwnerId($ownerId); // $ownerId = 3829784117300
$this->em->flush();
Run Code Online (Sandbox Code Playgroud)
正在生成一个查询,它的工作原理...除了强调db之外,基本上没有其他功能(在我的情况下,我每天有几千万个)。上面特定情况的解决方案...
$product = $productRepo->find($id);
if ((int)$product->getOwnerId() !== $ownerId) {
$product->setOwnerId($ownerId); // $ownerId = 3829784117300
}
$this->em->flush();
Run Code Online (Sandbox Code Playgroud)
简单吧?但是...当你有2个bigints时你会怎么做?好吧... 2个条件...没什么大不了的。但是,如果他们是... 90?好的...我们可以使用反射来遍历实体属性并检查所有内容。
但是...如果在关系链中某处需要检查另一个实体怎么办?完整的解决方案是我们必须递归检查实体及其子代的每个属性,并检查bigints。
但是...这不是工作学说的目的吗?为什么我需要重新分析整个实体并检查是否仅因为bigint被视为字符串(已经导致基本上复制了大量理论代码)而检查过?
现在的问题是...如何解决这个问题(请记住,我不是在为简单案例寻求特定的解决方案,而是在寻求可应用于大型代码库的通用解决方案。应该被维护好几年-如您在上面看到的,我有解决方案,但我不能接受一半的工作和脆弱的代码,除非真的没有其他办法)?我正在寻找可能我错过的设置,该设置使学说将整数视为整数而不是字符串...诸如此类。
Bar*_*ada 10
一种解决方案是用bigint您自己的类型覆盖 Doctrine 的类型实现。首先,创建一个与 Doctrine 相同的类BigIntType,只不过将字符串转换替换为 int 转换:
class MyBigIntType extends Type
{
/**
* {@inheritdoc}
*/
public function getName()
{
return Type::BIGINT;
}
/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getBigIntTypeDeclarationSQL($fieldDeclaration);
}
/**
* {@inheritdoc}
*/
public function getBindingType()
{
return \PDO::PARAM_STR;
}
/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (null === $value) ? null : (int)$value;
}
}
Run Code Online (Sandbox Code Playgroud)
config.yml然后,在or中注册类型doctrine.yaml:
doctrine:
dbal:
types:
bigint: MyBigIntType
Run Code Online (Sandbox Code Playgroud)
我用 Symfony 2.8 对此进行了测试,这导致使用MyBigIntType所有类型为 的字段bigint。也应该适用于更高版本的 Symfony。