依赖注入 Symfony 处理多个参数
Dependecy Injection Symfony dealing with multiple parameter
我实际上是在尝试自动装配 class,目的是构建查询。
class 构造函数如下所示:
#App\Services\RepositoryDirector
class RepositoryDirector
{
public function __construct(BuilderQueryRepositoryInterface $builderQueryRepository, FilterInterface $filter)
{
$this->_builderQueryRepository = $builderQueryRepository;
$this->_filter = $filter;
}
}
请注意,这两个参数都是接口,因此它可能会根据我实现 RepositoryDirector 的位置而改变。
我已经尝试在名为 ProductController 和 CartController 的两个控制器中实现此对象。
# App\Controller\ProductController
class ProductController extends AbstractController
{
private RepositoryDirector $_cartRepositoryDirector;
public function __construct(ProductRepository $productRepository, ProductFilter $productFilter)
{
$this->_productRepositoryDirector = new RepositoryDirector($productRepository, $productFilter);
}
// Controller logic
# App\Controller\CartController
class CartController extends AbstractController
{
private RepositoryDirector $_cartRepositoryDirector;
public function __construct(CartRepository $cartRepository, CartFilter $cartFilter)
{
$this->_cartRepositoryDirector = new RepositoryDirector($cartRepository, $cartFilter);
}
// Controller logic
但问题是我这里没有使用自动布线,而且我没有使用DI,所以这是强耦合的。
我想要的是这样的东西:
# App\Controller\ProductController
class ProductController extends AbstractController
{
private RepositoryDirector $_productRepositoryDirector;
public function __construct(RepositoryDirector $productRepositoryDirector)
{
$this->_productRepositoryDirector = $productRepositoryDirector;
}
// Controller logic
所以我必须配置 config/services.yaml
来告诉 Symfony 当我使用 $productRepositoryDirector
作为参数时,我希望它创建一个带有两个参数的新对象 RepositoryDirector
:
- ProductRepository $productRepository
- ProductFilter $productFilter
我正在考虑做类似的事情:
App\Controller\ProductController:
public: true
arguments:
$productRepositoryDirector: ['@App\Repository\ProductRepository', '@App\Services\ProductFilter']
但这不起作用,我收到以下错误:
Cannot autowire service "App\Services\RepositoryDirector": argument
"$builderQueryRepository" of method "__construct()" references
interface "App\Repository\BuilderQueryRepositoryInterface" but no such
service exists. You should maybe alias this interface to one of these
existing services: "App\Repository\AreaCodeRepository",
"App\Repository\CompanyRepository", "App\Repository\DataRepository",
"App\Repository\GroupRepository",
"App\Repository\ParamStyleRepository",
"App\Repository\ParamTypeDatasetRepository",
"App\Repository\ParamTypeFormatRepository",
"App\Repository\ParamTypeRepository",
"App\Repository\ParameterGroupRepository",
"App\Repository\ParameterRepository",
"App\Repository\PhoneNumberRepository",
"App\Repository\ProductRepository",
"App\Repository\UserTokenRepository",
"App\Repository\ValueRepository".
我一直在阅读 this doc 但它没有提供任何关于我的问题的解决方案。
我终于找到了解决方案。
您必须像这样配置 config/services.yaml
:
#
# Director repository services
#
app.services.repository_director.product:
public: true
class: App\Services\RepositoryDirector
arguments:
$builderQueryRepository: '@App\Repository\ProductRepository'
$filter: '@App\Services\Filters\ProductFilter'
app.services.repository_director.cart:
public: true
class: App\Services\RepositoryDirector
arguments:
$builderQueryRepository: '@App\Repository\CartRepository'
$filter: '@App\Services\Filters\CartFilter'
#
# Controller
#
App\Controller\ProductController:
public: true
arguments:
$productRepositoryDirector: '@app.services.repository_director.product'
App\Controller\CartController:
public: true
arguments:
$cartRepositoryDirector: '@app.services.repository_director.cart'
我遗漏了 class
关键字,这要归功于 PHPStorm 自动补全,我是靠运气找到的!
如果你仔细阅读 this doc 你会注意到这个关键字使用别名的用法与我在上面的代码中所做的完全一样。
现在我已经能够找到关于这个问题的更准确的文档:Explicitly Configuring Services and Arguments。
我实际上是在尝试自动装配 class,目的是构建查询。 class 构造函数如下所示:
#App\Services\RepositoryDirector
class RepositoryDirector
{
public function __construct(BuilderQueryRepositoryInterface $builderQueryRepository, FilterInterface $filter)
{
$this->_builderQueryRepository = $builderQueryRepository;
$this->_filter = $filter;
}
}
请注意,这两个参数都是接口,因此它可能会根据我实现 RepositoryDirector 的位置而改变。
我已经尝试在名为 ProductController 和 CartController 的两个控制器中实现此对象。
# App\Controller\ProductController
class ProductController extends AbstractController
{
private RepositoryDirector $_cartRepositoryDirector;
public function __construct(ProductRepository $productRepository, ProductFilter $productFilter)
{
$this->_productRepositoryDirector = new RepositoryDirector($productRepository, $productFilter);
}
// Controller logic
# App\Controller\CartController
class CartController extends AbstractController
{
private RepositoryDirector $_cartRepositoryDirector;
public function __construct(CartRepository $cartRepository, CartFilter $cartFilter)
{
$this->_cartRepositoryDirector = new RepositoryDirector($cartRepository, $cartFilter);
}
// Controller logic
但问题是我这里没有使用自动布线,而且我没有使用DI,所以这是强耦合的。
我想要的是这样的东西:
# App\Controller\ProductController
class ProductController extends AbstractController
{
private RepositoryDirector $_productRepositoryDirector;
public function __construct(RepositoryDirector $productRepositoryDirector)
{
$this->_productRepositoryDirector = $productRepositoryDirector;
}
// Controller logic
所以我必须配置 config/services.yaml
来告诉 Symfony 当我使用 $productRepositoryDirector
作为参数时,我希望它创建一个带有两个参数的新对象 RepositoryDirector
:
- ProductRepository $productRepository
- ProductFilter $productFilter
我正在考虑做类似的事情:
App\Controller\ProductController:
public: true
arguments:
$productRepositoryDirector: ['@App\Repository\ProductRepository', '@App\Services\ProductFilter']
但这不起作用,我收到以下错误:
Cannot autowire service "App\Services\RepositoryDirector": argument "$builderQueryRepository" of method "__construct()" references interface "App\Repository\BuilderQueryRepositoryInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "App\Repository\AreaCodeRepository", "App\Repository\CompanyRepository", "App\Repository\DataRepository", "App\Repository\GroupRepository", "App\Repository\ParamStyleRepository", "App\Repository\ParamTypeDatasetRepository", "App\Repository\ParamTypeFormatRepository", "App\Repository\ParamTypeRepository", "App\Repository\ParameterGroupRepository", "App\Repository\ParameterRepository", "App\Repository\PhoneNumberRepository", "App\Repository\ProductRepository", "App\Repository\UserTokenRepository", "App\Repository\ValueRepository".
我一直在阅读 this doc 但它没有提供任何关于我的问题的解决方案。
我终于找到了解决方案。
您必须像这样配置 config/services.yaml
:
#
# Director repository services
#
app.services.repository_director.product:
public: true
class: App\Services\RepositoryDirector
arguments:
$builderQueryRepository: '@App\Repository\ProductRepository'
$filter: '@App\Services\Filters\ProductFilter'
app.services.repository_director.cart:
public: true
class: App\Services\RepositoryDirector
arguments:
$builderQueryRepository: '@App\Repository\CartRepository'
$filter: '@App\Services\Filters\CartFilter'
#
# Controller
#
App\Controller\ProductController:
public: true
arguments:
$productRepositoryDirector: '@app.services.repository_director.product'
App\Controller\CartController:
public: true
arguments:
$cartRepositoryDirector: '@app.services.repository_director.cart'
我遗漏了 class
关键字,这要归功于 PHPStorm 自动补全,我是靠运气找到的!
如果你仔细阅读 this doc 你会注意到这个关键字使用别名的用法与我在上面的代码中所做的完全一样。
现在我已经能够找到关于这个问题的更准确的文档:Explicitly Configuring Services and Arguments。