Hi, You should search this forumfor 'requestAction' first, IMHO. Then
read implementation of Object::requestAction(), Dispatcher::dispatch(),
Dispatcher::_invoke() and Dispatcher::start(). Source code will give
You best possible informations - CakePHP is about 150 files only ;-)
> If you do a requestAction() does this actually go thru the dispatcher
> and all that again?
Yes. As You can call URL's containing Your custom routes, it has to be
done by this way.
> Wouldn't it be more economical to call the controller
> directly? Of course, then I guess both ways the controller is loaded
> into memory either via the uses or on the fly with requestAction.
It depends on Your way how You're programming.
Answer is complex and there will be more points then one (I hope).
You can write very complex controller with plenty of used
components/helpers and/or automatic layout/language/ui dependencies and
drive load process of every component in proper methods in Your
controller.
COMPONENTS
If You have component which holds some data and You don't want to
re-generate them 'inside' of every requestAction() call, share those
data (or objects) through ClassRegistry singleton. You can also
implement method startup(&$controller) in Your component and in
controller::beforeFilter() set some variable like
$this->MyComponent->disableStartup = false;
and Your component will not execute what You will not want to execute
;-)
It is also possible do some hack and rewrite
controller::_initComponents() method, as in this method are $params of
controller already initialized - but I don't recommend this way as it
will not work for webservices and this method isn't supposed for such a
thing.
MODELS
see Controller::constructClasses(). Until this method is called inside
of Dispatcher::dispatch() You can manage $uses variable in controller.
Or You can implement method
function constructClasses() {
if (isset($this->params['custom_uses'])) {
// we want to set $uses variable manually
$this->uses = $this->params['custom_uses'];
}
else if (empty($this->params['bare'])) {
// we will render view inside of layout
$this->uses = array('User', 'UserProfile', 'Group',
'Permission');
}
else {
if (empty($this->params['return'])) {
// we will return rendered view through requestAction($url,
array('return'))
$this->uses = array('User', 'Group', 'Permission');
}
else {
// we will return value through requestAction($url)
$this->uses = array('User');
}
}
parent::constructClasses();
}
With this method implemented in Your controller:
- if it will be called from browser by non-bare (non-ajax,
non-requestAction) call, it will have 4 models initialized.
- if it will be called through call
$someData = $this->requestAction('/my_controller/my_action/',
array('custom_uses' => array('Permission')));
then only 'Permission' model will be attached. You can off course call
requestAction with array('custom_uses' => null) as second parameter :)
- if it will be called through call
$someData = $this->requestAction('/my_controller/my_action/',
array('return'));
then only 'User' model will be attached.
- if it will be called through call
$someData = $this->requestAction('/my_controller/my_action/');
then 3 models will be attached.
In fact: model instances are shared in during lifetime of script and if
You will consider variable $persistModel in Your controller, You can
probably completely forget about initialized models in Your controller.
You have think about MVC rule one-controller-for-one-model, model
inheritance (more then one model with one table) and precisely defined
associations with dynamic bind/unbind instead. Your controllers/models
could be in different places of class hierarchy, You know.
AppController and AppModel aren't only possible parent classes ;-)
VIEW CLASS AND HELPERS
..are loaded just before rendering of controller's action (if
$autoRender or render() call). If Your action is not rendered, view
instance and helpers aren't created. After render of action all helpers
calls their afterRender() methods, then if $autoLayout is rendered
layout. Nothing special - if You don't use array('return') as Your 2nd
argument of requestAction() or You don't use $this->render() in Your
controller's methods, You don't have to care about views and helpers as
they will not be instantialized.
URL BASED CACHING OF VIEWS
I left idea use it (for some time), as cached pages breaks DTD in time
I played with this feature. Besides: most of complex layouts have
somewhere inside of view/element digged <nocache>, so to be honest - in
compare with cache() function I didn't see some surprising growing
performance with cached actions. Almost OT: I just can't wait what is
happening in CakePHP kitchen with Dispatcher on the table - then I will
transform my i18 implementation from cookies/sessions to url's and
after this url-based multilanguage CakePHP built-in caching will arrive
to my desk again ;-)
BEHIND STAGE............
One of class which creates it's own instance of controller is
ErrorHandler.
(BTW OT: You can implement class AppError extends ErrorHandler { } in
app/error.php file and extend it's functionality)
Just take a look to ErrorHandler::__construct() and
ErrorHandler::error(). You will get a picture IMO. So when You will
have got an idea how controller starts and has to be initialized, You
can create instance of controler at every place You want, or even
better place it into ClassRegistry under some unique string key and You
can use it from anywhere, as ClassRegistry is singleton with static
methods.
> Also, do you advise multiple requestAction calls in the views?
In most of cases I'm using requestAction(), I never render through this
method. I'm using it only for returning values and - I'm considering
using of ClassRegistry of cache() for every of them in proper places.
So - for example I'm rendering my menus in element, which uses cache()
and then requestAction (if needed). Those talks about requestAction()
are mostly about fragments in layout, IMHO - navigation, info boxes,
homepage summary etc. Most of them could be cached with dirrerent
caching time, off course.
As I said, it depends on You, or on way You like. But if You're trying
call other controller's frequently, or even more (then one) other
controller's calls in one method, You're doing something wrong IMHO.
> I would think this should be placed in the controller itself since it is
> somewhat code and then set a variable of the results for the view to
> use.
requestAction() method is defined in class Object. See
http://api.cakephp.org/hierarchy.html
> ... what is CORRECT CakePHP in terms of cross controller
> calling and how to optimize it for speed ...
What is CORRECT will answer some CakePHP developer surely, I'm leaving
this question as it is ;-)
PERFORMANCE HITS
- Controller::persistModel variable
- smart using of cache() and ClassRegistry
- CakePHP MVC rules and proper functionality in proper piece of
application (app_controller, controller, component, app_model, model,
behavior, view_class, helper, view, element, layout)
- with knowledge of CakePHP code (just 150 files, You MUST KNOW how it
tastes inside...) You can drive whole process in proper methods of
proper objects, so in case of complex multi-choice-full-featured
applications You will end with Your own view class(es), error
class(es), dynamic routes, etc etc... :-)
- some PHP opcode cache like XCache or eAccelerator
>From my angle of view there are mainly 3 beautiful pieces of CakePHP:
- development strategy (and team, off course ;)
- speed of prototyping applications builded from ground (db schema, no
code)
- possibility of any change of any behaviour until it will not break
MVC, so everything is possible
So, let's discuss... ;-)
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Cake
PHP" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/cake-php
-~----------~----~----~----~------~----~------~--~---