Reputation: 1503
I've got a CRUD application, and in my views there are links to actions from various controllers e.g.
<?php echo $this->Html->link(__('List Docs'), array('controller' => 'docs', 'action' => 'index')); ?>
<?php echo $this->Html->link(__('Add Doc'), array('controller' => 'docs', 'action' => 'add')); ?>
<?php echo $this->Html->link(__('List Images'), array('controller' => 'images', 'action' => 'index')); ?>
<?php echo $this->Html->link(__('Add Image'), array('controller' => 'images', 'action' => 'add')); ?>
//etc..
Now, I also have a default.ctp layout with a sidebar that I'd like to dynamically populate with the action links from each view being rendered. I know that I can move the actions from my controllers to their respective models and set variables in a beforeRender() callback within a controller, however i'd like to keep my actions within the controllers, and instead set an array within a view and pass it to the default.ctp layout. Here's what I have so far:
Docs/index.ctp:
$links_array = array(
'list_docs' => array('controller' => 'docs', 'action' => 'index'),
'add_doc' => array('controller' => 'docs', 'action' => 'add'),
'list_images' => array('controller' => 'images', 'action' => 'index'),
'add_image' => array('controller' => 'images', 'action' => 'add')
);
$this->set('links', $links_array);
Layouts/default.ctp:
print_r($links);
This returns Notice (8): Undefined variable: links [APP\View\Layouts\default.ctp, line 93]
I'm guessing because the layout is being rendered before the view.
What's the best way to go about doing this without moving actions to their models?
Upvotes: 2
Views: 15596
Reputation: 1839
This is even better: using blocks for script and css files
You can define a block name, like scriptBottom.
Append contents to it and display in the right place on your layout or another view.
// In your view
$this->Html->script('carousel', ['block' => 'scriptBottom']);
$this->Html->script('custom', ['block' => 'scriptBottom']);
//or
$this->startIfEmpty('scriptBottom');
$this->append('scriptBottom', $this->script('custom2'));
// In your layout or another view
<?= $this->fetch('scriptBottom') ?>
Upvotes: 1
Reputation: 4969
$links_array = array(
'list_docs' => array('controller' => 'docs', 'action' => 'index'),
'add_doc' => array('controller' => 'docs', 'action' => 'add'),
'list_images' => array('controller' => 'images', 'action' => 'index'),
'add_image' => array('controller' => 'images', 'action' => 'add')
);
$this->set('links', $links_array);
... should be in the controller.
The layout will see any variable that is available in the view. So $links
will be visible in the layout. (and if you really have to set vars from the view instead of the controller, you don't need to use $this->set()
in the view, just use $links = ...
).
Upvotes: 4
Reputation: 29007
Have you considered using View blocks? The manual even uses a sidebar as an example for it's use; Using View Blocks
// In a view file.
// Create a navbar block
$this->startIfEmpty('navbar');
echo $this->element('navbar', array('links' => $links_array));
$this->end();
// In a parent view/layout
echo $this->fetch('navbar');
Upvotes: 3