views:

1976

answers:

7

I am trying to use either APC or XCache as an opcode to cache my php pages. I am using it with Zend and Doctrine and it's having a problem with the autoloader.

If I try with APC, I get the following:

Fatal error: spl_autoload() [<a href='function.spl-autoload'>function.spl-autoload</a>]: 
  Class Doctrine_Event could not be loaded in 
  C:\\[mydir]\\library\\doctrine\\Doctrine\\Record.php on line 777

If I try with XCache I get the following:

PHP Fatal error: Cannot redeclare class Zend_Registry in 
  C:\\[mydir]\\library\\zendframework\\Zend\\Registry.php on line 0

I'm running Zend 1.9.1, Doctrine 1.1 on a windows box.

My bootstrap is as follows:

set_include_path(dirname(__FILE__).'/../library/zendframework'
. PATH_SEPARATOR . dirname(__FILE__).'/../library/doctrine'.....

require 'Zend/Loader/Autoloader.php';

$loader = Zend_Loader_Autoloader::getInstance();
$loader->suppressNotFoundWarnings(false);
$loader->setFallbackAutoloader(true);

From what I've read, using APC or xcache is almost a must for performance, but I can't seem to get it working. Any ideas?

A: 

Is there something else mucking the include path? Maybe try to log out the include path right before that line in your first APC example.

The XCache one is really weird. That project is pretty dead though, and I'd not trust it on PHP 5.2+. Try eaccelerator instead? We've had the best luck with it.

Justin
There are other Doctrine-specific things in the include path (models, etc).We're looking for a ZendCache backend (http://framework.zend.com/manual/en/zend.cache.backends.html) so eaccelerator won't work.
Chris Williams
Theres a proposal for an eaccelerator backend http://framework.zend.com/wiki/display/ZFPROP/Zend_Cache_Backend_Eaccelerator+-+Federico+Cargnelutti - should be pretty easy to implement really. Anyway what i was wondering is if anything is removing your intended include paths from the total before that error is thrown.
Justin
+7  A: 

You could put a "Zend_Session::writeClose(true);" at the end of your index.php.
This will write the session into a persistent state before necessary Objects (Zend_Loader etc.) get destructed.

Better: Register it as shutdown function.
So it will be executed even if you use exit(), die() or a fatal error occures:

register_shutdown_function(array('Zend_Session', 'writeClose'), true);
Benjamin Cremer
This solved it for me, using APC.
smoove666
Credit for register_shutdown_function goes to hogberg and battal.
Benjamin Cremer
+1  A: 

I LOVE YOU!!! YOU MADE MY DAY!

After 3 days struckling of sessiondata is getting lost i found this post, and damned!! it works!!!

Nico

Nico
+2  A: 

It is probably similar to the problem with custom session handling and APC-cache. If you have assigned a custom session handler it is registered with RSHUTDOWN in PHP. It is the same routine that APC uses and will therefor create an internal conflict in PHP and your custom session handler will not close in all situations.

So you will have to make sure you manually close the custom session handler at shutdown

Putting a "Zend_Session::writeClose(true);" at the end of your index.php is not the best way to do that in case you have any exit; calls in your scripts anywhere.

It is better to register a shutdown handler in this way:

function shutdown()
{
 Zend_Session::writeClose(true);
}

register_shutdown_function('shutdown');

Put that in top of your index.php file to make sure that the shutdown procedure is registered before any other scripts are run.

Hogberg
A: 

@hogberg Thanks a lot for putting me out of my misery! :)

JohnB
A: 

Thank you very much, it helped me a lot... I was wondering where the problem lies since about two weeks and finaly used google and found your anwers ;)

Hikaru
A: 

Benjamin Cremer, you're a life saver. While the above (original) problem is a special case of autoloading with sessions, closing the session seems to be a general solution for such cases. A note though:

Placing Zend_Session::writeClose(true); at the end of your scripts may not always cut it, since you may have exit;'s, die();'s, etc in your code. In this case, you can use

register_shutdown_function(array('Zend_Session', 'writeClose'), true);

or, simply

register_shutdown_function('session_write_close');

if you do not use Zend for sessions.

battal