-- Nick Lo <[EMAIL PROTECTED]> wrote (on Wednesday, 06 December 2006, 03:09 PM +1100): > Aha, now I get it ...so what I CAN do is:
<snip -- code examples> > So in short init() is a convenience method which is fine. Correct. It's to make it easier on you, the developer, so you don't have to write out that nasty __construct() line. :-) > I was just uncomfortable with the idea of being forced to use it on > the basis that things otherwise broke (which they don't - my mistake) > and that I may forget to properly initialise the parent class. > > Thanks very much for your detailed (and patient) responses, I now > follow it a lot more clearly. No problem! Glad I was able to clarify things. > >-- Nick Lo <[EMAIL PROTECTED]> wrote > >(on Wednesday, 06 December 2006, 01:00 PM +1100): > >>Hi Matthew, > >> > >>>init() happens at object instantiation, which happens before > >>>preDispatch() -- it's basically provided so that you don't need to > >>>override the constructor, and thus possibly forget to set the > >>>request, > >>>response, and other parameters (as you discovered the hard way). > >> > >>It does seem like having init() as a means to bypass the constructor > >>and also having preDispatch() is possibly a little unintuitive. > >>Surely init() is a constructor of sorts? > > > >It's not meant to bypass the constructor; it's meant as a means to > >allow > >further instantiation actions without needing to override the > >constructor. > > > >Matt Ratzloff asked "why not declare it final?" My answer to this is > >backwards compatability; by not declaring it final, developers instead > >can fix their classes as they start needing some of the functionality, > >such as access to the request object, instead of having their apps > >break > >entirely due to the constructor now being final. (There were a lot of > >complaints about this.) > > > >>In theory I can set the request and response.... > >> > >>$controller->setRequest( new Zend_Controller_Request_Http ); > >>$controller->setResponse( new Zend_Controller_Response_Http ); > >> > >>...as I do the router... > >> > >>$controller->setRouter($router); > > > >This latter is only in the front controller. > > > >> > >>...but it will still be required to specified in the constructor of > >>classes overriding __construct... > >> > >>parent::__construct( new Zend_Controller_Request_Http, new > >>Zend_Controller_Response_Http ); > >> > >>...however at that point the parameters will not be available. > > > >Umm... yes, they will, if you define your constructor to follow > >Zend_Controller_Action's prototype: > > > > public function __construct( > > Zend_Controller_Request_Abstract $request = null, > > Zend_Controller_Response_Abstract $response = null, > > array $invokeArgs = null) > > {} > > > >then simply do this: > > > > public function __construct(...) > > { > > parent::__construct($request, $response, $invokeArgs); > > > > // ... > > } > > > >>It seems that if we have to follow the init() path the manual is > >>going to have to say something like... > >> > >> "If you subclass Zend_Controller_Action you should not override the > >>constructor instead setup code should go in the init() method" > > > >It does say that. In the current manual from subversion: > > > > "While you may override the constructor, we suggest putting any > > initialization handling into init() to ensure the request and > > response objects are properly registered." > > > >>In other words it will need to be a warning. That is where I feel > >>that init() is unintuitive and most people (I say with hesitation > >>being a self elected representative) would expect to go with the > >>constructor for this task. > >> > >>Note also that I didn't forget to set the request and response > >>objects when I overrode the constructor, rather that when I did set > >>them in the subclass no parameters were available in the controller. > > > >You set them improperly, though. You created *new* objects, instead of > >simply passing in the parameters that were passed to your constructor. > > > >>>Theoretically, if something goes wrong during the initialization > >>>sequence, you could throw an exception, in which case the > >>>preDispatch() > >>>will not be called -- this may be handy so that you can, for > >>>instance, > >>>setup your models, etc., and, if unavailable, prevent the action > >>>from > >>>dispatching. preDispatch() might then actually use the models to do > >>>some > >>>determination of whether or not to skip the current action. > >> > >>I follow the theory and I'd be interested in hearing how others are > >>using preDispatch and whether their use really does differentiate > >>init > >>() from preDispatch() in the way you mention. > > > >Here's how I'm using it in one of my applications. I have this in a > >Zend_Controller_Action subclass from which my other classes then > >derive: > > > > public function init() > > { > > // Loads the model based on the current action, which will > >throw > > // an exception if there are issues > > $this->loadModel(); > > > > // Load up authentication and start it. Again, throws an > > // exception if there are issues > > $this->getAuth()->start(); > > } > > > >Then, preDispatch() is defined on a per action controller basis. Some > >may set certain ACLs -- which require that authentication has already > >begun. Some may query the model based on user information, and > >decide to > >forward to another controller. > > > >Which brings up another point: init() should not change the requested > >action; preDispatch() may do so, forwarding to another action if > >certain > >criteria are not met. > > > >Hope this helps answer some questions. I think there's still some > >wiggle > >room inthe API, but many of the decisions have been debated or are > >based > >on user feedback already. > > > >-- > >Matthew Weier O'Phinney > >PHP Developer | [EMAIL PROTECTED] > >Zend - The PHP Company | http://www.zend.com/ > -- Matthew Weier O'Phinney PHP Developer | [EMAIL PROTECTED] Zend - The PHP Company | http://www.zend.com/