Change layout file within a view in Yii2 - php

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

Related

How to use a path in PHP's include function [duplicate]

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

PHP MVC understanding help (Laravel 5.3)

First, I want to say that it's the first time for me working
with a PHP Framework and MVC and I have not found all the answers to my problems yet. I'm using Laravel 5.3 at the moment.
Problem:
I have a website where a User can login and a few pages (I'm using Laravel Auth) and on a lot of pages I have a sidebar which is every time the same. Then I have on every page some content which is different (about, articles, ...). I heard that the most important thing is that you should never write code twice and there is the problem. On this sidebar there is a "service" which show content to the user but to show this I have an algorithm which needs the user data from the authenticated user and the Auth function is not available in Laravel 5.3 ServiceProvider or BaseController and was never meant to be.
My question now is how can I do that cleanly?
Some codes to understand it better:
Routes:
Route::get('/community/ranking', 'Pages\RankingController#getView');
Route::get('/community/advertising', 'Pages\AdvertisingController#getView');
Route::get('/logout', 'PagesController#doLogout');
Route::get('/home', 'Pages\HomeController#getView');
Then I have for every page an own controller which serves the content for this page (except of the sidebar - no solution yet).
HomeController:
<?php
namespace App\Http\Controllers\Pages;
use App\Http\Controllers\BaseController;
use Redis;
use App\Http\Requests;
use Request;
use Shoutbox;
use User;
class HomeController extends BaseController
{
function getView()
{
$shoutboxData = $this->getShoutboxData();
return view('pages.home', compact('shoutboxData'));
}
private function getShoutboxData()
{
$shoutbox = Shoutbox::orderBy('time', 'DESC')->skip(0)->take(15)->get();
if(count($shoutbox) > 0)
{
foreach($shoutbox as $entry)
{
$getUser = User::where('id', '=', $entry->user_id)->first();
$entry['username'] = $getUser->username;
$entry['look'] = $getUser->look;
$shoutboxData[] = $entry;
}
}
else
{
$shoutboxData = null;
}
return $shoutboxData;
}
public function systemMessage()
{
$redis = Redis::connection();
$redis->publish('chat.message', json_encode([
'msg' => 'System message',
'nickname' => 'System',
'system' => true,
]));
}
}
Now I serve the view in each, own controller and the content of this page (for example shoutbox, news) is also in that controller. (Not very clean in my opinion but didnt find any better way. Something I can improve here?).
I can serve the sidebar content on every Controller but this is not what I want. How can I do that? Am I using MVC right?
Thanks in advance!
Because you're using the Laravel Blade template system you can split your view logic out into separate blade files.
Your sidebar is common to every page so put this in your layout file (resources/views/layouts/app.blade.php) put the logic before
<div class="container" id="app">
#yield('content')
</div>
Now in your blade files for each individual page just extend the layout template you just created:
#extends('layouts.app')
#section('content')
<h1>page content goes here</h1>
#endsection
Now everyone of your blade files which extend the layouts.app will have the sidebar logic in them.
EDIT: With the extra information provided.... do as I said above but also create a view composer, you can find the full documentation here: https://laravel.com/docs/5.3/views#view-composers
Create a view composer for your main layout (or sidebar layout if you're going to be extending layouts instead) and pass your data within the view composer, the documentation gives good examples so just modify that for your own sidebar.

Best method of including views within views in CodeIgniter

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

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

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