PHP FPM Docker ZF1:会话已经启动。 会话ID必须先设置

在我的开发环境中,我试图使用docker-compose来replace旧的笨重的Vagrant VM和Docker:

 version: '2' services: nginx: build: ./containers/nginx networks: mm: ipv4_address: 172.25.0.101 environment: APPLICATION_ENV: development extra_hosts: - "mysite.dev:127.0.0.1" ports: - 80:80 links: - php volumes: - ../:/srv php: build: ./containers/php-fpm networks: mm: ipv4_address: 172.25.0.102 volumes: - ../:/srv links: - memcached ports: - 9000:9000 memcached: image: memcached:latest ports: - 1234:11211 networks: mm: ipv4_address: 172.25.0.103 networks: mm: driver: bridge ipam: driver: default config: - subnet: 172.25.0.0/24 

但是应用程序是用ZF1编写的,每当我在Zend_Session::start()后面实例化一个Zend_Session_Namespace对象时,就会出现以下错误:

 Zend_Session_Exception: The session has already been started. The session id must be set first. in /srv/mm/vendor/zendframework/zendframework1/library/Zend/Session.php on line 667 

我已经尝试了一切,用VOLUME一个会话path,改变session.save_path ,一遍又一遍的安装,没有任何反应。

花了很长时间debugging这个问题后,我find了你的问题的答案。 在第二次调用Zend_Session::start() ZF将通过检查是否使用由php_ini设置session.hash_bits_per_character定义的正确hash_bits_per_character生成来validation会话id。

 /** * From Zend_Session */ protected static function _checkId($id) { $saveHandler = ini_get('session.save_handler'); if ($saveHandler == 'cluster') { // Zend Server SC, validate only after last dash $dashPos = strrpos($id, '-'); if ($dashPos) { $id = substr($id, $dashPos + 1); } } $hashBitsPerChar = ini_get('session.hash_bits_per_character'); if (!$hashBitsPerChar) { $hashBitsPerChar = 5; // the default value } switch($hashBitsPerChar) { case 4: $pattern = '^[0-9a-f]*$'; break; case 5: $pattern = '^[0-9a-v]*$'; break; case 6: $pattern = '^[0-9a-zA-Z-,]*$'; break; } return preg_match('#'.$pattern.'#', $id); } 

问题在于,由于某种原因,会话ID是使用hash_bits_per_char = 5而不是hash_bits_per_char = 4 。 所以,要解决这个问题,你需要做的就是在第一次调用Zend_Session::start()之前强制执行session.hash_bits_per_char设置,Zend_Session将使用正确的模式检查哈希位:

 Zend_Session::setOptions(['hash_bits_per_char' => 5]);