ZF2 using PHP5 vs PHP7

2.9k Views Asked by At

I have a problem with my custom class located in:

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

I get a database adapter like this using the ServiceLocator (exactly as 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;
}

In PHP 5 it works just fine, but in PHP 7 it doesn't. It seems that the class is no longer ServiceLocatorAware in PHP 7. And gives this error:

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

Anyone can tell me why there is this difference between PHP 5 and PHP 7 and how to resolve it?

3

There are 3 best solutions below

2
Daniel W. On BEST ANSWER

You or the Zend Framework are calling a static member with $this (similiar to calling a non-static member using a static call).

If you didn't remove half of your error message I could tell you where exactly this happens.

From 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.

1
Wilt On

This problem is probably caused by the fact that the ServiceLocatorAwareInterface and the ServiceManagerAwareInterface in the later versions of Zend Framework were removed. This also means that the ServiceLocator is no longer available in the ServiceLocatorAware classes by default.

So this line from the tutorial taht your are referring to in your question:

The adapter can then be accessed in any ServiceLocatorAware classes.

does no longer apply to newer Zend Framework versions (PHP 7 versions).


You can also read more on this change in 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.

You will need to refactor your service and probably the best way to do that is to create a service factory where you inject your dependencies (in your example the Zend\Db\Adapter\Adapter class).

2
Wilt On

After your comment I see what the problem is. This information should have been in the question, maybe you could edit your question and add it.

You can call getAdapter statically (User::getAdapter();) but $this will not be available when you do this...

You can call a non static method statically in PHP but it will throw an error if the method uses $this since $this is not available when calling the method statically.

Check also this similar question with an answer for more information:

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

About why this was working with PHP 5.6 and not anymore I would like to refer to the answer from @DanFromGermany who explains this nicely...