> Hi folks, > > after discussing the idea with various PHP developers > I now felt safe enough that it's not a completely stupid > idea to post an RFC for it. The idea is to add support > the registration of > custom factories which are > responsible for instantiating certain classes. > > Here is the first draft of my RFC: > http://wiki.php.net/rfc/customfactories
Robert, Slightly different idea, why not to generalize the way of class-load and class-instantiation in php and make existing auto-load feature implemented as a part of it? It should be flexible enough and allow to work with auto-loading files and/or factories to be called for the class instance. Class instantiation is an important thing itself and PHP should support certain interface for this. So all the factories will have at least one common interface. Similar stuff works great in Mozilla (XPCOM) and MS' COM. I mean IFactory and nsIFactory: interface nsIFactory : nsISupports { /** * Creates an instance of a component. * * @param aOuter Pointer to a component that wishes to be aggregated * in the resulting instance. This will be nsnull if no * aggregation is requested. * @param iid The IID of the interface being requested in * the component which is being currently created. * @param result [out] Pointer to the newly created instance, if successful. * @return NS_OK - Component successfully created and the interface * being requested was successfully returned in result. * NS_NOINTERFACE - Interface not accessible. * NS_ERROR_NO_AGGREGATION - if an 'outer' object is supplied, but the * component is not aggregatable. * NS_ERROR* - Method failure. */ void createInstance(in nsISupports aOuter, in nsIIDRef iid, [retval, iid_is(iid)] out nsQIResult result); /** * LockFactory provides the client a way to keep the component * in memory until it is finished with it. The client can call * LockFactory(PR_TRUE) to lock the factory and LockFactory(PR_FALSE) * to release the factory. * * @param lock - Must be PR_TRUE or PR_FALSE * @return NS_OK - If the lock operation was successful. * NS_ERROR* - Method failure. */ void lockFactory(in PRBool lock); }; similar thingy can be found in COM. In PHP terms it'd be much easier: interface IFactory... { /** * @returns mixed class instance initialized with default constructor * @except throws descendant of EFactory exception in case of errors */ function CreateInstance(); } /** * @desc nothing new in this class except its class name that can be used for filtering exceptions in catch() */ class EFactory extends Exception {}; Regarding your sample, "class SystemLogger implements LoggerInterface" is nothing more but a classic singleton. It creates one and only one instance and always return it. In terms of XPCOM or COM it can be created with appropriate flags used in the factory template. See SINGLETON attribute in mozilla sources. While the factory is a standalone instance or static class that can only create instances or instance of another certain class. For example LoggerFactory would create SystemLogger instances (instance). This is proven technology and works good for more than 10 years. Regarding such contructs like $this->logger->log() in SomeService, it's known that many classes are partially or wholly wrappers around one or many instances in them. With SomeService, one can introduce log method in it like: class SomeService { ... log($msg) { $this->logger->log($msg) } } and call $this->log() instead of $this->logger->log(), as it's shorter and more readable. But in cases when inner instance have many methods to be wrapped, such dummy code may waste too much space. So I'd propropose to implement a "delegate calls to instance" feature. It may look like below delegate_calls($delegator, $delegatee, $interface). For example delegate_calls($this, $this->logger, LoggerInterface) can be called and after that you'll call any methods defined in LoggerInterface interface with $this instance but in fact method in $this->logger will be called. Such delegation would simplify sources: $this->log('aMethod has been called.'); instead of $this->logger->log('aMethod has been called.'); I know, __call() can be used to delegate calls too, but with this way I'd have to intercept __call and repeat the same method body each time I need delegation. -jv -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php