Apigility + Doctrine - ManyToMany 从任何一方获取 Eager 都不起作用 - 存在数据
Apigility + Doctrine - ManyToMany fetch Eager not working from either side - data present
我有一个包含国家和货币对象的设置。一个国家可能有 0 个或多个货币对象,反之亦然,0 个或多个国家对象可能使用货币。问题是数据没有返回到前端(api 请求)。
在Country
实体
/**
* @var Collection|ArrayCollection|Currency[]
* @ORM\ManyToMany(targetEntity="Currency", inversedBy="countries", fetch="EAGER")
* @ORM\JoinTable(
* name="country_country_currencies",
* joinColumns={@ORM\JoinColumn(name="country_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="currency_id", referencedColumnName="id")}
* )
*/
protected $currencies;
在Currency
实体
/**
* @var Collection|ArrayCollection|Currency[]
* @ORM\ManyToMany(targetEntity="Country", mappedBy="currencies", fetch="EAGER")
*/
protected $countries;
双方都有一个__construct()
函数将初始值设置为new ArrayCollection()
。两者都有自己的 get*()
、add*()
和 remove*()
函数。
在单个对象(例如 /currencies/45
)上调试 DoctrineResource::fetch()
函数时,$entity
对象 在执行 return $entity
(fethc()
的最后一行),所以我知道 数据在那里。
然而,当它最终 returns 到 "front-end" 时,我丢失了 ManyToMany 关系的数据:
正如您在上面看到的:countries
是空的。
从另一端(来自Country
)请求时,currencies
为空。
附加信息
其他类似问题在评论或答案中有建议,我会立即放在这里,因为我已经检查过了。
Doctrine 缓存 - 我 运行 以下命令:
./vendor/bin/doctrine-module orm:clear-cache:query
./vendor/bin/doctrine-module orm:clear-cache:result
./vendor/bin/doctrine-module orm:clear-cache:metadata
我已确保禁用 Zend Framework 缓存(另外,通过 composer development-enable
启用开发模式)。
生成的实体代理也已多次删除,以确保它们不是问题所在。我也尝试过不使用 fetch="EAGER"
(实际上是原始的),但结果相同。
为实体使用错误的水化器:两者都配置为使用 Doctrine EntityManager(两者相同):
'zf-hal' => [
'metadata_map' => [
\Country::class => [
'route_identifier_name' => 'id',
'entity_identifier_name' => 'id',
'route_name' => 'country.rest.doctrine.country',
'hydrator' => 'Country\V1\Rest\Country\CountryHydrator',
'max_depth' => 3,
],
\Country\V1\Rest\Country\CountryCollection::class => [
'entity_identifier_name' => 'id',
'route_name' => 'country.rest.doctrine.country',
'is_collection' => true,
],
// other entity
],
],
// some more config
'zf-apigility' => [
'doctrine-connected' => [
\Country\V1\Rest\Country\CountryResource::class => [
'object_manager' => 'doctrine.entitymanager.orm_default',
'hydrator' => 'Country\V1\Rest\Country\CountryHydrator',
],
// other entity
],
],
'doctrine-hydrator' => [
'Country\V1\Rest\Country\CountryHydrator' => [
'entity_class' => \Salesupply\Core\Country\Entity\Country::class,
'object_manager' => 'doctrine.entitymanager.orm_default',
'by_value' => true,
'strategies' => [],
'use_generated_hydrator' => true,
],
// other entity
],
另一位建议 content negotiation
类型可能设置为 json
而不是 HalJson
:两者(所有内容)都设置为 HalJson
:
'zf-content-negotiation' => [
'controllers' => [
'Country\V1\Rest\Country\Controller' => 'HalJson',
'Country\V1\Rest\Currency\Controller' => 'HalJson',
],
],
ApiSkeletons 供应商包设计有此功能。几个月前我打开了 an issue on Github。
为确保您收到回款:
- 创建策略 class 并扩展 Doctrine 的
AllowRemoveByValue
策略。
- 将
extract
函数覆盖为 return 集合,填充或空
就是这样。
完整 class:
namespace Application\Strategy;
use DoctrineModule\Stdlib\Hydrator\Strategy\AllowRemoveByValue;
use ZF\Hal\Collection;
class UniDirectionalToManyStrategy extends AllowRemoveByValue
{
public function extract($value)
{
return new Collection($value ?: []);
}
}
在需要的地方应用此策略。例如。你的 Advert
和 Applications
一样多,所以应该像这样修改配置:
'doctrine-hydrator' => [
'Application\V1\Entity\ApplicationHydrator' => [
// other config
'strategies' => [
'relatedToManyPropertyName' => \Application\Strategy\UniDirectionalToManyStrategy::class,
],
],
],
现在应该 return 编辑集合。
快速说明:这只会作为策略 对 *ToMany 方有效。
我有一个包含国家和货币对象的设置。一个国家可能有 0 个或多个货币对象,反之亦然,0 个或多个国家对象可能使用货币。问题是数据没有返回到前端(api 请求)。
在Country
实体
/**
* @var Collection|ArrayCollection|Currency[]
* @ORM\ManyToMany(targetEntity="Currency", inversedBy="countries", fetch="EAGER")
* @ORM\JoinTable(
* name="country_country_currencies",
* joinColumns={@ORM\JoinColumn(name="country_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="currency_id", referencedColumnName="id")}
* )
*/
protected $currencies;
在Currency
实体
/**
* @var Collection|ArrayCollection|Currency[]
* @ORM\ManyToMany(targetEntity="Country", mappedBy="currencies", fetch="EAGER")
*/
protected $countries;
双方都有一个__construct()
函数将初始值设置为new ArrayCollection()
。两者都有自己的 get*()
、add*()
和 remove*()
函数。
在单个对象(例如 /currencies/45
)上调试 DoctrineResource::fetch()
函数时,$entity
对象 在执行 return $entity
(fethc()
的最后一行),所以我知道 数据在那里。
然而,当它最终 returns 到 "front-end" 时,我丢失了 ManyToMany 关系的数据:
正如您在上面看到的:countries
是空的。
从另一端(来自Country
)请求时,currencies
为空。
附加信息
其他类似问题在评论或答案中有建议,我会立即放在这里,因为我已经检查过了。
Doctrine 缓存 - 我 运行 以下命令:
./vendor/bin/doctrine-module orm:clear-cache:query
./vendor/bin/doctrine-module orm:clear-cache:result
./vendor/bin/doctrine-module orm:clear-cache:metadata
我已确保禁用 Zend Framework 缓存(另外,通过 composer development-enable
启用开发模式)。
生成的实体代理也已多次删除,以确保它们不是问题所在。我也尝试过不使用 fetch="EAGER"
(实际上是原始的),但结果相同。
为实体使用错误的水化器:两者都配置为使用 Doctrine EntityManager(两者相同):
'zf-hal' => [
'metadata_map' => [
\Country::class => [
'route_identifier_name' => 'id',
'entity_identifier_name' => 'id',
'route_name' => 'country.rest.doctrine.country',
'hydrator' => 'Country\V1\Rest\Country\CountryHydrator',
'max_depth' => 3,
],
\Country\V1\Rest\Country\CountryCollection::class => [
'entity_identifier_name' => 'id',
'route_name' => 'country.rest.doctrine.country',
'is_collection' => true,
],
// other entity
],
],
// some more config
'zf-apigility' => [
'doctrine-connected' => [
\Country\V1\Rest\Country\CountryResource::class => [
'object_manager' => 'doctrine.entitymanager.orm_default',
'hydrator' => 'Country\V1\Rest\Country\CountryHydrator',
],
// other entity
],
],
'doctrine-hydrator' => [
'Country\V1\Rest\Country\CountryHydrator' => [
'entity_class' => \Salesupply\Core\Country\Entity\Country::class,
'object_manager' => 'doctrine.entitymanager.orm_default',
'by_value' => true,
'strategies' => [],
'use_generated_hydrator' => true,
],
// other entity
],
另一位建议 content negotiation
类型可能设置为 json
而不是 HalJson
:两者(所有内容)都设置为 HalJson
:
'zf-content-negotiation' => [
'controllers' => [
'Country\V1\Rest\Country\Controller' => 'HalJson',
'Country\V1\Rest\Currency\Controller' => 'HalJson',
],
],
ApiSkeletons 供应商包设计有此功能。几个月前我打开了 an issue on Github。
为确保您收到回款:
- 创建策略 class 并扩展 Doctrine 的
AllowRemoveByValue
策略。 - 将
extract
函数覆盖为 return 集合,填充或空
就是这样。
完整 class:
namespace Application\Strategy;
use DoctrineModule\Stdlib\Hydrator\Strategy\AllowRemoveByValue;
use ZF\Hal\Collection;
class UniDirectionalToManyStrategy extends AllowRemoveByValue
{
public function extract($value)
{
return new Collection($value ?: []);
}
}
在需要的地方应用此策略。例如。你的 Advert
和 Applications
一样多,所以应该像这样修改配置:
'doctrine-hydrator' => [
'Application\V1\Entity\ApplicationHydrator' => [
// other config
'strategies' => [
'relatedToManyPropertyName' => \Application\Strategy\UniDirectionalToManyStrategy::class,
],
],
],
现在应该 return 编辑集合。
快速说明:这只会作为策略 对 *ToMany 方有效。