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;
                },
            )
        );
    }

有了这个重构,我有两个问题:

  1. 考虑到 ServiceLocator 在模型文件中不可用,如何在模型文件中使用 Forms\Users 服务?
  2. 如何在模型中实例化用户 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);
    }
}