How to fill sidebar content in a symfony layout? - php

I am building a simple application using Symfony. The page layout consists of a main body with left and right sidebars. The sidebars contains several modules which are user configurable.
Symfony provides slots which seem to be the correct way to fill the sidebars:
layout.php
<div id="left_sidebar">
<?php if (has_slot('left_sidebar')): ?>
<ul>
<?php include_slot('left_sidebar') ?>
</ul>
<?php else: ?>
<!-- default sidebar code -->
<?php endif; ?>
</div>
To fill the slots I tried using a filter. The problem is that some modules in the sidebars depend on what happens in the actions (category updates etc). So they should be generated after the action has run to completion.
msBootstrapFilter
class msBootstrapFilter extends sfFilter
{
public function execute($filterChain)
{
// Generating the sidebars at this point is TOO early
// as the content of some sidebars depends on the actions
// Execute next filter
$filterChain->execute();
// Generate the sidebars after running through all the code
// This is TOO LATE, the layout has been rendered
$this->generateSidebars();
}
}
I do not want to add a "run sidebar" call to each action as that seems inflexible.
What is the best point in the Symfony event flow to generate the sidebar content ? Is there a suitable event that I can connect to?

You can use a component? Which basically is a slot with some sort of action attached to it. In your action you can do whatever your logic needs and render it in the same way as above, but with more logic.
From the manual:
A component is like an action, except
it's much faster. The logic of a
component is kept in a class
inheriting from sfComponents, located
in an actions/components.class.php
file. Its presentation is kept in a
partial. Methods of the sfComponents
class start with the word execute,
just like actions, and they can pass
variables to their presentation
counterpart in the same way that
actions can pass variables.

Related

Change layout file within a view in Yii2

I am doing a small project using Yii2.
Suppose I have same layout (header, footer) in a view (eg site) except a login.php in this view. I want a different or no header / footer in this file. What can I do the remove the header / footer only from this view file.
All I could get to change layout in different views. Is it possible to change layout in a single file of a view?
Inside the relative action:
public function actionYourAction($id)
{
$this->layout = 'yourNewLayout';
return $this->render('yourView', [
'model' =>$model,
]);
}
I am a little late to the party, but you CAN change your layout from within your view. You do not have to declare it in your controller. I personally think it is better to do it in the view, because you can easily see later what is going on. If your making HTML edits, you would go into the view file, and easily be able to see which layout it is using. Putting this in the Controller, you (or someone later on) might miss the layout change nested into your controller's action.
Since $this refers to your view in Yii2 and not your controller as it did in Yii1, the old $this->layout doesn't work anymore from within your view.
Now, in Yii2, you refer to the controller from your view using $this->context.
$this->context->layout = 'your-layout';
In my project I wanted 2 layouts: one for site and one for the webapp. As the main.php file is the default layout, I've created a site.php layout and in the beginning of the siteController, just after the class declaration, I've put
public $layout = 'site';
The result is that only the siteController rendered views are using the site.php layout. It worked for me.
I'm also a litte late to the party, but struggled with this stuff today...
To me, to create a separate layout just because I want to skip the footer or header seems like much code for little win. If I can stick to the main layout, I can just get at the controller and the action
currently loaded, and have it omitted this way (write this in main.php):
$contr = Yii::$app->controller->id;
$action = Yii::$app->controller->action->id;
$skipFooter = $contr == 'site' && $action == 'login'; //...or enter here what U want
... and then later:
<?php if (!$skipFooter): ?> //Never at login...
<footer class="footer">
<div class="container">
<p class="pull-left">© YourSite.com <?= date('Y') ?></p>
<p class="pull-right"><?= Yii::powered() ?></p>
</div>
</footer>
<?php endif; ?>

What is Layout and what is View in ZF? When and whose variables should I use and why?

