Getting the hang of CodeIgniter - Templating / loading views - php

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

Related

Loading laravel view with ajax

I am new to web development.I am using laravel for my app where i used blade templates for creating pages.I have a main blade in which my header and footer exist and i am using it as wrapper.I want all of other pages to be open in that without reloading that base template and when i open the page it extends the main wrapper with new view correctly but when i update that page's content with ajax content of that page doubles the footer that may be because #includes() that creates a new page within existing one but i want to fix that double content and footer.Please help!Here is the code of pages that i used to load within the main wrapper
#extends('wrappertemplate')
#section('content')
<div class="body-content">`
And the content is here
</div>
#stop
I would advise that unless it's a very simple use case/playground exercise, that you don't do it this way, and instead define a proper API using Laravel, then use a front end framework like React, Angular, Ember etc etc. to interact with this API and handle DOM manipulation/creation. Seems v bizarre to re-render the entire page using HTML loaded of Ajax. There are plenty of tutorials on using Laravel and Various Front End Frameworks
However, for what you asked, you need to first create a page that extends wrappertemplate which you have. This should load without any content in the body
Then create a blade file which has the html that you want - it shouldn't extend anything. Then you just have a route and controller method which returns the contents of this file.
Then all you have to do is get your HTML over ajax and append it to the body.
This is just a sample controller:
class PageController extends Controller
{
// This is your method which renders the page that is essentially a wrapper
public function home()
{
return view('pages.home');
}
// This is your route which returns a partial, i.e. the content which gets refreshed
public function content()
{
$html = view('partials.home-content')->with(['name'=>'ExoticChimp'])->render();
return response->json(['html' => $html]);
}
}
Then your views:
<!--pages.home-->
#extends('wrappertemplate')
#section('content')
<div class="body-content">`
And the content is here
</div>
#stop
<!--partials.home-content-->
<h1>Hello {{$name}}</h1>
Then you'd just append the html parameter in the response to your body-content using basic jquery or js. I'm not going to write the JS as well, just google making AJAX requests using jQuery and there are a ton of articles on this stuff. I must stress though that you should look into using Laravel + a front end framework.
Tutorial: http://culttt.com/2015/04/06/getting-started-with-laravel-and-ember/
You should read up on the Laravel documentation for controllers.
http://laravel.com/docs/5.1/controllers

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; ?>

Fat Free PHP Layouts

I'm going through some of the code and projects provided here http://fatfreeframework.com/development. My goal is to create a lightweight MVC kickstarter projecting using F3. I know it's been done before, but I'm using this as a learning exercise and I hope to have something useful come out of it in the end.
The biggest stumbling block I'm coming across right now is the concept of layouts. I know the documentation mentions using templates within templates, but I'm struggling to implement it in practice. In the end, I want to have 1 or 2 layouts (default layout, maybe a custom one for modal popups, etc), and then have my views rendered wrapped inside of those layouts. I want a default layout and then the ability to override the default for the few pages that need custom ones. Here's the code I've been using:
// this is the handler for one of my routes, it's on a controller class called Index
public function index($f3, $params)
{
// this (or anything else) should get passed into the view
$f3->set('listOfItems',array("item1", "item2"));
// set the view
$f3->set('content', 'index.htm')
// render the layout
\Template::instance()->render('layout.htm');
}
Unfortunately, I keep getting a blank page. Am I going about this completely the wrong direction, or am I on the right track? Is there a way to set a default layout somewhere so it's used until it's overridden?
Well you could create a base class with a default layout. Then you extend it for each controller class. For example:
abstract class Layout {
protected $tpl='layout.htm';
function afterRoute($f3,$params) {
echo \Template::instance()->render($this->tpl);
}
}
Then:
class OneController extends Layout {
function index($f3,$params) {
$f3->set('listOfItems',...);
$f3->set('content','one/index.htm');
}
}
class AnotherController extends Layout {
protected $tpl='popup.htm';//override default layout here
function index($f3,$params) {
$f3->set('listOfItems',...);
$f3->set('content','another/index.htm');
}
}
In layout.htm:
<body>
<div id="content">
<include href="{{#content}}" if="isset(#content)"/>
</div>
</body>
Structure of the UI folder:
/ui
|-- layout.htm
|-- popup.htm
|-- one
|-- index.htm
|-- another
|-- index.htm
This is just one example of how you could organize your code. F3 is loose enough to let you organize it in a multitude of ways.
I had exactly the same problem - set everything up as required, rendered the layout, and kept getting a blank page. Also when I checked the HTML source of the rendered page it was completely empty.
If you look closely however rendering the layout is not enough, you have to also print it using the echo command. So rather than the following example which appears at first glance to be correct:
$f3->route('GET /',
function($f3) {
// Instantiates a View object
$view = new View;
// Render the page
$view->render('template/layout.php');
you actually need the last line to start with echo:
echo $view->render('template/layout.php');
For more examples see:
http://fatfreeframework.com/views-and-templates
https://www.digitalocean.com/community/tutorials/how-to-use-the-fat-free-php-framework
http://takacsmark.com/fat-free-php-framework-tutorial-4-database-models-crud/
Also for some reason (which I'm sure will become clear soon - I've only just started using the Fat Free Framework) you seem to also be able to render an .htm file which contain embedded PHP (i.e. they don't have to have the .php extension).

How to fill sidebar content in a symfony layout?

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.

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