Have recently started to re-develop an application with CodeIgniter and I am trying to implement my template into the system.
I am facing an issue that I can't yet see a way around
Basically, at the minute within the controller an example of what I am doing is:
/*
* Load view for header
*/
$this->load->view('header_view');
/*
* Load view for navigation
*/
$this->load->view('navigation_view');
/*
* Load view for content
*/
$this->load->view('content_view');
/*
* Load view for footer
*/
$this->load->view('footer_view');
However the problem I am facing is that the content area has pages dynamically loaded in to it.
So the navigation area links don't open up the HREF URL but they load that page data in to the content div via ajax.
I need to be able to go to my controllers directly via the URL such as 'http://www.website.co.uk/controller/method_name/parameters' which at the minute is fine.
The navigation however will load that link in to the content area which also includes the header/navigation/footer so I end up with nested layouts in the content area...
The simple way around it is 'well don't include the header/navigation/footer views in every page' however then you can't directly go to the URL such as above, it would only work when loaded in to the content area as it would need to have the header, navigation and footer.
The solution that I ideally need is that the header/navigation/footer are ALWAYS loaded around any controller so that if I go to a controller/method via the URL I don't have to load the header/navigation/footer in the controller but it is automatically loaded around it.
Any ideas appreciated, thanks
Why not extend the CI controller with a MY_Controller, then all your controllers will extend MY_Controller. In my_Controller have a function like:
public function loadView($file, $data=array()){
$this->load->view('header', $data);
$this->load->view($file, $data);
$this->load->view('footer', $data);
}
Then, from your controllers actions, just call it :
public function index(){
// code code code
$this->loadView('welcome', array('message'=>'Hello!'));
}
I think you get the point.
in ajax you can use views like this:
<div id="header"></div>
<div> //here all your stuffs</div>
</div id="footer"></div>
then just :
<script>
$(function(){
$('#footer').load('my_footer_view_url');
$('#header').load('my_header_view_url');
});
</script>
this is a poor example, you can define both a php method which serves the views and a js method which loads them into divs, so each view then must have only a <div> where to load partials
Important
if you can use Ajax, this solution is great, cause once you move the #footer div somewhere else in your views you moves an enteire footer view for example, php will be more static anyway, but it depends, i sad, if you can or not use ajax ;)
Related
I'm new to Symfony2 and I've been thinking of the best way to generate navigation bar HTML that is used on every page request - especially with regards to caching.
So imagine if every page request shows the logged in user and a number indicating how many messages are unread (in fact like stackoverflow for that). I'm guessing that could be generated in every controller to ensure the info is up-to-date (using a function or something of course) - but I'm also looking at caching the whole controller output, and think it might be good to keep this dynamic part separate.
Would creating a controller extension for all this kind of stuff be a good way to go? So this way the controller only deals with that specific function (e.g. getting blog posts from a DB etc.) and the controller extension adds all the dynamic content. That way I can cache the controller result and speed up pages without caching the full page (which can't really be done due to lots of dynamic HTML content).
Something like this maybe:
class ControllerExtension extends Controller
{
public function render($view, array $parameters = array(), Response $response = null)
{
//get number of messages for this user
$parameters['messages'] =
//are they logged in
$parameters['logged_in'] =
// render as normal
return parent::render($view, $parameters, $response);
}
}
For this I want to ignore use of JS. I know some of these things could be populated with JS, but I would prefer not for this.
You can solve this by caching the navbar fragment separably from the page html with ESI or Hinclude and can be simply and elegantly solved with Symfony2.
Embed a controller inside a template
You can render a controller inside a template:
<div id="sidebar">
{% render url('latest_articles', { 'max': 3 }) %}
</div>
This will render the controller with the route "latest_articles", inside your html.
This can be done in you controller template, or in the global layout template (where you define the header, footer, js, css ecc of all your pages, see Template Inheritance)
Cache the embedded fragment separately from the page html:
You can use a reverse proxy (like Varnish, or the AppCache), to cache the two part of the html separately:
<div id="sidebar">
{% render url('latest_articles', { 'max': 3 }, {'standalone': true}) %}
</div>
That's it, just add {'standalone': true}
You'll need an external program on front of your web server (like Varnish, or Nginx with a mod), but this is the fastest way.
Load the fragment with javascript:
You can also tell symfony to asynchronously load the fragment in javascript:
<div id="sidebar">
{% render url('latest_articles', { 'max': 3 }, {'standalone': 'js'}) %}
</div>
This is a nice approach, since you can cache the entire html in a CDN (for example with Amazon CDN CloudFront), and still show user specific content.
For info see: http://symfony.com/doc/2.1/book/templating.html#asynchronous-content-with-hinclude-js
I wish to have a codeigniter application with 3 templates.
a template for displaying a login view, or an error view.
a template with header body navigation
a template with header body sidebar footer
now I can build the codeigniter application, but I can't find a simple template system to accomplish this task. There are many recommendations for libraries available, but they lack implementation details.
Suggestions and guidance would be appreciated.
You can user CodeIgniter Template.
http://williamsconcepts.com/ci/codeigniter/libraries/template/index.html
Download here the library and also you have a full documentation.
With this library, you can use more than one template, and you can manage it easy and separate in groups.
It's quite simple once you get your head around it.
You need to create a view file for each of the things you've listed above, so you'll want something like this (folder/file wise):
views/page-login.php
views/page-error.php
views/header.php
views/footer.php
Then from your controller you will load one of the page views.
Within the page view you can then load the elements you require, so header and footer with the page specific code between them.
So for example your login page could be:
<?php $this->load->view('header'); ?>
<h1>Login</h1>
<p>Please login to my website.</p>
<?php $this->load->view('footer'); ?>
This is fairly simple.
A quick example:
In your controller you can put
//a test variable
$data["foo"] = 'bar';
$data["page"] = 'a_page'; // this will make sure it loads the views/pages/a_page.php in your template
$this->load->view('templates/login',$data);
And in your views/template/login.php you can put:
<!-- your login template html -->
<html>
...
<!-- include the view you want inside your login template -->
<?php $this->load->view('pages/'.$page);?><!-- As you can see it loads /views/pages/a_page.php -->
<?php echo $foo;?> //This will echo Bar
</html>
or:
<?php $this->load->view('template/login_header');?>
<?php $this->load->view('pages/'.$page);?>
<?php $this->load->view('template/login_footer');?>
views/pages/a_page.php will also know $foo.
This loads another view (views/pages/a_page.php) in your template.
This way you can create all the templates you want, and include your view in those templates.
TIP: Handling headers & footers this way get's unmanageable pretty quickly. And it's still better to use template libraries. Try Phil sturgeon's library
I am creating a website using codeigniter and I want to include the menu (options) file so that I could save all my time from independently pasting the code on every view I need.
Or even if there is a common file for custom functions where I could place the code and call the function.
ANy help. My menu option is as follows.
<h5>Admin Options</h5>
<ul>
<li>Portfolio
<ul>
<li> Add a Category</li>
<li> Edit/Delete Category</li>
<li> Add a Link</li>
<li> Edit/Delete Link</li>
</ul>
</li>
<li>First</li>
<li>First</li>
<li>First</li>
<li>First</li>
</ul>
Just put your HTML in a view file "options_view.php" and anywhere you want to include this HTML snippet just load that view:
<?php $this->load->view('options_view') ?>
As you can see by the answers there are a number of ways of doing this but honestly I don't see the point in a templating library as it's relatively easy to do on your own. I use templates for my entire site since it means I don't have to keep rewriting code. Below is how I do it.
Template.php This file loads the other parts of the template, it loads the header dependent on whether the user is logged in so I can add the user menus easily.
<?php
if($this->session->userdata('is_logged_in'))
{
$this->load->view('templates/header-admin', $title);
} else {
$this->load->view('templates/header', $title);
}
$this->load->view('templates/sidebar',$sidebar_content);
$this->load->view('pages/'.$main_content);
$this->load->view('templates/footer');
?>
Each of those pages is a static html file or as in the case of the main content and sidebar_content they're variables. So then from a controller I load my views like this (this is a basic page)
public function welcome()
{
$data['main_content'] = 'welcome';
$this->load->model('someModel');
$data['someArray'] = $this->someModel->someFunction();
$data['title']='Welcome to example.com';
$data['sidebar_content'] = 'sidebar/no_sidebar';
$data['additionalHeadInfo'] ='';
$this->load->view('templates/template',$data);
}
So what's happening above is the first line is the actual view getting loaded to main content this is a php page with nothing but the middle content of the site in it. Title fills in the title tags in the header. sidebar content loads the appropriate sidebar.php page (in this case it's an empty file). Additional head info is so I can load libraries or css pages specific to a single view. The final line brings it all together.
Edit - I added two lines for adding variable data. So you would do a call to your model like normal and return the data, but return it to an array inside the $data array. Then in your view you would access it like this (variables are obviously for example, you'd use whatever variables your model returns:
echo $someArray['userName'];
For the record normal PHP include statements work just fine in CI, it just makes a lot less sense than creating a template.
See CodeIgniter's documentation and the PHP documentation.
There is something to be said for self-directed learning.
Templating is going to be the answer for this. Since out of the box CI treats any view as essentially its own page, it is up to the user to either load other views progressively or to wrap all views except those loaded as strings into a common template.
Here is just one library to implement this:
http://williamsconcepts.com/ci/codeigniter/libraries/template/reference.html
Personally I would not load all views progressively as Wolf states. Nothing wrong with this except that it can lead to maintainability problems. I would create as many templates as necessary - some may not need the options view, for example - and load the correct one with each method.
I'm working with a CakePHP application and jQuery Mobile. In the CakePHP application, RequestHandler is turned on, now, jQuery Mobile makes all of it's requests as ajax requests but requires a full page not just what is in my view but the full layout to.
I need requesthandler and I've tried to set a layout, force a render, turn off autolayout, nothing works, cake only returns the contents of my view.
I'd really love to know what's going on here.
If anyone is interested I found a solution to this, I found out that when you have RequestHandler on and make a Ajax request, it doesn't matter what you do, RequestHandler then decides that your layout is 'ajax' via call backs, this probably applies for all non-html request types, like json and text.
I had to set
$this->RequestHandler->enabled = false;
It really needs to be set in beforeFilter() as well, latter in the call chain and it appears to not work.
So my code ended up as:
class AppController extends Controller {
var $components = array('RequestHandler');
function beforeFilter() {
if ($this->RequestHandler->isMobile()) {
$this->RequestHandler->enabled = false
//set special mobile rules here
}
}
}
I was having the same problem with a CakePHP 1.3 app that is using jQueryMobile to build mobile-friendly views. I'll try to lay it out for future searches.
When I switched on $.mobile.ajaxEnabled = true; for jQM's nice Ajax-based navigation all the linked pages showed undefined instead of the page content. The Ajax nav requires that the linked page have the proper structure, like so:
<div data-role="page">
<div data-role="header">
<h1>Page Title</h1>
</div><!-- /header -->
<div data-role="content">
<p>Page content goes here.</p>
</div><!-- /content -->
<div data-role="footer">
<h4>Page Footer</h4>
</div><!-- /footer -->
</div><!-- /page -->
This markup was coming from two places for my app, though: my default mobile layout had the <html>, <body> and the page and footer divs. Each view had a header and content div.
The problem arose because Cake's RequestHandler wanted to set the layout to ajax for all Ajax requests. It does this somewhere after beforeFilter(), which caused it to ignore a declared layout there (which Luke mentions).
The ajax layout is empty, unlike my default layout--it doesn't have <html> and other markup because it assumes (rightly) that you only want partial markup that will be inserted into a page by Ajax. The jQuery Ajax-based navigation does want to see the full markup though, and when it didn't receive a well-formed page when making the Ajax request it had no page to display.
So the question became, "How do I make RequestHandler use my default mobile layout for mobile page requests?" I wasn't satisfied with Luke's solution above of disabling RequestHandler completely for mobile. Luckily I found a post from May '11 with the same problem and a better solution:
Finally sorted it! I was checking to see whether a mobile device was
requesting the page using $this->RequestHandler->isMobile(), but had
placed it in the beforeFilter() function. Moving this to the
beforeRender() function in the app_controller.php file fixed the
problem.
http://cakephp.1045679.n5.nabble.com/Jquery-Mobile-and-CakePHP-1-3-td4422871.html
So my code ended up something like this in AppController:
function beforeRender() {
if ($this->RequestHandler->isMobile()) {
$this->layout = 'm_default';
}
}
I hope that helps someone out there.
Just set $this->layout = 'default'; in your controller, and it will use the default layout.
Or maybe you could make a header and footer element to put in your ajax and default layouts.
I was new to CakePHP and started with Version 2 several weeks ago.
So far I also keep the beforeFilter untouched to identifier isMobile() and finally use mobile-views within a Themed-Folder. Therefore I dont use subfolders for mobile-views within the default desktop-views. After adding this->layout in the condition it seems that I got rid off the undefined which appeared only via some actions links.
public function beforeRender() {
if($this->RequestHandler->isMobile()) {
$this->theme = 'Mobile';
$this->layout = 'default';
}
}
The best sollution I think is to configure the request handler in before filter after the mobile browser was detected in your app controller:
public function beforeRender() {
if($this->RequestHandler->isMobile()) {
$this->theme = 'Mobile';//set your theme
$this->RequestHandler->ajaxLayout = 'public';//this does the trick, set your mobile layout, $this->layout is simply ignored or overwritten by the component
}
}
i cannot use iframe in codeigniter. My have tried following
/My controller things.php
function index()
{ $this->load->view('view_index'); }
In view view_index.php there r 4 frame header, main, left & footer. My view_login.php will be loaded in main frame which actually loads my function login()
To send data to different parts of a page the use of templates is advised, at least by myself.
For instance, a template page file look like this
$this->load->view('tops/home1'); //header
$this->load->view($content);//main content(your login area)
$this->load->view('bottoms/main_home'); //footer
From the controller
$data['content'] = 'home/home_content'; //this is the **main** part of your page
$this->load->view('template1', $data);
To include your login script, simply put the login file in the root(in a directory made by you) and include it as a normal php include wherever you want it to be. As Aren noted, the use of Iframes is ancient and should be avoided