table 和列名的命名策略(Doctrine ORM)
Naming Strategy for table and column names (Doctrine ORM)
是否可以使用命名策略来处理 Doctrine ORM 中的映射 table 和列名?
现在所有名称都是通过实体 classes 中的注释指定的,例如
<?php
namespace App\Entity;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\Table(name="role")
*/
class Role
{
/**
* @ORM\Id()
* @ORM\Column(name="id", type="guid")
* @ORM\GeneratedValue(strategy="NONE")
* @var string
*/
private $id;
/**
* @ORM\Column(name="created_at", type="datetime")
* @var \DateTimeImmutable
*/
private $createdAt;
/**
* @ORM\Column(name="created_by", type="string")
* @var string
*/
private $createdBy;
// [..]
}
Table 和列名称都是 snake_case
而 class 和 属性 名称都是 camelCase
.
我尝试删除实体classes中的table和列名声明,并通过配置提供命名策略,尝试通过以下两种方式设置。
<?php
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
return [
'doctrine' => [
'connection' => [
// [..]
],
'driver' => [
// [..]
],
'annotation' => [
// [..]
],
'entity_managers' => [
'default' => [
'naming_strategy' => UnderscoreNamingStrategy::class,
],
],
'orm' => [
'naming_strategy' => UnderscoreNamingStrategy::class,
],
],
];
尝试检索实体时,抛出错误。
Doctrine\DBAL\Exception\InvalidFieldNameException: An exception occurred while executing 'SELECT t0.id AS id_1, t0.createdAt AS createdAt_2, t0.createdBy AS createdBy_3, t0.updatedAt AS updatedAt_4, t0.updatedBy AS updatedBy_5, t0.name AS name_6, t0.desc AS desc_7, t0.isCore AS isCore_8 FROM Role t0':
SQLSTATE[42S22]: Column not found: 1054 Unknown column 't0.createdAt' in 'field list' in file C:\project\path\vendor\doctrine\dbal\lib\Doctrine\DBAL\Driver\AbstractMySQLDriver.php on line 60
经过一些研究和试验,我得到了以下在 Zend Expressive 应用程序中工作的解决方案。
在doctrine.local.php
中配置命名策略
<?php
declare(strict_types = 1);
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
return [
'doctrine' => [
'connection' => [
// [..]
],
'driver' => [
// [..]
],
'annotation' => [
// [..]
],
'configuration' => [
'orm_default' => [
'naming_strategy' => UnderscoreNamingStrategy::class,
],
],
],
];
为命名策略实现一个工厂
<?php
namespace App;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class NamingStrategyFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new $requestedName();
}
}
在ConfigProvider.php
注册工厂
<?php
declare(strict_types = 1);
namespace App;
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
class ConfigProvider
{
public function __invoke()
{
return [
'dependencies' => $this->getDependencies(),
];
}
public function getDependencies(): array
{
return [
'invokables' => [
],
'factories' => [
// [..]
UnderscoreNamingStrategy::class => NamingStrategyFactory::class,
],
];
}
}
是否可以使用命名策略来处理 Doctrine ORM 中的映射 table 和列名?
现在所有名称都是通过实体 classes 中的注释指定的,例如
<?php
namespace App\Entity;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\Table(name="role")
*/
class Role
{
/**
* @ORM\Id()
* @ORM\Column(name="id", type="guid")
* @ORM\GeneratedValue(strategy="NONE")
* @var string
*/
private $id;
/**
* @ORM\Column(name="created_at", type="datetime")
* @var \DateTimeImmutable
*/
private $createdAt;
/**
* @ORM\Column(name="created_by", type="string")
* @var string
*/
private $createdBy;
// [..]
}
Table 和列名称都是 snake_case
而 class 和 属性 名称都是 camelCase
.
我尝试删除实体classes中的table和列名声明,并通过配置提供命名策略,尝试通过以下两种方式设置。
<?php
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
return [
'doctrine' => [
'connection' => [
// [..]
],
'driver' => [
// [..]
],
'annotation' => [
// [..]
],
'entity_managers' => [
'default' => [
'naming_strategy' => UnderscoreNamingStrategy::class,
],
],
'orm' => [
'naming_strategy' => UnderscoreNamingStrategy::class,
],
],
];
尝试检索实体时,抛出错误。
Doctrine\DBAL\Exception\InvalidFieldNameException: An exception occurred while executing 'SELECT t0.id AS id_1, t0.createdAt AS createdAt_2, t0.createdBy AS createdBy_3, t0.updatedAt AS updatedAt_4, t0.updatedBy AS updatedBy_5, t0.name AS name_6, t0.desc AS desc_7, t0.isCore AS isCore_8 FROM Role t0':
SQLSTATE[42S22]: Column not found: 1054 Unknown column 't0.createdAt' in 'field list' in file C:\project\path\vendor\doctrine\dbal\lib\Doctrine\DBAL\Driver\AbstractMySQLDriver.php on line 60
经过一些研究和试验,我得到了以下在 Zend Expressive 应用程序中工作的解决方案。
在doctrine.local.php
中配置命名策略<?php
declare(strict_types = 1);
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
return [
'doctrine' => [
'connection' => [
// [..]
],
'driver' => [
// [..]
],
'annotation' => [
// [..]
],
'configuration' => [
'orm_default' => [
'naming_strategy' => UnderscoreNamingStrategy::class,
],
],
],
];
为命名策略实现一个工厂
<?php
namespace App;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class NamingStrategyFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new $requestedName();
}
}
在ConfigProvider.php
注册工厂<?php
declare(strict_types = 1);
namespace App;
use Doctrine\ORM\Mapping\UnderscoreNamingStrategy;
class ConfigProvider
{
public function __invoke()
{
return [
'dependencies' => $this->getDependencies(),
];
}
public function getDependencies(): array
{
return [
'invokables' => [
],
'factories' => [
// [..]
UnderscoreNamingStrategy::class => NamingStrategyFactory::class,
],
];
}
}