我在symfony项目中使用Spatie's enums,并为这些对象创建了自定义DBAL类型。将枚举对象保存到数据库时,将其保存为特殊的字符串格式。我的EnumType
中的转换函数如下:
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
return get_class($value) . '::' . $value->getIndex() . '::' . $value->getValue();
}
例如,我有一个如下所示的交易状态枚举:
namespace App\Enum;
use Spatie\Enum\Enum;
/**
* @method static self failed()
* @method static self pending()
* @method static self completed()
*/
final class TransactionStatus extends Enum {}
当我将其保存到数据库时,它可以分别转换为以下字符串之一:
App\Enum\TransactionStatus::0::failed
App\Enum\TransactionStatus::1::pending
App\Enum\TransactionStatus::2::completed
这有助于我的EnumType
知道将其转换回哪个枚举。我之所以在字符串中使用索引号,是因为这有助于排序。
现在,所有这些对于将我的实体保存并保存到数据库都非常有效。但是,当我尝试在DQL语句的where子句中使用枚举时,它根本无法工作。
namespace App\Repository;
use App\Entity\Transaction;
use App\Enum\TransactionStatus;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
class TransactionRepository extends ServiceEntityRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, Transaction::class);
}
public function findByStatus(TransactionStatus $status)
{
return $this->createQueryBuilder('t')
->andWhere('t.status = :status')
->setParameter('status', $status)
->getQuery()->getResult();
}
}
由于某些原因,学说忽略了我的转换函数,而只使用了Spatie枚举中内置的__toString()
函数。因此,学说正在寻找字符串"pending"
而不是"App\Enum\TransactionStatus::1::pending"
。
如何确保我的枚举始终在DQL where子句中正确转换?
答案 0 :(得分:0)
好的,即使它是超级hacky,我也找到了一种方法。我只是从__toString()
方法的调用位置进行检查,如果它是从Doctrine的DBAL中调用的,那么我使用枚举的DB格式。
namespace App\Enum;
use Spatie\Enum\Enum as BaseEnum;
abstract class Enum extends BaseEnum
{
public function __toString(): string
{
if (debug_backtrace()[1]['class'] === 'PDOStatement') {
return get_class($this) . "::$this->index::$this->value";
}
return parent::__toString();
}
}