Zend\Session error with phpunit and php 7.2 (but not <= 7.1)

zend-mvc

#1

I’m trying to update my zend-mvc project to run with PHP 7.2, and it seems all good in the web environment, but when I run phpunit tests, I encounter errors like:

1) ApplicationTest\Controller\AuthControllerTest::testRedirectionFollowingAuthentication
Zend\ServiceManager\Exception\ServiceNotCreatedException: Service with name "Zend\Session\Config\ConfigInterface" could not be created. Reason: ini_set(): Headers already sent. You cannot change the session module's ini settings at this time

/opt/www/court-interpreters-office/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:771
/opt/www/court-interpreters-office/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:200
/opt/www/court-interpreters-office/vendor/zendframework/zend-session/src/Service/SessionManagerFactory.php:75
/opt/www/court-interpreters-office/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:764
/opt/www/court-interpreters-office/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:200
/opt/www/court-interpreters-office/vendor/zendframework/zend-session/src/Service/ContainerAbstractServiceFactory.php:160
/opt/www/court-interpreters-office/vendor/zendframework/zend-session/src/Service/ContainerAbstractServiceFactory.php:100
/opt/www/court-interpreters-office/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:764
/opt/www/court-interpreters-office/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:200
/opt/www/court-interpreters-office/module/Admin/src/Module.php:104
/opt/www/court-interpreters-office/vendor/zendframework/zend-eventmanager/src/EventManager.php:322
/opt/www/court-interpreters-office/vendor/zendframework/zend-eventmanager/src/EventManager.php:179
/opt/www/court-interpreters-office/vendor/zendframework/zend-mvc/src/Application.php:311
/opt/www/court-interpreters-office/vendor/zendframework/zend-test/src/PHPUnit/Controller/AbstractControllerTestCase.php:310
/opt/www/court-interpreters-office/module/InterpretersOffice/test/Controller/AuthControllerTest.php:70

Caused by
PHPUnit\Framework\Error\Warning: ini_set(): Headers already sent. You cannot change the session module's ini settings at this time[...]
/opt/www/court-interpreters-office/vendor/zendframework/zend-session/src/Service/ContainerAbstractServiceFactory.php:160
/opt/www/court-interpreters-office/vendor/zendframework/zend-session/src/Service/ContainerAbstractServiceFactory.php:100
/opt/www/court-interpreters-office/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:764
/opt/www/court-interpreters-office/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:200
/opt/www/court-interpreters-office/module/Admin/src/Module.php:104
/opt/www/court-interpreters-office/vendor/zendframework/zend-eventmanager/src/EventManager.php:322
/opt/www/court-interpreters-office/vendor/zendframework/zend-eventmanager/src/EventManager.php:179
/opt/www/court-interpreters-office/vendor/zendframework/zend-mvc/src/Application.php:311
/opt/www/court-interpreters-office/vendor/zendframework/zend-test/src/PHPUnit/Controller/AbstractControllerTestCase.php:310
/opt/www/court-interpreters-office/module/InterpretersOffice/test/Controller/AuthControllerTest.php:70

I have read https://github.com/zendframework/zend-session/issues/104, but before I start trying to re-wire my session stuff, I was hoping someone could confirm that this looks like the same issue.

The line in my application code that sets it off is in a Module.php's onBootstrap() where I check authentication and authorization. The logic is pretty standard. If they’re not logged in and requesting something for which authentication is required, I save the current url in a session variable and redirect them to the login page so that on successful login I can send know where to send them back.

For setting up sessions I have borrowed the technique found in https://olegkrivtsov.github.io/using-zend-framework-3-book/html/en/Working_with_Sessions/Session_Manager.html. I don’t have any factory for the SessionManager registered anywhere in my configuration so I am assuming (yes I ought to understand this better) there is some abstract factory magic happening.

But, again, I’m a little confused/uncertain and hoping to confirm that the approach suggested in the discussion at https://github.com/zendframework/zend-session/issues/104 is the way to go.


#2

OK, after a full two days of struggle, I found at least the proximate cause of my heartbreak and patched it up, and now my phpunit tests are happy under php 7.[0-2]. I was accessing the SessionManager from the service manager early in the cycle (as suggested in https://olegkrivtsov.github.io/using-zend-framework-3-book/html/en/Working_with_Sessions/Session_Manager.html) because that was supposed to be a good idea, so as to make it become the default session manager. The official docs https://docs.zendframework.com/zend-session/manager/ don’t seem to support that notion. And I still don’t have a complete grasp of all this plumbing. But… onwards!