2

我的自定义类位于:

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

我得到了一个像这样的数据库适配器ServiceLocator(就像在这个Learning Zend Framework 2教程中一样):

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

在 PHP 5 中它工作得很好,但在 PHP 7 中却不行。似乎该类不再ServiceLocatorAware在 PHP 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\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\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\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 之间存在这种差异以及如何解决它?

4

3 回答 3

3

您或 Zend 框架调用静态成员$this(类似于使用静态调用调用非静态成员)。

如果您没有删除一半的错误消息,我可以告诉您发生这种情况的确切位置。

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

$this当从对象上下文中调用方法时,伪变量可用。$this 是对调用对象的引用(通常是方法所属的对象,但也可能是另一个对象,如果该方法是从辅助对象的上下文中静态调用的)。从 PHP 7.0.0 开始,从不兼容的上下文中静态调用非静态方法会导致 $this 在方法内部未定义。自 PHP 5.6.0 起,从不兼容的上下文中静态调用非静态方法已被弃用。从 PHP 7.0.0 开始,静态调用非静态方法通常已被弃用(即使从兼容的上下文中调用)。在 PHP 5.6.0 之前,此类调用已经触发了严格的通知。

于 2016-12-01T08:47:19.833 回答
1

这个问题可能是因为Zend Framework 的更高版本中的ServiceLocatorAwareInterface和被删除了。ServiceManagerAwareInterface这也意味着默认情况下ServiceLocator在类中不再可用。ServiceLocatorAware

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

然后可以在任何 ServiceLocatorAware 类中访问适配器。

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


您还可以在迁移指南中阅读有关此更改的更多信息:

删除了以下接口、特征和类:

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

ServiceLocatorAware 和 ServiceManagerAware 接口和特征在 v2 下经常被滥用,并且代表了 Service Manager 组件的目的的对立面;依赖项应该直接注入,容器永远不应该由对象组成。

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

于 2016-12-01T08:21:53.980 回答
1

在您发表评论后,我看到了问题所在。此信息应该在问题中,也许您可​​以编辑您的问题并添加它。

您可以getAdapter静态调用 ( User::getAdapter();) 但$this在执行此操作时将不可用...

您可以在 PHP 中静态调用非静态方法,但如果该方法使用时会抛出错误,$this因为$this在静态调用该方法时不可用。

还要检查这个类似的问题和答案以获取更多信息:

您可以这样做,但如果您在调用的函数中使用 $this,您的代码会出错fun1()

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

于 2016-12-01T10:27:05.580 回答