I can't understand when to use Layout's variables and when to use View's variables to get page segments on the page. Here is the picture form their Layout package tutorial ($this means the View instance everywhere):
Why Navigation, Content and Sidebar segments are got as Layout variables?
$this->layout()->nav;
But HeadTitle, HeadScript, HeadStylesheet are got straightly from View?
$this->headTitle(); // I know that this is a placeholder view helper.
// But this segment of the page logically belongs to Layout.
// and it has to be called smth like view->layout->placeholder
And why Header and Footer are from some partial method of the View but not Layout's properties?
$this->partial('header.phtml');
I've tried to change them and both ways work fine:
echo $this->nav; // I assigned navigation segment script to the View and it works;
I tried to assign Footer segment script to the Layout and it also works:
$layout->footer = $footer;
echo $this->layout()->footer; // it also works, it's displayed on the page
Any of the ways may be applied to any variable on the page. For example in Navigation segment I have a lot of variables to display and I can output them using both ways - one variable as Layout's property, another one sa View's property.
So what is the rule to use them right way? When should I use View's variables and when Layout's ones?
I agree that this isn't very clear from the documentation, and I don't think $this->layout()->nav is explained at all. A few points that might help:
$this->layout() is actually a call to the layout view helper, which returns the current instance of Zend_Layout.
Zend_Layout registers its own placeholder helper (with the key 'Zend_Layout'), and by default creates a 'content' variable in this.
the Zend_Layout class has a magic __get() method which proxies any member variable calls over to its registered placeholder container. So calling $this->layout()->content is another way of writing $this->placeholder('Zend_Layout')->content
the Zend_Layout class also has a magic __set() method that proxies stored data to the placeholder class. So $layout->footer = 'foo' is the same as calling $this->placeholder('Zend_Layout')->footer = 'foo' in the view
With that in mind:
Why Navigation, Content and Sidebar segments are got as Layout variables?
As these are accessing data stored in Zend_Layout's placeholder. You could also use $this->placeholder('Zend_Layout')->content
But HeadTitle, HeadScript, HeadStylesheet are got straightly from View?
These are view helpers.
And why Header and Footer are from some partial method of the View but not Layout's properties?
This is the standard way of accessing content from other templates.
In general, assume that using the view object is the correct way to access the data. Use the layout object/helper only if you know the data is in the layout placeholder.
The advantage of using placeholders over partials is that you can access and modify them in several different places, including in the view itself. For example say you had a sidebar which is stored in a partial. If you were to store this in the Zend_Layout placeholder instead (for example in a controller plugin), you can then override this for certain actions in the controller:
public function someAction()
{
$this->view->layout()->sidebar = 'Some other sidebar content';
}
or in the view script itself:
<?php $this->layout()->sidebar = 'Content for this page only'; ?>

Getting the hang of CodeIgniter - Templating / loading views

Attempting to learn CI and going through the docs to get a better understanding. Without getting a separate library, I could make a template by including a list of views like so:
$this->load->view('header');
$this->load->view('navigation');
$this->load->view('sidenav_open');
$this->load->view('blocks/userinfo');
$this->load->view('blocks/stats');
$this->load->view('sidenav_close');
$this->load->view('content',$data);
$this->load->view('footer');
This makes sense but would I actually have that on each of my controllers (pages)? Not sure if there is a way to include this in the initial controller (welcome) and then in the others somehow reference it? Or perhaps there is something I am missing completely
You can load views from within a view file. for example, consider a generic page template called page_template.php:
<html>
<body>
<div id = "header">
<?php $this->load->view('header');?>
<?php $this->load->veiw('navigation');?>
</div>
<div id = "sidenav">
<?php $this->load->view('sidenav');?>
</div>
<div id = "content">
<?php echo $content;?>
</div>
<div id = "footer">
<?php $this->load->view('footer');?>
</body>
</html>
Load your more dynamic areas by making use of codeigniter's abiltiy to return a view as a variable in your controller:
$template['content'] = $this->load->view('content',$data,TRUE);
$this->load->view('page_template',$template);
By passing TRUE to the load function, CI will return the data from the view rather than output to the screen.
Your sidenav section could be it's own view file, sidenav.php, where you have your 'blocks' hard-coded or loaded similar to the above example.
I've done it both ways, including every stinking bit of views in each controller method, and by using a page template that loads sub-views and dynamic areas, and by far, the second method makes me happier.
Loading views from within views can lead to confusion.
Extending the Controller class hides much of the complexity that comes from that approach, but still utilises the idea of generating common views (footer, header, navigation bars, etc) by rendering them once on every page load.
Specifically, consult the CI User Guide and wiki for references to MY_Controller - you extend this by creating a MY_Controller.php file in the ./libraries directory.
In there you can call view fragments, also utilising the third-parameter=true feature of the load->view() call. You load these into $this->data - for example loading the footer into $this->data['footer']. In your various controllers, continue adding view data to $this->data. In your views - I typically use a template that does little other than skeleton HTML and some basic CSS, and then echos the entire header, footer, nav and main content lumps as variables taken from $this->data
Added bonus - if you're new to CI, you'll likely soon be looking for how to do other things that a MY_Controller will make easy for you :)
I've got a wiki page on simplifying the generation and display of view partials, as you're trying to do here, using MY_Controller at:
https://github.com/EllisLab/CodeIgniter/wiki/Header-and-Footer-and-Menu-on-every-page---jedd

