2010-03-19

Namespaced out of nothing...

I am currently trying to debug a very strange error I am seeing.

The Stage

FLOW3 in it's current SVN version, PHP 5.3.2 (MacPorts) on OSX 10.6.2, SwiftMailer 4.0.6

The Setup

I created a SwiftMailer package, in that exists a class that extends SwiftMailer's Message class. Now I ask the object manager in FLOW3 for an instance of that class. That all works fine when the static object container for FLOW3 has not yet been written. If the static object container is used, I get:

The Problem

But the problem is cause by something inside PHP, it seems, which is triggered somehow when FLOW3 is involved. Does it push PHP over it's edge? Here is the error I get:
Fatal error: Interface 'F3\Party\Domain\Model\Swift_Mime_HeaderSet' not found in /.../Swift/Mime/SimpleHeaderSet.php on line 23
Line 23 of SimpleHeaderSet.php looks like this:
class Swift_Mime_SimpleHeaderSet implements Swift_Mime_HeaderSet
Now, there is no namespace declaration in that file, so why on earth does PHP want to use F3\Party\Domain\Model\Swift_Mime_HeaderSet? I could not believe what I was seeing, and added some lines echoing __NAMESPACE__ to some files involved. This is the result:
namespace in SwiftMailer\Message constructor: F3\SwiftMailer
namespace in Swift_Message constructor:
namespace in SimpleHeaderSet file: F3\Party\Domain\Model
Message, check; Swift_Message, check; SimpleHeaderSet, .... WTF? Here is the backtrace to see what happens:
F3\FLOW3\Object\Container\StaticObjectContainer->c0294( ??? ) ../AbstractObjectContainer.php:0
F3\SwiftMailer\Message->__construct( ) ../StaticObjectContainer.php:4747
Swift_Message->__construct( ???, ???, ???, ??? ) ../Message.php:44
Swift_DependencyContainer->createDependenciesFor( ??? ) ../Message.php:38
Swift_DependencyContainer->_resolveArgs( ??? ) ../DependencyContainer.php:121
Swift_DependencyContainer->_lookupRecursive( ??? ) ../DependencyContainer.php:321
Swift_DependencyContainer->lookup( ??? ) ../DependencyContainer.php:345
Swift_DependencyContainer->_createNewInstance( ??? ) ../DependencyContainer.php:105
ReflectionClass->__construct( ??? ) ../DependencyContainer.php:277
Swift::autoload( ??? ) ../Swift.php:0
require_once( '/.../Swift/Mime/SimpleHeaderSet.php' ) ../Swift.php:44
As you can see, the namespace in Message is fine, as is the case in Swift_Message. Now the Swift_DependencyContainer comes into play and when ReflectionClass' constructor fires an autoloading request for Swift_Mime_SimpleHeaderSet the namespace magically changes to F3\Party\Domain\Model (the namespace is output in the first LoC of that file!).

I wrote a small script consisting of 5 require() statements and two lines of code to instantiate a Message using the static object container, but of course that works like a charm.

Any Hints

on how to debug this further are highly welcome. But I am rather certain that not anyone else on our planet ever had a similar problem. Do they use PHP and FLOW3 on the ISS?

5 comments:

tester said...

Whats with the HeaderSet Interface? Does that cause the problem?

tester said...

What happens if you deactivate the Party Package?
Or is it deactivated? What happens if you remove it?

tribble said...

Where do you construct the Swift_Message? When does the file SimpleHeaderSet.php get included?

Its says in the __NAMESPACE__: namespace in SimpleHeaderSet file: F3\Party\Domain\Model

I am not sure, but since no namespace is given in the file, can the namespace be inherited from the inclusion point? This should not happen, but it might be a bug in PHP. Could be a problem in the Reflection Class.

Or the Dependency Container does it. Does the SwiftMailer have some kind of autoload implemented, or did you replace that with FLOW3 autoloading mechanisms?

tribble said...

OMG, i just saw, this is a year old. Did you solve the problem? And if so, i would like to know, what the problem was, if you remember ;)

Chad said...

when referencing a class in one namespace (global namespace) from a class in another namespace F3\Party\... you will want to load the class using an explicit/absolute path.

In this case, when you are inside a class in the F3\Party\... namespace, and you load Swift (which is in the global namespace) you need to prefix Swift with a slash like so:

$m = new \Swift...();