I'm starting a large codeigniter project and would like to try to create some reusable 'mini' views for snippets of content like loops of data which may be displayed on different pages/controllers.
Is it better to call the views from within the main controller's view? If so, how? Or should I call the 'mini view' from the controller and thus pass the view's code to the main view?
Views within other views are called Nested views.
There are two ways of including nested views in CodeIgniter:
1. Load a nested view inside the controller
Load the view in advance and pass to the other view. First put this in the controller:
<?php
// the "TRUE" argument tells it to return the content, rather than display it immediately
$data['menu'] = $this->load->view('menu', NULL, TRUE);
$this->load->view ('home', $data);
?>
Then put <?=$menu?> in your view at the point you want the menu to appear.
2. Load a view "from within" a view
First put this in the controller:
<?php
$this->load->view('home');
?>
Then put this in the /application/views/home.php view:
<?php $this->view('menu'); ?>
<p>Other home content...</p>
About best method, I prefer the 1st method over 2nd one, because by using 1st method I don't have to mix up code, it is not like include php. Although indirectly both are same, the 1st method is clearer & cleaner than 2nd one!
Honestly I prefer to do this by having template views then loading that with the necessary data from the controller, it means a lot less repeated code and follows the DRY concept better than loading views from views. Especially for things like headers, footers and menus.
So my template view would look something like this:
template.php
$this->load->view('header',$title);
$this->load->view('sidebar',$sidebar_content);
$this->load->view('main_content',$main_content);
$this->load->view('footer');
Then in my controller I pass the data required to the template like this:
$data['title'] = 'Home Page';
$data['sidebar_content']='pages/standard_sidebar';
$data['main_content'] ='pages/my_home_page';
$this->load->view('template',$data);
There are a number of benefits to doing it this way. First is I can have multiple templates, for example I have, in my case, two main ones, one for full page views without a sidebar and one for pages with a sidebar, I also call an if statement to decide which header to include, the regular one or the one with the admin menu in it.
Yes I could include the header, sidebar and footer in every main view page, but that ends up in a ton of duplicate code. And what happens if for example I want all my pages to have something new, some other small snippet? Using templates I add the snippet to the appropriate template and it's done. Going the other route I find every page and add the snippet view there, it's the equivalent to having CSS in the page in my opinion, wasteful and not ultimately maintainable.
METHOD 1
I use this method into my view to insert the include view where I want
$this->load->view('include/include_view');
METHOD 2
or in the controller you can load more than a view like this:
$this->load->view('header_view');
$this->load->view('list_view');
$this->load->view('footer_view');
No one method is better than the other, it depends if you have to pass some data (in this case use method2) or if you want to include a view in a specific part of your main view (in this case is better to use method1)
METHOD 3
Passing data to your include view by your main view
into your controller:
$data['title'] = "Title";
$this->load->view('main_view',$data);
in your view
$data2['title'] = $title;
$this->load->view('include/include_view',$data2);
If you want to pass entire data to your include view you can do in this way:
in your controller:
$data['nestedView']['title'] = 'title';
in your view
$this->load->view('includes/included_view', $nestedView);
This a simple way of including views within views.there is no need to load views in advance.just pass view path to other view.
In your controller use this:
$data['middle'] = 'includeFolder/include_template_view'; //the view you want to include
$this->load->view('main_template_view',$data); //load your main view
and in main_template_view you can include other views :
$this->load->view($middle);
In my opinion for solve in more efficient way this problem I have done so:
You create a new helper (in application/helpers) with name (es. common_helpers.php, the underscore is important). In this file, you put all the functions for example build pieces of html in common.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
function getHead(){
require_once(APPPATH."views/common/head.php");
}
function getScripts(){
require_once(APPPATH."views/common/scripts.php");
}
function getFooter(){
require_once(APPPATH."views/common/footer.php");
}
In your controller you call only one view in respect of MVC and call the functions from your custom helper.
class Hello extends CI_Controller {
public function index(){
$this->load->helper('common');
$this->load->view('index');
}
}
In the controller
controller
<?php
public function view($page = NULL)
{
if ( ! file_exists(APPPATH.'views/pages/'.$page.'.php'))
{
$data['title'] = ucfirst($page); // Capitalize the first letter
// Whoops, we don't have a page for that
show_404();
}
$data= array('');
$data['title'] = ucfirst($page); // Capitalize the first letter
$data['page_layout']='pages/'.$page;
$this->load->view('page_layout', $data);
}
?>
In the Views folder create a page called page_layout.php
page_layout.php
//This is where you set the layout to call any view through a variable called $page_layout declared in the controller//
<?php
$this->load->view('header');
$this->view($page_layout);
$this->load->view('footer');
?>
Is it possible to display a view of a component without iframe and plugin?
(That is to say, if possible with a few lines of PHP and maybe SQL queries?)
EDIT:
To be more clear: I'd like to do it directly in the PHP-Template!
(Would be fine to do it in an article as well, as I have written a
PHP-function showArticle(mixed $ident))
(I'm using Joomla 3.5)
I'd like to do something like
<jdoc:include type="component" view="example" name="position-x" />
or
<?php
show_component('component-name', 'view-name');
?>
you can use this component http://extensions.joomla.org/extension/components-anywhere
Install the plugin and enable it.
Then you can call the component this way {component url/of/the/component}
{component index.php?component=com_example&form=1}
Try to use non-sef urls in the url but sef url will still work.
There is another way to achieve this by calling the model into your controller file this way
JModelLegacy::addIncludePath(JPATH_SITE . '/components/com_example/models', 'ExampleModel');
What this does is it searches the model class starting with ExampleModel in the folder specified. here you can eneter just a path string or array of the directories as the first parameter. Next you have to call the method inside the views file this way
$exmodel = JModelLegacy::getInstance('Something', 'ExampleModel', array('ignore_request' => true));
So here you create an instance of the class object which can be used to get the items from the model this way
$items = $exmodel->getitem();
$this->assignRef('items', $items);
next you can copy the default.php file in the tmpl folder of that component and place it anywhere you like inside your layout file. Basically instead of copying the entire component you are calling the model and getting the data which you can use in your layouts.
I'm writing a website using Slim Framework and Twig.
The sidebar on the website will have dynamically created links and i want to get the links from the database/cache every time a page is rendered, i can do this in each controller action but i would like to do this in my base template so i don't have to get and render the data manually in every controller action.
I have looked through the twig documentation and I haven't seen anything that could be of use besides the include function/tag but i don't see how i could get the data easily.
Is my only option to write an twig extension to do this or is there an easier way?
First of all: templates usually shouldn't contain any type of bussines logic but only render the data you provide it.
However you could write a custom twig function and use that to aquire the menu data from the DB in order to render it in your base template.
Alternativeley you could write some Slim middleware that aquires the data which might be able to inject the data into the template.
Hope that helps.
After reading Anticoms answer i was able to do it by writing a Twig extension.
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('render', array($this, 'render'))
);
}
public function render($template, $controller, $action) {
$app = Slim::getInstance();
return $app->$controller->$action($template);
}
Now i can simply write
{{ render('Shared/sidebar.twig', 'Controller', 'Index') }}
Into my twig template to render the template with the data i want.
Note that my render() function uses slim dependency injection to instanciate the controller at runtime.
i am using laravel's blade template and i have a master template for all my pages. In the master template i have a top bar and a sidebar. I want to load something in the sidebar. But i don't know how do it in a simpler way. Now i am calling that method (which i want in to display in my sidebar) in every controller i have like this:
View::make()->with('data_to_load_in_sidebar',$data_to_load_in_sidebar)
How can i load this only once, not every time i generate a view?
This is what view composers are for, any view that is loaded will automatically have it's composer run alongside providing the view with any extra data it may require.
View::composer(array('partials.sidebar'), function($view)
{
$news = News::all();
$view->with('news', $news);
});
I typically put this in my routes.php file in both L3 and L4.
In the view views\partials\sidebar.blade.php you now always have access to the variable $news that will contain all models from the News collection.
I would share top bar & sidebar data in constructor (prefferably in some BaseController's contructor, that other controllers extends).
public function __construct()
{
// if needed, call parent's contructor method as well
parent::__construct()
$data_to_load_in_sidebar = loadDataForSidebar();
View::share('data_to_load_in_sidebar',$data_to_load_in_sidebar)
}
I wanted the functionalities of view files to run in controller file also.
For example, I wanted $this->escapeHtml() which runs in view file alone to run in controller through some means like $this->...->escapeHtml()
Is this possible? Kindly help.
You need to get the ViewHelperManager and extract the EscapeHtml helper. This is a one example how to do it from the controller:
$viewHelperManager = $this->getServiceLocator()->get('ViewHelperManager');
$escapeHtml = $viewHelperManager->get('escapeHtml'); // $escapeHtml can be called as function because of its __invoke method
$escapedVal = $escapeHtml('string');
Note that it is recommended to escape and display the output in the view scripts and not in the controller.