Doctrine 数据类型(使用工厂)
Doctrine Data Type (use Factory)
我想实现一个新的学说数据类型 (http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html)。
我已经实现了一个国家服务,它通过适配器从任何图书馆加载国家数据。知道我有以下实现:
<?php
interface CountryInterface;
interface Address
{
public function setCountry(CountryInterface $country);
public function getCountry() : CountryInterface;
}
?>
所以,我想做的是 - 制作一个 CountryType
将 Country
对象转换为特定的字符串值(使用的字段将通过 OptionClass
设置,例如。 : Alpha2, Alpha3, IsoNumber).
我的问题是,doctrine 只允许通过类名映射数据类型,所以我无法实现一个工厂来加载所有需要的依赖项。
我希望这是可以理解的。
问候
首先,您需要为扩展 Doctrine\DBAL\Types\Type
class:
的国家/地区注册您的自定义 DBAL 类型
<?php
namespace Application\DBAL\Types;
use Application\Resource\Country;
use Application\Service\CountryService;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;
use InvalidArgumentException;
class CountryType extends Type
{
const NAME = 'country';
/**
* Country service
*/
protected $countryService;
/**
* @return string
*/
public function getName()
{
return self::NAME;
}
/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getDoctrineTypeMapping('text');
}
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if($value === null){
return null;
}
if ($value instanceof Country) {
return (string) $value;
}
throw ConversionException::conversionFailed($value, self::NAME);
}
/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if($value === null){
return null;
}
$country = $this->countryService->getCountry($value);
if( ! $country instanceof Country ){
throw ConversionException::conversionFailed($value, self::NAME);
}
return $country;
}
/**
* Set country service
*
* @var CountryService $service
*/
public function setCountryService ($service){
$this->countryService = $service;
}
}
该类型需要实现getName
、getSQLDeclaration
、convertToDatabaseValue
和convertToPHPValue
四个方法。
- 第一个 returns 类型的名称
- 第二个用于 (SQL) 数据库中的类型声明(我在示例中使用了
text
,但您也可以使用整数或任何其他有效的学说数据库类型)。
- 第三种方法将您的国家/地区对象转换为数据库值(在本例中为文本值)。
- 最后一种方法正好相反;它转换来自数据库的文本值。在这种情况下,我只是实例化 Country class 并将数据库值传递给构造函数。您需要在 class 构造函数中添加自定义逻辑。
在我的示例中,我假设 null
值也是允许的。
您的国家 class 的简单版本可能如下所示:
<?php
namespace Application\Resource;
class Country{
protected $value;
/**
* Magic stringify to cast country object to a string
*/
public function __toString(){
return $value;
}
/**
* Constructor method
*/
public function construct($value){
$this->value = $value
// set other properties...
}
// setters and getters...
}
值应该是 alpha2
/alpha3
/country_name
还是您希望在数据库中可见的任何值由您决定。您还应该以某种方式在构造函数方法中使用其他属性填充其他国家/地区。我把这部分留给你。
现在您需要注册您的自定义国家/地区类型,以便学说将使用它:
'doctrine' => array(
//...
'configuration' => array(
'orm_default' => array(
Application\DBAL\Types\CountryType::NAME => Application\DBAL\Types\CountryType::class,
)
)
)
并且您可以在您的应用程序 Module.php
文件中的 bootstrap 上设置您的服务:
/**
* @param EventInterface|MvcEvent $event
* @return void
*/
public function onBootstrap(EventInterface $event)
{
$application = $event->getApplication();
$eventManager = $application->getEventManager();
$eventManager->attach(MvcEvent::EVENT_BOOTSTRAP, array($this, 'initializeCountryType');
}
/**
* @param MvcEvent $event
*/
public function initializeCountryType(MvcEvent $event)
{
$application = $event->getApplication();
$serviceManager = $application->getServiceManager();
//get your country service from service manager
$countryService = $serviceManager->getCountryService();
$countryType = \Doctrine\DBAL\Types\Type::getType('country');
$countryType->setCountryService($countryService);
}
现在您可以在任何实体定义中使用您的国家/地区类型,如下所示:
/**
* @var string
* @ORM\Column(type="country", nullable=true)
*/
protected $country;
中阅读有关如何映射自定义 DBAL 类型的更多信息
我想实现一个新的学说数据类型 (http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html)。
我已经实现了一个国家服务,它通过适配器从任何图书馆加载国家数据。知道我有以下实现:
<?php
interface CountryInterface;
interface Address
{
public function setCountry(CountryInterface $country);
public function getCountry() : CountryInterface;
}
?>
所以,我想做的是 - 制作一个 CountryType
将 Country
对象转换为特定的字符串值(使用的字段将通过 OptionClass
设置,例如。 : Alpha2, Alpha3, IsoNumber).
我的问题是,doctrine 只允许通过类名映射数据类型,所以我无法实现一个工厂来加载所有需要的依赖项。
我希望这是可以理解的。
问候
首先,您需要为扩展 Doctrine\DBAL\Types\Type
class:
<?php
namespace Application\DBAL\Types;
use Application\Resource\Country;
use Application\Service\CountryService;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;
use InvalidArgumentException;
class CountryType extends Type
{
const NAME = 'country';
/**
* Country service
*/
protected $countryService;
/**
* @return string
*/
public function getName()
{
return self::NAME;
}
/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getDoctrineTypeMapping('text');
}
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if($value === null){
return null;
}
if ($value instanceof Country) {
return (string) $value;
}
throw ConversionException::conversionFailed($value, self::NAME);
}
/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if($value === null){
return null;
}
$country = $this->countryService->getCountry($value);
if( ! $country instanceof Country ){
throw ConversionException::conversionFailed($value, self::NAME);
}
return $country;
}
/**
* Set country service
*
* @var CountryService $service
*/
public function setCountryService ($service){
$this->countryService = $service;
}
}
该类型需要实现getName
、getSQLDeclaration
、convertToDatabaseValue
和convertToPHPValue
四个方法。
- 第一个 returns 类型的名称
- 第二个用于 (SQL) 数据库中的类型声明(我在示例中使用了
text
,但您也可以使用整数或任何其他有效的学说数据库类型)。 - 第三种方法将您的国家/地区对象转换为数据库值(在本例中为文本值)。
- 最后一种方法正好相反;它转换来自数据库的文本值。在这种情况下,我只是实例化 Country class 并将数据库值传递给构造函数。您需要在 class 构造函数中添加自定义逻辑。
在我的示例中,我假设 null
值也是允许的。
您的国家 class 的简单版本可能如下所示:
<?php
namespace Application\Resource;
class Country{
protected $value;
/**
* Magic stringify to cast country object to a string
*/
public function __toString(){
return $value;
}
/**
* Constructor method
*/
public function construct($value){
$this->value = $value
// set other properties...
}
// setters and getters...
}
值应该是 alpha2
/alpha3
/country_name
还是您希望在数据库中可见的任何值由您决定。您还应该以某种方式在构造函数方法中使用其他属性填充其他国家/地区。我把这部分留给你。
现在您需要注册您的自定义国家/地区类型,以便学说将使用它:
'doctrine' => array(
//...
'configuration' => array(
'orm_default' => array(
Application\DBAL\Types\CountryType::NAME => Application\DBAL\Types\CountryType::class,
)
)
)
并且您可以在您的应用程序 Module.php
文件中的 bootstrap 上设置您的服务:
/**
* @param EventInterface|MvcEvent $event
* @return void
*/
public function onBootstrap(EventInterface $event)
{
$application = $event->getApplication();
$eventManager = $application->getEventManager();
$eventManager->attach(MvcEvent::EVENT_BOOTSTRAP, array($this, 'initializeCountryType');
}
/**
* @param MvcEvent $event
*/
public function initializeCountryType(MvcEvent $event)
{
$application = $event->getApplication();
$serviceManager = $application->getServiceManager();
//get your country service from service manager
$countryService = $serviceManager->getCountryService();
$countryType = \Doctrine\DBAL\Types\Type::getType('country');
$countryType->setCountryService($countryService);
}
现在您可以在任何实体定义中使用您的国家/地区类型,如下所示:
/**
* @var string
* @ORM\Column(type="country", nullable=true)
*/
protected $country;
中阅读有关如何映射自定义 DBAL 类型的更多信息