ZF2 使用 PHP5 与 PHP7

ZF2 using PHP5 vs PHP7

我的自定义 class 位于:

module/SomeModule/src/SomeModule/Model/someClass.php

我使用 ServiceLocator(与 in this Learning Zend Framework 2 tutorial 完全一样)获得了这样的数据库适配器:

public function getAdapter()
{
  if (!$this->adapter) {
    $sm = $this->getServiceLocator();
    $this->adapter = $sm->get('Zend\Db\Adapter\Adapter');
  }
  return $this->adapter;
}

在 PHP 5 中它工作得很好,但在 PHP 7 中它不工作。似乎 class 不再是 PHP 中的 ServiceLocatorAware 7。并给出此错误:

Fatal error: Uncaught Error: Using $this when not in object context in C:\Zend9\Apache24\htdocs\Project\module\Account\src\Account\Model\User.php:316 
Stack trace:
#0 C:\Zend9\Apache24\htdocs\Project\module\Account\src\Account\Model\User.php(271): Account\Model\User::getAdapter()
#1 C:\Zend9\Apache24\htdocs\Project\module\Account\src\Account\Controller\LoginController.php(40): Account\Model\User::userLogin('xxx', 'xxx')
#2 C:\Zend9\ZendServer\data\libraries\Zend_Framework_2.4.9\library\Zend\Mvc\Controller\AbstractActionController.php(82): Account\Controller\LoginController->indexAction()
#3 [internal function]: Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Zend\Mvc\MvcEvent))
#4 C:\Zend9\ZendServer\data\libraries\Zend_Framework_2.4.9\library\Zend\EventManager\EventManager.php(444): call_user_func(Array, Object(Zend\Mvc\MvcEvent))
#5 C:\Zend9\ZendServer\data\libraries\Zend_Framework_2.4.9\library\Zend\EventManager\EventManager.php(205): Zend\EventManager\EventManager->trigg
in C:\Zend9\Apache24\htdocs\Project\module\Account\src\Account\Model\User.php on line 316

谁能告诉我为什么 PHP 5 和 PHP 7 有这个区别,如何解决?

这个问题可能是由于Zend Framework 更高版本中的ServiceLocatorAwareInterfaceServiceManagerAwareInterface被删除造成的。这也意味着默认情况下 ServiceLocatorServiceLocatorAware class 中不再可用。

因此,您在问题中所指的教程中的这一行:

The adapter can then be accessed in any ServiceLocatorAware classes.

不再适用于较新的 Zend Framework 版本(PHP 7 版本)。


您还可以在 the migration guide 中阅读有关此更改的更多信息:

The following interfaces, traits, and classes were removed:

  • ...
  • Zend\ServiceManager\ServiceLocatorAwareInterface
  • Zend\ServiceManager\ServiceLocatorAwareTrait
  • Zend\ServiceManager\ServiceManagerAwareInterface

The ServiceLocatorAware and ServiceManagerAware interfaces and traits were too often abused under v2, and represent the antithesis of the purpose of the Service Manager component; dependencies should be directly injected, and the container should never be composed by objects.

您将需要重构您的服务,最好的方法可能是创建一个服务工厂,在其中注入您的依赖项(在您的示例中 Zend\Db\Adapter\Adapter class)。

您或 Zend Framework 正在使用 $this 调用静态成员(类似于使用静态调用调用非静态成员)。

如果您没有删除错误消息的一半,我可以告诉您具体发生在何处。

来自http://php.net/manual/en/language.oop5.basic.php

The pseudo-variable $this is available when a method is called from within an object context. $this is a reference to the calling object (usually the object to which the method belongs, but possibly another object, if the method is called statically from the context of a secondary object). As of PHP 7.0.0 calling a non-static method statically from an incompatible context results in $this being undefined inside the method. Calling a non-static method statically from an incompatible context has been deprecated as of PHP 5.6.0. As of PHP 7.0.0 calling a non-static method statically has been generally deprecated (even if called from a compatible context). Before PHP 5.6.0 such calls already triggered a strict notice.

在您发表评论后,我明白了问题所在。这些信息应该在问题中,也许你可以编辑你的问题并添加它。

您可以静态调用 getAdapter (User::getAdapter();),但是当您这样做时 $this 将不可用...

您可以在 PHP 中静态调用非静态方法,但如果方法使用 $this 将引发错误,因为在静态调用方法时 $this 不可用。

查看also this similar question with an answer了解更多信息:

You can do this, but your code will error if you use $this in the function called fun1()

关于为什么这适用于 PHP 5.6 而不再适用,我想参考 @DanFromGermany 的回答,他很好地解释了这一点...