Сначала вам необходимо зарегистрировать свой собственный тип DBAL для страны, простирающейся на Doctrine\DBAL\Types\Type
класс:
<?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
.
- Тр первые один возвращает имя типа
- Второй для объявления типа в (SQL) базы данных (я использовал
text
в примере, но вы также можете использовать целое число или любой другие действительным тип базы данных доктрины).
- Третий метод преобразует объект вашей страны в значение базы данных (так что в этом случае текстовое значение).
- Последний метод делает обратное; он преобразует текстовое значение из базы данных. В этом случае я просто создаю экземпляр класса Country и передаю значение базы данных конструктору. Вам нужно добавить свою собственную логику в свой конструктор класса.
В моем примере я допускаю, что значения null
также допускаются.
Простая версия вашего класса Country может выглядеть следующим образом:
<?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
файл:
/**
* @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 в Doctrine2 documentation chapter Custom Mapping Types
Вы используете Doctrine 2 ORM или просто DBAL? – edigu
привет, на данный момент я использую доктрину 2 ORM, но в будущем я также буду поддерживать доктрину 2 ODM – user3549136