Symfony 4:使用服务工厂来实例化多个对象
Symfony 4: Using Factories of a Service to instantiate multiple objects
我有一个 class 路径,代表一条常规路径,可以用它做一些神奇的事情。每当我想在我的应用程序中处理路径时,我都想快速实例化一个 Path 对象并继续使用它。路径 class 有一些依赖关系,我想使用自动装配/依赖注入。
我试过的:
我将 class 作为一项服务部署到位并创建了一个工厂方法,类似于此处描述的内容:https://symfony.com/doc/current/service_container/factories.html。工厂方法接收依赖项作为参数并将它们存储在私有属性中。
只要在需要实例的地方使用依赖注入,我就能够获得新实例。这里的依赖没有问题。
现在的问题是我只能使用依赖注入获得一个实例。是的,我可以在上面克隆一个 "plain" 对象,但我想有更好的解决方案。
手动调用工厂方法是行不通的,因为那里有依赖注入。
服务和控制器:
<?
// Service
namespace App\Service;
class Path {
private $dep;
public function __construct(DependencyName $dep) {
$this->dep = $dep;
}
public static function factory(DependencyName $dep) {
$path = new Path($dep);
return $path;
}
// some methods
}
// Controller
namespace App\Controller;
use App\Service\Path;
class SomeController {
public function generatePaths() {
for (int i = 0; i < 10; i++) {
$paths[] = Path::factory(/* missing dependencies */);
}
}
public function __construct(Path $path) {
// here I can have one Path without a problem
// but I need more than one
}
}
在services.yaml中:
App\Service\Path:
# call the static method
factory: ['App\Service\Path', 'factory']
更一般:如何创建具有依赖项的服务的多个实例, 当我使用自动装配时?
解决方案不应仅限于控制器。我也需要在其他服务中使用此服务。
您可以在服务定义中使用 shared
选项:
In the service container, all services are shared by default. This
means that [...] you'll get the same instance. In some cases, you
might want to always get a new instance.
通过这样做(据我了解,您的 Dependency
始终相同)您将不再需要 factory
方法,并且可以将定义更改为:
App\Service\Path:
class: App\Service\Path
shared: false
要拥有多个实例,您不能使用注入,因此您需要实施 ServiceSubscriberInterface
并注册您的服务,这样您就可以在每次需要时从容器中手动检索它,同时仍然利用自动装配。
我不会详细介绍,因为有多个选项,其中一个可能比其他选项更有意义,但一旦实施,请执行以下操作:
$path = $this->get('path_builder'); // Whatever your alias is
每次都会给你一个新的实例。
我有一个 class 路径,代表一条常规路径,可以用它做一些神奇的事情。每当我想在我的应用程序中处理路径时,我都想快速实例化一个 Path 对象并继续使用它。路径 class 有一些依赖关系,我想使用自动装配/依赖注入。
我试过的:
我将 class 作为一项服务部署到位并创建了一个工厂方法,类似于此处描述的内容:https://symfony.com/doc/current/service_container/factories.html。工厂方法接收依赖项作为参数并将它们存储在私有属性中。 只要在需要实例的地方使用依赖注入,我就能够获得新实例。这里的依赖没有问题。 现在的问题是我只能使用依赖注入获得一个实例。是的,我可以在上面克隆一个 "plain" 对象,但我想有更好的解决方案。 手动调用工厂方法是行不通的,因为那里有依赖注入。
服务和控制器:
<?
// Service
namespace App\Service;
class Path {
private $dep;
public function __construct(DependencyName $dep) {
$this->dep = $dep;
}
public static function factory(DependencyName $dep) {
$path = new Path($dep);
return $path;
}
// some methods
}
// Controller
namespace App\Controller;
use App\Service\Path;
class SomeController {
public function generatePaths() {
for (int i = 0; i < 10; i++) {
$paths[] = Path::factory(/* missing dependencies */);
}
}
public function __construct(Path $path) {
// here I can have one Path without a problem
// but I need more than one
}
}
在services.yaml中:
App\Service\Path:
# call the static method
factory: ['App\Service\Path', 'factory']
更一般:如何创建具有依赖项的服务的多个实例, 当我使用自动装配时? 解决方案不应仅限于控制器。我也需要在其他服务中使用此服务。
您可以在服务定义中使用 shared
选项:
In the service container, all services are shared by default. This means that [...] you'll get the same instance. In some cases, you might want to always get a new instance.
通过这样做(据我了解,您的 Dependency
始终相同)您将不再需要 factory
方法,并且可以将定义更改为:
App\Service\Path:
class: App\Service\Path
shared: false
要拥有多个实例,您不能使用注入,因此您需要实施 ServiceSubscriberInterface
并注册您的服务,这样您就可以在每次需要时从容器中手动检索它,同时仍然利用自动装配。
我不会详细介绍,因为有多个选项,其中一个可能比其他选项更有意义,但一旦实施,请执行以下操作:
$path = $this->get('path_builder'); // Whatever your alias is
每次都会给你一个新的实例。