2

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?

Wilt
  • 41,477
  • 12
  • 152
  • 203
user3130983
  • 31
  • 1
  • 5
  • Did you start by checking the error logs – RiggsFolly Nov 30 '16 at 21:41
  • What version of PHP5 were you using before the PHP7 jump – RiggsFolly Nov 30 '16 at 21:41
  • PHP 5.6, error log shows: Using $this when not in object context – user3130983 Nov 30 '16 at 21:47
  • How are you calling that method? – Tim Fountain Dec 01 '16 at 02:26
  • Within the same class in another function i request and assign the adapter to a variable like this (The class is called User): $dbAdapter = User::getAdapter(); – user3130983 Dec 01 '16 at 09:41
  • Your question should include all relevant information so others can properly answer it. Showing half the error message and later adding relevant information in an additional comment is not the way to go. Also read [the **how to ask** on StackOverflow](http://stackoverflow.com/help/how-to-ask) for more details. – Wilt Dec 01 '16 at 10:36

3 Answers3

3

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.

Daniel W.
  • 31,164
  • 13
  • 93
  • 151
  • I think you are correct, i added the entire error message to topic. How is the best way of doing it with PHP 7 - just declaring the getAdapter function static? Thanks – user3130983 Dec 01 '16 at 09:27
  • 1
    Nice answer. This question is a good example on why the deprecation is legitimate and a great improvement in PHP7. – Wilt Dec 01 '16 at 10:40
1

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

Community
  • 1
  • 1
Wilt
  • 41,477
  • 12
  • 152
  • 203
  • Thanks for your answer, however, the code - even the framework version is exactly the same - only change is Zend server with php5.6 vs Zend server with php7. – user3130983 Dec 01 '16 at 09:20
1

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

Community
  • 1
  • 1
Wilt
  • 41,477
  • 12
  • 152
  • 203
  • Isn't the whole point with the service manager and service locater aware classes to be able to use $this? Remember it is instantiated by the global autoload settings? – user3130983 Dec 01 '16 at 10:44
  • @user3130983 Not sure what you are trying to say. If you want to continue using such code start [with declaring your functions static](http://php.net/manual/en/language.oop5.static.php): `public static function getAdapter`. – Wilt Dec 01 '16 at 11:01