Magento module - overridden a controller, adding templates

I am currently working on a Magento extension, and I have overridden a core controller, which works fine.
I have now added a new action to my controller. Problem is that whenever I call the action a blank page is produced. If I echo something it is displayed correctly.
Therefore I dug into the core of the Customer module and controllers. I saw there that methods like indexAction() implement the layout this way:
<?php
public function indexAction()
{
$this->loadLayout();
$this->_initLayoutMessages('customer/session');
$this->_initLayoutMessages('catalog/session');
$this->getLayout()->getBlock('content')->append(
$this->getLayout()->createBlock('customer/account_dashboard')
);
$this->getLayout()->getBlock('head')->setTitle($this->__('My Account'));
$this->renderLayout();
}
I transferred this to my own action and the layout is now rendered correctly. Now for the question:
No matter what I enter into the ->createBlock('...') call, nothing is rendered into the content area.
How do I specify the location of my own block to be rendered as the content of the page while still decorating it with the layout?
I tried fiddling with the xml files in /design/frontend/base/default/layout/myaddon.xml but couldn't really make it work.
Covering the entirety of the Magento layout system in a single StackOverflow post is a little much, but you should be able to achieve what you want with the following.
$block = $this->getLayout()->createBlock('Mage_Core_Block_Text');
$block->setText('<h1>This is a Test</h1>');
$this->getLayout()->getBlock('content')->append($block);
Starting from the above, you should be able to build up what you need. The idea is you're creating your own blocks, and then append them to existing blocks in the layout. Ideally, you're creating your own block classes to instantiate (rather than Mage_Core_Block_Text), and using their internal template mechanism to load in phtml files (separating HTML generation from code generation).
If you're interested in learning the internals of how the layout system works, you could do a lot worse than to start with an article I wrote on the subject.

Best practice creating dynamic sidebar with zend framework

What is best practice to create dynamic sidebar or other non content layout places with zend framework. At this moment I created controller witch i called WidgetsController. In this controller i defined some actions with 'sidebar' response segment for my sidebar and in IndexController i call them with $this->view->action(); function but I don't think that is a best practice to create dynamic sidebar.
Thanks for your answers.
You question doesn't provide many details. Generally, I'd say load the sidebar as view template, via the render/partial methods of the view. So from inside a view:
//$data is dynamic data you want to pass to the sidebar
echo $this -> partial('/path/to/sidebar.phtml',array('menuitems' => $data));
And then sidebar could process that dynamic data:
//sidebar.phtml
<div id="sidebar">
<?php foreach($this -> menuitems as $item) : ?>
<?php echo $item['title']; ?>
<?php endforeach; ?>
</div>
If you need extra functionality, you could create a dedicated view helper to handle it.
This works for ZF 1.11: A dynamic sidebar implementation in Zend Framework
Yes, folks, my bet is that the answer from the Code Igniter folks is the correct approach.
Actually its helpful to see how CI does it simply, and to make comparisons.
It's basically the same in ZF, except that instead of the "named view" ZF has "Partials".
ZF simply has more imposed discipline, such as layouts + views + partials, and more internal machinery to implement this, which actually does make it run half as fast,
whereas code igniter just seems to have flattened this whole apparatus into "named views".
(I haven't yet made up my mind as to whether ZF has over-cooked it or whether some CI steaks have to remain raw in the middle.)
If you use $navigation->setPartial(blah blah) then the leadup array (technically this kind of data constitutes the "model" part of the MVC thing) and is made available to the partial.
So there you have it, the idea seems to be don't pull the display aspects of the model into the controller, push the model display stuff out to the view processing machinery.
I am just about to have a go at this myself, I did do a search on partials in the view helpers section of the Zend Manual to find this, even though the examples are a bit thin.
Wish me luck
Keith
We'd like some more details, i.e what sort of content is shown in the sidebars, how you show them (i.e using a <ul>, <div> or something else), is the content retrieved from a database, etc.
In CodeIgniter which also uses the Model, View, Controller format, we create a view called 'sidebar.php' and in the Header view, we include a call to this sidebar view, i.e:
<html>
<head>.......</head>
<div id="header">....</div>
<?php $this->load->view('sidebar');?>
The sidebar view contains the logic for showing the menu items. Usually it is a static menu, but if it was dynamic and had to be fetched from the database, I would do this:
<ul>
<?php
$items=$this->some_model->getMenuItems();
foreach ($items as $item):
?>
<li><a href="<?=$item['url'];?>"><?=$item['text'];?></li>
<?php endforeach;?>
</ul>

Categories