I think this should have a pretty simple explanation but I'm still learning Fat-Free Framework (F3): How do I render only once the header and footer and switch out the content code for the selected route? I have this code:
$f3->route('GET /',
function($f3) {
$f3->set('content','views/welcome.htm');
$f3->set('page_head', 'Welcome');
}
);
And if I add this line:
echo View::instance()->render('layouts/header+footer.htm');
either after the f3->set calls in the route or after $f3->run(); at the end of the index.php file, the whole page refreshes on a route change. I can't call that echo line above before the route code without throwing an error in the content box.
Is there any way to disable the page refreshing? Is it being refreshed because my links are being interpreted as separate pages by the browser? Thanks for any help!
Your question is a little hazy. But I will try to answer in the way I understand.
First your index.php
$f3->route('GET /',
function($f3) {
$f3->set('content','views/welcome.htm');
$f3->set('page_head', 'Welcome');
echo Template::instance()->render('layouts/header+footer.htm');
}
);
$f3->run();
In your header+footer.htm
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>{{#page_head}}</title>
</head>
<body>
<include href="{{#content}}"/>
</body>
</html>
Your views/welcome.htm can contain anything.
<h1>Welcome</h1>
<p>You have arrived to the welcome page</p>
Please remember the folders views and layouts should be in the UI folder
$f3->set('UI','ui/');
On your comment:
You can access the params of a request from $f3->get('PARAMS') or you can do this.
$f3->route('GET /#page',
function($f3,$params) {
$page = $params['page'];
$f3->set('content','views/'. $page .'.htm');
$f3->set('page_head', 'Welcome');
echo Template::instance()->render('layouts/header+footer.htm');
}
);
This should work
If you wish to update only a portion of a web page, without doing a full refresh, then you need to use AJAX.
Start by reading this:
https://fatfreeframework.com/3.6/routing-engine#AJAXandSynchronousRequests
You'll need to use javascript on the front end to make this work. If you don't know how to code this in javascript, then you can start by reading this:
https://www.w3schools.com/js/js_ajax_intro.asp
You may find it easier to use Jquery, which is a very popular javascript library. You can read about it here:
https://www.w3schools.com/jquery/jquery_ref_ajax.asp
Maybe will be not bad to create your own instance of View and extend the main with functionality similar to PHPTal Filters. Then you can set Header in preFilter and Footer in postFilter and extend render() function. The extended render() will render everything together for you including header, footer and body content.
I don't have personally anything against FatFree View but will suggest PHPTal as a templating engine - here simply implementation https://github.com/creoLIFE/FatFree-PHPTAL including Header/Footer served from separate files.
Related
I'm looking for advice on the best practice for separating site content up into logical blocks. I want a header and footer that are constant throughout the site, so that if I have several pages of different content, they will all look as below — changes made to the header and footer then update automatically without me having to change each individual page.
<?php
include 'header.php';
?>
<body>
<p>page content here</p>
</body>
<?
include 'footer.php';
?>
The header.php would contain the opening <html>, <head> and static content, and the footer.php would contain any extra static content and the closing </html> tag. So, my question is: Is this a good approach? I'm worried that spreading the <html> tags across multiple files is bad practice. If so, what is the right way to approach this kind of design?
Nope, your approach is wrong.
Here are main faults in your design:
You're assuming that header.php would be called on the every page call. That's wrong.
You're assuming that header.php will always be static. That's wrong.
You forgot to create a template for the page itself.
The main rule everyone have to learn by heart:
Not a single character has to be sent into browser, until all data gets ready.
Why?
it's 2011 today. AJAX era. What if your code will have to send JSONed data instead of whole HTML page?
there is a thing called HTTP header. Sometimes we have to send them. And it's gets impossible if you already have your ornate HTML header sent.
it's for just 4-page site. Okay. Imagine you've got lucky and got a request for another 4-page site. You will have to change only templates and don't touch engine files. That's really great benefit.
Imagine you're going to make a custom <title> tag for your pages, based on the page content. Isn't it extremely common thing? But you can't make it without using templates.
So, you have to have one common site template containing header and footer and also dedicated templates for the every php script.
An example layout is going to be like this:
.1. page itself.
it outputs nothing but only gather required data and calls a template:
<?php
//include our settings, connect to database etc.
include dirname($_SERVER['DOCUMENT_ROOT']).'/cfg/settings.php';
//getting required data
$DATA=dbgetarr("SELECT * FROM links");
$pagetitle = "Links to friend sites";
//etc
//and then call a template:
$tpl = "links.tpl.php";
include "template.php";
?>
.2. template.php which is your main site template,
consists of your header and footer:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My site. <?=$pagetitle?></title>
</head>
<body>
<div id="page">
<?php include $tpl ?>
</div>
</body>
</html>
.3. and finally links.tpl.php is the actual page template:
<h2><?=$pagetitle?></h2>
<ul>
<?php foreach($DATA as $row): ?>
<li><?=$row['name']?></li>
<?php endforeach ?>
<ul>
easy, clean and maintainable.
In building off of Your Common Sense's answer, there's not a good reason to have 2 files for every page. You can easily combine your template (YCS called this .tpl.php) and your actual page into one file.
First, start off with a class that you can expand as your template needs expand:
<?php
#lib/PageTemplate.php
class PageTemplate {
public $PageTitle;
public $ContentHead;
public $ContentBody;
}
Then, make your layout:
<?php
# layout.php
require_once('lib/PageTemplate.php');
?>
<!DOCTYPE HTML>
<html>
<head>
<title><?php if(isset($TPL->PageTitle)) { echo $TPL->PageTitle; } ?></title>
<?php if(isset($TPL->ContentHead)) { include $TPL->ContentHead; } ?>
</head>
<body>
<div id="content">
<?php if(isset($TPL->ContentBody)) { include $TPL->ContentBody; } ?>
</div>
</body>
</html>
And finally, add your page with the body content:
<?php
#Hello.php
require_once('lib/PageTemplate.php');
# trick to execute 1st time, but not 2nd so you don't have an inf loop
if (!isset($TPL)) {
$TPL = new PageTemplate();
$TPL->PageTitle = "My Title";
$TPL->ContentBody = __FILE__;
include "layout.php";
exit;
}
?>
<p><?php echo "Hello!"; ?></p>
This is a basic approach but, yeah, it does work :) I sure would bother with a lot of templating and OOP but you are definitely on the right path
As i can't comment anymore, then i will answer here ;) If he need a custom title then he needs some more advanced functions. So, as i told, this is a basic approach. But in the end, if he really have a static header/footer, and really use them everywhere, well, yes, this is a good way to go.
So ofc you could bother with some advanced headers with parameters you could feed on each page. You could go on a whole MVC stuff. In the end just tell him to use a pre-made framework and stop bothering. How could he learn if you don't let him do some trial and error ?
index.php -- includes header, footer, and content based on REQUEST variable.
header.php -- header content
footer.php -- footer content
content1.php, content2.php, etc.
index.php:
<?php
include ('header.php');
// VERY IMPORTANT - do not use the GET variable directly like this
// make sure to filter it through a white-list
include(basename($_GET['page']).'.php');
include ('footer.php');
?>
if you want the URL to go www.domain.com/pagename where the page you're trying to load into index.php is "pagename", use HTACCESS and do some URL Rewriting: http://corz.org/serv/tricks/htaccess2.php
Is it possible to use WordPress as the CMS but all of contents will be displayed using CodeIgniter?
What I want to know also if I can use the functions of WordPress by simply including this wp-blog-header.php in the CodeIgniter.
Do you think guys this idea will work?
Probably one of the function I really need is apply_filters().
I used the wordpress headers on a codeigniter site once, and there were a lot of conflicts with global functions like site_url that had to be manually resolved (by renaming those functions in the codeigniter core)
It was a mess, and I wouldn't recommend it if you can get away with it.
You might be better off querying the same database and building new functionality in codeigniter using the same data.
But if you still want to do it, you can do something like this:
// in codeigniter index.php
require_once( '../wordpress/wp-blog-header.php' );
Then (in your header view, for example):
if(function_exists('get_header'))
{
get_header(); // will echo the wordpress header
} else {
//html code for your header ?>
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<!-- etc... -->
<?php } ?>
And you should see the wordpress header, at least once you solve all the errors caused by including it. There's also a get_footer() function for the footer.
Good luck
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 developing a Zend MVC application.
Sometimes I like to echo some text just for quick and dirty debugging. e.g
<?php
class MyClass {}
echo('hello world - yes this script is included');
I can echo 'debug-text' in my bootstrap> But, when text is echoed in my model or controllers it is NOT being rendered in the output.
I am using Zend 1.9.5 and using Zend Layout with MVC
Is there a setting somewhere that is suppressing all ''non-view script rendered'' output?
You can also use die() instead of echo :) it will work. Or use Zend_Log and output writer like this:
$writer = new Zend_Log_Writer_Stream('php://output');
Output buffering may be the culprit. Try:
echo 'my debug output';
flush();
If viewRendering is turned on, it's probably looking for the view/scripts/ to render and possibly not displaying your echo statements.
You could try to turn viewRendering off the given controller and see if that helps.
viewRenderer->setNoRender()
I am answering this question because I came back to the same code , 10 months later , and it confused me again.
I was in the context of a Default Module, Index Controller, and Index Action.
I wanted to echo some simple text as a quick way to see what was happening in the code:
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
//home page
echo '<h1>hello world</h1>';
//set the special home page layout
$this->_helper->layout()->setLayout('home-page');
}
Trouble was - the echoed text was just not showing up.
It worked in other controllers , but not this one. It was driving me crazy.
Now - I've worked out the problem.
I was using a special layout for this particular control action... a 'home page layout'.
In my home page layout I was not rendering any view script. All the content and design was in the layout. Because the home page is a special , unique page, there was no need to separate into a two step view. For this reason I had no reason to need a view script. But, I did create a 'views\scripts\index\index.phtml' to keep ZF from complaining. I did not however, render it in my layout - cos it was not needed.
Any echoed output is captured into the layout()->content (automatically assigned by the layout from the 'default' response segment). Because I was not echoing out that segment, it behaved as if the echoed text was being suppressed.
To solve the problem , i simply had to ensure that i was echoing out the content segment.
i.e.
<html>
<head>
...
</head>
<body>
... my home page html...
<?php echo $this->layout()->content ?>
... my home page html...
</body>
</html>
which, with my debug text being echoed too... would render as:
... my home page html...
<h1>hello world</h1>
... my home page html...
Im learning a lot about how MVC frameworks work by looking around and studying existing ones. It seems that every framework I see has a layout where each method in each controller has its own template file. So there will be a login template, a logout template, register, so on and so on.
My question is, how and why would you create a template for the entire page all within one file. Lets say you wanted to show the login form on more than one page, wouldn't you have to create the login form for each template that you want it to display on? Doesn't that go against the don't repeat yourself rule (DRY)?
The way i've been doing things so far is I've been creating liitle chunks of templates and then combining them to create each page. So instead of doing something like this,
$title = 'Blah Blah Blah';
$user = 'Jon Miller';
include 'index.phtml';
<html>
<head>
<title><?php echo $title; ?></title>
</head>
<body>
<h3><?php echo $user; ?></h3>
<form>login form</form>
</body>
</html>
I've been doing this
$title = 'Blah Blah Blah';
include 'header.phtml';
$user = 'Jon Miller';
include 'user.phtml';
include 'login_form.phtml';
include 'footer.phtml';
header.phtml
<html>
<head>
<title><?php echo $title; ?></title>
</head>
<body>
user.phtml
<h3><?php echo $user; ?></h3>
login_form.phtml
<form>login form</form>
footer.phtml
</body>
</html>
As alway, I would just like to know the proper way to do it, along with how and why...It just seems to go against the DRY rule.
Thanks
You should check out the concepts of 'layouts' and 'view helpers'. While I've linked to the Zend Framework version of those concepts, other MVC frameworks (and the MVC concept) should have them as well.
The basic idea is that your page 'view' - for example the login form - is included into your site 'layout' - the general template that is used throughout your site. When you request a different controller, with a different view - for example a user profile - that view is also included in the same layout.
To include something like a login form on all pages, a view helper can be used. That view helper could display the current user, or display a login form, depending on the login status. View helpers may be included in the layout, or included by the specific controller (as long as MVC framework allows some kind of named render segments).
The two step 'include' method works better than linear inclusion of parts (including header, then content, then footer - what you're doing now) because your templates do not have to split HTML tags. The Zend Guide has a good visual example of view templates in a layout.
One word: Organization. Separating each part of the page will allow each of them to be viewed/edited separately. This simple concept is very beneficial. For example, anyone in the team that want to handle login process can easily figure out that they have to edit login_form.phtml and they can be sure that editing login_form.phtml will less likely to unintentionally interfere with other functionalities.
As of the best practice, here is how I do it (not exactly but similar).
$Title = 'Blah Blah Blah';
$User = 'Jon Miller';
$ThemeName = "MyGreenPage";
$Contents = array("User", "Login_Form");
function Include($FileName) {
if (file_exists($FileName))
include $FileName;
}
MyGreenPage.phtml:
<html>
<head>
<title><?php echo $title; ?></title>
<?php
foreach($Contents as $Content)
Include("$Content.pcss");
?>
<?php
foreach($Contents as $Content)
Include("$Content.pjs");
?>
</head>
<body>
<?php
foreach($Contents as $Content)
Include("$Content.phtml");
?>
</body>
</html>
User.pcss:
/* Some styles needed by User */
User.pjs:
/* Some script needed by User */
User.phtml:
<h3><?php echo $user; ?></h3>
Login_Form.pcss:
/* Some styles needed by Login_Form */
Login_Form.pjs:
/* Some script needed by Login_Form */
Login_Form.phtml:
<form>login form</form>
Let me remind you again that this is not that exactly what I do (what I do use OOP) so this may not exactly run as is and you may need to edit it.
The most common way to do HTML templating with PHP, is to use one of these popular templating engines :
Smarty
Twig
Latte
Mustache
Alternatively, you can just put placeholders in your HTML that look something like <% variablename %>. Just load your HTML, do a regex do find all placeholders and replace them with the corresponding variables.
Alternatively, you can load your HTML, parse it as a DOM document and then modify your DOM. I created the library DOM Query to be able to do this with a jQuery-like syntax, but you could use vanilla PHP or one of several other libraries as well.
Alternatively, you can do some HTML templating in frontend with JavaScript. If you want to do HTML templating both on frontend and backend, you might want to consider using Mustache, because Mustache templates can be used both in frontend (with JavaScript) and in backend (with PHP).
For this project I am working on, all views are XSL templates. Instead of passing variables to the view, I generate all the XML in the controller and transform it with the view.
I like this structure because I can keep all my templates in one file, and arrange them anyway I want. It's also a standard template language which is very flexible and has tons of documentation. This has been working out really well so far.
A really good example of this structure is the WoW Armory website (view the source).