关于 8 版本的问题。 Doctrine 如何将实体放入包中?我没有映射到数据库(
1 回答
这取自我写的关于如何在 V8 中执行此操作的新文档:
标准行为
默认情况下,包中的实体以下列方式提供:
- 使用注释驱动程序,它从 PHP 代码中直接提供的注释中加载数据库信息。
- 如果在包中启用了旧的 \Src 命名空间,如果包不使用任何自定义自动加载器,并且在版本 8 之前支持具体 5,则扫描整个 packages/package_handle/src/ 目录中的实体并他们的注释。
- 如果未启用旧的 \Src 命名空间,则 $pkg->getPackageAutoloaderRegistries() 指定的类位置以及在 packages/your_package/src/Concrete/Entity 中找到的任何文件都将被扫描以查找实体。
此行为都可以在 中找到Concrete\Core\Database\EntityManager\Provider\DefaultPackageProvider
,如果未提供另一个,则使用默认实体管理器提供程序类。
注释驱动程序功能
在早期的 Doctrine ORM 包文档中找到的大部分文档仍然是准确的,但有一个很大的变化:
如果您的包包含使用注释的实体类,并且包需要版本 8 或更高版本,则必须在注释中包含 @ORM。所以代替这个:
<?php
namespace Concrete\Package\Statistics\Src\Entity;
/**
* @Entity
* @Table(name="StatisticsUserAgents")
*/
class UserAgent
{
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @Column(type="string")
*/
protected $value;
/**
* @Column(type="string")
*/
protected $hash;
}
您必须导入 ORM 命名空间,并在所有注释前加上 ORM:
<?php
namespace Concrete\Package\Statistics\Src\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="StatisticsUserAgents")
*/
class UserAgent
{
/**
* @ORM\Id @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string")
*/
protected $value;
/**
* @ORM\Column(type="string")
*/
protected $hash;
}
我们为什么这样做?不只是让你的生活更加困难。一旦包含了 @ORM 命名空间,它就可以让你的 Doctrine 做很多很多的事情。例如,任何在版本 8 上运行的包都将能够支持Doctrine Extensions等等。
可定制的行为
自定义包实体管理器的行为很容易。您可以使用可自定义的实体管理器配置做什么?
- 如果您的包的一个特定部分包含实体,并且您不希望扫描整个包的代码库以查找实体,请提供一个自定义包提供程序,该提供程序仅指向文件系统中包含您的实体类的位置。
- 提供额外的 Doctrine 类型或扩展
- 以其他格式提供您的实体信息,例如 XML 或 YAML(而不是 PHP 类中的注释)。
要自定义包配置其提供的实体的方式,请执行以下操作之一
- 让你的包的控制器实现
Concrete\Core\Database\EntityManager\Provider\ProviderAggregateInterface
,它将负责实现 getEntityManagerProvider() 方法,该方法返回Concrete\Core\Database\EntityManager\Provider\ProviderInterface
接口的一个对象, - 使您的包的控制器实现该
Concrete\Core\Database\EntityManager\Provider\ProviderInterface
方法,该方法返回一个对象数组Concrete\Core\Database\EntityManager\Driver\DriverInterface
。
在这两种情况下,您最终都会提供至少一个Concrete\Core\Database\EntityManager\Driver\DriverInterface
对象。
例子
这是一个简单的例子。假设您有一个包含以下位置的实体的包:
- Concrete\Package\YourPackage\Entity(由concrete5从packages/src/your_package/Concrete/Entity自动加载)
PortlandLabs\Testing\Entity,您已使用 $pkgAutoloaderRegistries 将其设置为自定义类位置:
protected $pkgAutoloaderRegistries = array('src/Testing' => '\PortlandLabs\Testing', );
无需扫描在 packages/your_package/src/ 中找到的所有文件(这是默认的标准行为),您只想使用标准注释驱动程序从这两个位置加载类。首先,修改您的包控制器,使其实现 ProviderAggregateInterface,并导入接口以及 StandardPackageProvider 类:
use Concrete\Core\Database\EntityManager\Provider\ProviderAggregateInterface;
use Concrete\Core\Database\EntityManager\Provider\StandardPackageProvider;
class Controller extends Package implements ProviderAggregateInterface
然后,实现提供者类:
public function getEntityManagerProvider()
{
$provider = new StandardPackageProvider($this->app, $this, [
'src/Concrete/Entity' => 'Concrete\Package\YourPackage\Entity',
'src/Testing/Entity' => 'PortlandLabs\Testing\Entity'
]);
return $provider;
}
而已!标准包提供程序是一个简单的库,大多数想要使用注释实体但从自定义位置加载它们的类都可以使用它。
其他文件格式
存在其他类以提供不同格式的实体定义。看看你是否想以 YAML 或 XML 格式提供你的包实体Concrete\Core\Database\EntityManager\Provider\YamlProvider
。Concrete\Core\Database\EntityManager\Provider\XmlProvider