I have a class
class ModuleController extends Controller {
private static $allowed_actions = array(
'index'
);
public function index(SS_HTTPRequest $request) {
return $this->renderWith(array("Module/HomePage", "Page"));
}
}
And two templates, one is Page.ss and another is Layout/Module/Homepage.ss. In Page.ss I have a bunch of html and $Layout. Looking through other areas online I would have expected the page to render according to Page.ss and the layout variable to render with Layout/Module/HomePage.ss however it just renders with Page.ss. How can I get my page to render with the base template of Page.ss and render the $Layout with my controller defined layout?
EDIT
So if I put the Homepage.ss up one level (i.e. no 'Module' directory) this code works. Is it possible to have directories in the Layout directory as I think this folder will get messy overtime without some structure. It also seems strange that the folder path works when setting the template but not the layout.
EDIT 2
Looks like This is a core problem I've just discovered a different way and looks to be addressed in SS4 so looks like this can't be done in SS3.
Related
I have a sidebar in my site that receive some information from db and I can't use controller for retrieve data because I have different controller and same sidebar. How can I print this data in view page.
when I wrote in P.h.P code in the view it shows an error that it cant define variables.
How could I do this?
When you find that you need the same code in many different controllers a "custom library" (class) is the perfect choice. Documentation for creating your own libraries is found HERE.
Controllers should be using models to get data from the database. Custom libraries can also use models just like controllers. Here is a very basic custom library called Sidebar. It depends on a model (sidebar_model) that will not be shown. The purpose of the Sidebar library is to return the variables need by the sidebar_view file.
File: application/libraries/Sidebar.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Sidebar
{
protected $CI; // Read the documentation link to see why this is needed.
public function __construct()
{
$this->CI = & get_instance();
$this->CI->load->database(); //only needed if not already done
$this->CI->load->model('sidebar_model');
}
public function get_sidebar_data()
{
return $this->CI->sidebar_model->get_sidebar();
}
}
The library method get_sidebar_data() returns the variables for the view.
Here is a controller that uses the custom library. It will use the custom library and a view file (not shown) containing HTML for the sidebar.
File: application/controllers/Main.php
class Main extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('sidebar'); //can also be autoloaded
}
public function index()
{
$data['sidebar'] = $this->sidebar->get_sidebar();
$this->load
->view('banner')
->view('sidebar_view', $data)
->view('main_view')
->view('footer_view');
}
}
Any other controller that needs to show the sidebar would use this same pattern.
This controller loads four different view files and is using "method chaining" which is encouraged. Method chaining executes a tiny bit faster. But the best reason for using it? Less typing.
The method chaning could also be type like this:
$this->load->view('banner')->view('sidebar_view', $data)->view('main_view')->view('footer_view');
But, IMO, putting each ->view() on a separate line makes it easier to read.
You can create a helper for your common tasks. Then create a function for your sidebar and call it where you need it. Check this link for more details about creating helper
You can also create a library for it. Although it will not a very good choice.
create sidebar (view page) and Call model directly inside that sidebar (view page).
secondly call sidebar (view page) directly inside all other view pages.
I'm working in a website where part of it I have the static html, so I created a layout and in it I'm inserting the static content using views. My problem is as this website has many pages I feel wrong creating an action for each url. So I implemented the controller below:
class PageController extends ControllerBase
{
public function initialize(){
$this->init();
$this->view->setLayout( 'website' );
}
public function indexAction ($url=''){
if($url == 'about')
$this->view->pick('page/about');
}
}
When I set the controller view to render $this->view->pick('page/about'); it doesn't insert the view in the template. It renders only the view.
Is there a way to render the view within the layout, and is there a better approach to what I'm doing?
Thanks for any help
To load a template you should use
$this->view->setTemplateAfter('website');
instead of $this->view->setLayout( 'website' );
By using $this->view->pick('page/about'); you are overwriting the layout set by $this->view->setLayout( 'website' );, resulting in only seeing the page/about layout.
I have an admin login page that I want to render without the layout. How can I render a view in Yii2 without rendering the main layout?
This can be done using renderPartial() method.
You can get more from the official documentation. Here's a link!
In your controller you can assing layout for all actions of controller or turn it off:
class AdminController extends Controller
{
// public $layout='//admin';
public $layout=false;
OR you can do it for only one action:
public function actionIndex()
{
$this->layout = false;
You can use renderPartial to exclude header and footer of layout from view file. However if you renderPartial it will not load asset files (css and js files). To load asset files without layout you can use renderAjax.
Is there a way to alter the autorender views in cake 2.3.5, either but overriding something or method name conventions?
I want to render views in subfolders of the main Controller directory, here is an example:
class AdministrationController extends AppController {
public function products(){
$this->render('/Administration/products/index');
}
}
I would rather store the views in organized subfolders like this:
- Administration
- products
- index.ctp
- edit.ctp
My question is: Is there a way to rework this so that I don't have to use $this->render() in every action?
Yes
Either call render with a path relative to the corresponding view folder:
$this->render('products/index')
Or call with an "absolute" path which is understood to be relative to the view folder:
$this->render('/Administration/products/index');
Both of these calls will render the view file app/View/Administration/products/index. If you want to structure your view files like that - you either call render in each action or manipulate the viewPath variable to point where it needs to be (either in the class, or in the beforeFilter).
An Administration controller is not normal
In the question there is Administration , products and index - all normal things, but it's not normal to have an Administration controller. With that kind of controller structure the Administration controller will become huge.
The normal way to do that would be to use admin routing and define an admin index:
class ProductsController extends AppController {
function admin_index() {
//
}
}
I've created Yii quiz module which I also want to use in Facebook app (Facebook side).
It can be done trough iframe, but generated page have got also menus and many other unnecessary (in this case) stuff. Is it possible in Yii to show only generated module code without rest of the website?
Try and use a different layout for that module. First you can add a layout folder and layout files to that module, say : /protected/modules/quiz/views/layouts/quizlayout.php. So this new quizlayout.php should be your layout for all the views in this module.
To do that you can set the layout property of the quizmodule in the QuizModule class's init(), like so (in QuizModule.php):
class QuizModule extends CWebModule {
public function init() {
// this method is called when the module is being created
// you may place code here to customize the module or the application
// import the module-level models and components
$this->setImport(array(
'quiz.models.*',
'quiz.components.*',
));
$this->layout='quizlayout';
}
//...
}
Now by default, gii generated modules' controllers are subclasses of the Controller class in component/Controller.php file. And that Controller class defines a layout, so if you have that same structure, then the above method will not work, and you'll have to override the layout within your modules' controllers. However instead of going inside each controller and adding a line, you can instead do this in the beforeControllerAction($controller, $action) function in QuizModule.php :
public function beforeControllerAction($controller, $action) {
if(parent::beforeControllerAction($controller, $action)) {
// this method is called before any module controller action is performed
// you may place customized code here
$controller->layout='quizlayout';
return true;
}
else
return false;
}
Edit:
Of course your quizlayout.php should not have code for menus, and any extra stuff, but at the very least the echo $content line should be there, as also mentioned in eskimo's answer.
In you protected/views there is a file called "main.php"
This is your main layout file, that gets rendered around any view called by $this->render
To remove the menu etc.. remove everything within the body except for the line:
<?php echo $content; ?>
Obviously leave in all the stuff in the head (.css files etc...)