I'll check out your proposal Federico - been a few months since I had time to 
do anything ZF related so catching up ;).

If indeed Zend_Di is accepted I would primarily suggest this specific interface 
is as simple as possible since in controllers not making full use of DI it's 
primarily a simple pass through method to Zend_Loader::loadClass() and 
ReflectionClass::newInstanceArgs(). I'll raise a comment on the proposal when 
I've reviewed it then!

Thanks,
Paddy
 
Pádraic Brady

http://blog.astrumfutura.com
http://www.patternsforphp.com
OpenID Europe Foundation Member-Subscriber


----- Original Message ----
From: Federico Cargnelutti <[EMAIL PROTECTED]>
To: Pádraic Brady <[EMAIL PROTECTED]>; Zend Framework 
<[email protected]>
Sent: Thursday, January 17, 2008 11:17:08 PM
Subject: Re: [fw-general] Zend_Factory/Zend_Loader addition suggestion




 
DIV {
MARGIN:0px;}



Have you seen my proposal, Zend_Di? I needed 
something similar and I developed that component. I've using it for 
quite some time now. The problem with Pico and Phemto is that you need to adapt 
your API to their injectors, this doesn't happen with Zend_Di, 
it adapts to your API. 

 

The problem with Pico is that it's way to heavy, 
and Phemto is way to simple and only supports CI.

 

Check out the proposal:

http://framework.zend.com/wiki/display/ZFPROP/Zend_Di+-+Dependency+Injection+Container

 

The code you posted is similar to the one found in 
Zend_Di_Component_Factory

 

Cheers,

Fede

 


  ----- Original Message ----- 

  From: 
  Pádraic 
  Brady 

  To: Zend Framework General 

  Sent: Thursday, January 17, 2008 9:20 
  PM

  Subject: [fw-general] 
  Zend_Factory/Zend_Loader addition suggestion

  


  Hi 
  guys,

I'm currently working on a project to implement Zend Framework 
  controller and model testing and specification. I'm looking for opinions on 
  whether this is feasible - the main problem I have is that directly 
  instantiating objects within controllers makes it impossible for any testing 
  suite from isolating the controller action from it's carrying objects. 
Without 
  requiring some perverse parameter acrobatics or requiring configuration heavy 
  injectors like Pico or Phemto a simple solution (I think) is to enable a 
  simplified object loader of a few dozen lines to be added for use.

This 
  could be added either as a separate class Zend_Factory, or appended to 
  Zend_Loader (which seems appropriate). I've copied the current sample code 
and 
  unit tests below. In use, it would require a simple call 
  of:

Zend_Factory::create('Zend_Mail');

Then a unit test or BDD 
  spec could mock this object result (before the create() call of course) 
  using:

Zend_Factory::replaceClass('Zend_Mail', new 
  ZMail_Mock);

Here's the suggested source code and unit tests. Any 
  comments or criticisms most welcome - not sure if it's worth an actual 
  proposal given it's size but it's of immense value to my ongoing work. If you 
  prefer online viewing it's at: 
http://svn.astrumfutura.org/zendframework/trunk/library/Proposed/Zend/Factory.php

Zend/Factory.php:

<?php

require_once 
  'Zend/Loader.php';

require_once 
  'Zend/Registry.php';

/**
 * Abstract object instantiation with 
  minimal setup and allow for replacement
 * of created object return 
  values by preceding unit tests or BDD 
  specifications
 *
 */
