ZF2 - 如何将构造函数参数传递给 Module.php 中的服务
ZF2 - How do I pass constructor arguments to a Service in Module.php
我有一个 PHP class 有一个带参数的构造函数:
例如:
Users.php
namespace Forms;
class Users
{
protected $userName;
protected $userProperties = array();
public function __construct($userName, array $userProperties = null)
{
$this->userName = $userName;
$this->userProperties = $userProperties;
}
public function sayHello()
{
return 'Hello '.$this->userName;
}
}
现在,我正尝试在这样的模型文件中使用这个 class:
$form = new Forms\Users( 'frmUserForm', array(
'method' => 'post',
'action' => '/dosomething',
'tableWidth' => '800px'
) );
它工作得很好。但是,为了编写单元测试,我需要将其重构为一个服务工厂,以便我可以模拟它。
所以,我的服务工厂现在看起来像这样:
public function getServiceConfig()
{
return array(
'initializers' => array(
function ($instance, $sm)
{
if ( $instance instanceof ConfigAwareInterface )
{
$config = $sm->get( 'Config' );
$instance->setConfig( $config[ 'appsettings' ] );
}
}
),
'factories' => array(
'Forms\Users' => function ($sm )
{
$users = new \Forms\Users();
return $users;
},
)
);
}
有了这个重构,我有两个问题:
- 考虑到 ServiceLocator 在模型文件中不可用,如何在模型文件中使用 Forms\Users 服务?
- 如何在模型中实例化用户 class 时更改服务工厂实例以获取构造函数的参数。
我曾经遇到过类似的问题。然后我决定不将参数传递给 Factory 本身。但是构建 setter 方法来处理这种情况。
namespace Forms;
class Users
{
protected $userName;
protected $userProperties = array();
public function setUserName($userName)
{
$this->userName = $userName;
}
public function setUserProperties($userProperties)
{
$this->userProperties = $userProperties;
}
public function sayHello()
{
return 'Hello '.$this->userName;
}
}
您可以实现您的模型 ServiceLocatorAwareInterface 接口,然后它可以调用如下所示的任何服务。
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class MyModel implements ServiceLocatorAwareInterface
{
protected $service_manager;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->service_manager = $serviceLocator;
}
public function getServiceLocator()
{
return $this->service_manager;
}
public function doTask($name, $properties)
{
$obj = $this->getServiceLocator('Forms\Users');
$obj->setUserName($name);
$obj->setUserProperties($properties);
}
}
我有一个 PHP class 有一个带参数的构造函数:
例如:
Users.php
namespace Forms;
class Users
{
protected $userName;
protected $userProperties = array();
public function __construct($userName, array $userProperties = null)
{
$this->userName = $userName;
$this->userProperties = $userProperties;
}
public function sayHello()
{
return 'Hello '.$this->userName;
}
}
现在,我正尝试在这样的模型文件中使用这个 class:
$form = new Forms\Users( 'frmUserForm', array(
'method' => 'post',
'action' => '/dosomething',
'tableWidth' => '800px'
) );
它工作得很好。但是,为了编写单元测试,我需要将其重构为一个服务工厂,以便我可以模拟它。
所以,我的服务工厂现在看起来像这样:
public function getServiceConfig()
{
return array(
'initializers' => array(
function ($instance, $sm)
{
if ( $instance instanceof ConfigAwareInterface )
{
$config = $sm->get( 'Config' );
$instance->setConfig( $config[ 'appsettings' ] );
}
}
),
'factories' => array(
'Forms\Users' => function ($sm )
{
$users = new \Forms\Users();
return $users;
},
)
);
}
有了这个重构,我有两个问题:
- 考虑到 ServiceLocator 在模型文件中不可用,如何在模型文件中使用 Forms\Users 服务?
- 如何在模型中实例化用户 class 时更改服务工厂实例以获取构造函数的参数。
我曾经遇到过类似的问题。然后我决定不将参数传递给 Factory 本身。但是构建 setter 方法来处理这种情况。
namespace Forms;
class Users
{
protected $userName;
protected $userProperties = array();
public function setUserName($userName)
{
$this->userName = $userName;
}
public function setUserProperties($userProperties)
{
$this->userProperties = $userProperties;
}
public function sayHello()
{
return 'Hello '.$this->userName;
}
}
您可以实现您的模型 ServiceLocatorAwareInterface 接口,然后它可以调用如下所示的任何服务。
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class MyModel implements ServiceLocatorAwareInterface
{
protected $service_manager;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->service_manager = $serviceLocator;
}
public function getServiceLocator()
{
return $this->service_manager;
}
public function doTask($name, $properties)
{
$obj = $this->getServiceLocator('Forms\Users');
$obj->setUserName($name);
$obj->setUserProperties($properties);
}
}