class 
  Zend_Factory
{

    /**
     * 
  Registry instance for holding replacement objects
     
  *
     * @var Zend_Registry
     
  */
    protected static $_registry = 
  null;

    /**
     * Create a new 
  object based on the referenced class name and 
  construction
     * parameters. If a registered 
  replacement object exists, this will be
     * returned 
  instead.
     *
     * @param 
  object $className
     * @param array 
  $constructionParams
     * @return 
  object
     */
    public static 
  function create($className, array $constructionParams = null) 
  
    {
        if 
  (!class_exists($className, true)) 
  {
            
  Zend_Loader::loadClass($className);
        
  }
        if 
  (isset(self::$_registry->$className)) 
  {
            return 
  self::$_registry->$className;
        
  }
        if ($constructionParams !== 
  null) {
            
  $refClass = new 
  ReflectionClass($className);
            
  $createdObject = 
  $refClass->newInstanceArgs($constructionParams);
        
  } else {
            
  $createdObject = new $className;
        
  }
        return 
  $createdObject;
    }

    
  /**
     * Replace the return value of any call for an 
  instance of the referenced
     * class name with an 
  alternative object.
     *
     
  * @param string $className
     * @param object 
  $withObject
     */
    public static 
  function replaceClass($className, $withObject) 
    
  {
        if (self::$_registry == null) 
  {
            
  self::$_registry = new Zend_Registry(array(), 
  ArrayObject::ARRAY_AS_PROPS);
        
  }
        
  self::$_registry->$className = $withObject;
    
  }
    
    /**
     
  * Clear the registry of replacement objects
     
  *
     */
    public static function 
  clearRegistry()
    
  {
        if(isset(self::$_registry)) 
  {
            
  self::$_registry = null;
        
  }
    }
}

Unit Tests: 
  FactoryTest.php

<?php
/**
 * @package    
  Zend_Factory
 * @subpackage UnitTests
 */

require_once 
  dirname(dirname(__FILE__)) . '/TestHelper.php';


/** Zend_Factory 
  */
require_once 'Zend/Factory.php';


/** 
  PHPUnit_Framework_TestCase */
require_once 
  'PHPUnit/Framework/TestCase.php';

// pre included class used in 
  tests
require_once 'Zend/Mail.php';


/**
 * 
  @package    Zend_Factory
 * @subpackage 
  UnitTests
 */
class FactoryTest extends 
  PHPUnit_Framework_TestCase
{

    public function 
  testFactoryInstantiatesZendObjectAfterIncluded() 
    
  {
        $mail = 
  Zend_Factory::create('Zend_Mail');
        
  $this->assertTrue($mail instanceof Zend_Mail);
    
  }

    public function 
  testFactoryInstantiatesZendObjectBeforeIncluded() 
    
  {
        $gdata = 
  Zend_Factory::create('Zend_Gdata_Photos_AlbumEntry');
        
  $this->assertTrue($gdata instanceof 
  Zend_Gdata_Photos_AlbumEntry);
    
  }

    public function 
  testFactoryThrowsExceptionIfClassDoesNotExist() 
    
  {
        try 
  {
           $mail = 
  Zend_Factory::create('Zend_Foo');
           
  $this->fail('Did not throw an expected Exception on non-existent class 
  request');
        } catch 
  (Zend_Exception $e) {
        
  }
    }

    public function 
  testFactoryInstantiatesUsingConstructParams() 
    
  {
        $registry = 
  Zend_Factory::create('Zend_Registry', 
  array(array('index'=>'something')));
        
  $this->assertEquals('something', $registry['index']);
    
  }

    public function 
  testFactoryAllowsObjectReplacementForClasses() 
    
  {
        
  Zend_Factory::replaceClass('Zend_Registry', new 
  Factory_Foo);
        $class = 
  Zend_Factory::create('Zend_Registry');
        
  $this->assertTrue($class instanceof Factory_Foo);
    
  }

    public function 
  testFactoryChecksOriginalClassExistenceToPreventBlindReplacement() 
  
    {
        
  Zend_Factory::replaceClass('Zend_Foo', new 
  Factory_Foo);
        try 
  {
            $class 
  = 
  Zend_Factory::create('Zend_Foo');
            
  $this->fail('Expected exception since replaced class never existed which 
  means replacement could create blind 
  errors');
        } catch 
  (Zend_Exception $e) {
        
  }
    }
    
    public 
  function tearDown()
    
  {
       Zend_Factory::clearRegistry(); 
  
    }

}

class 
  Factory_Foo
{
}

Best regards,
Paddy

   
Pádraic Brady

http://blog.astrumfutura.com
http://www.patternsforphp.com
OpenID Europe 
  Foundation Member-Subscriber

  





Reply via email to