I'm used to working in ASP.NET / ASP.NET MVC and now for class I have to make a PHP website.
What is the equivalent to Master Views from ASP.NET in the PHP world?
Ideally I would like to be able to define a page layout with something like:
Master.php
<html>
<head>
<title>My WebSite</title>
<?php headcontent?>
</head>
<body>
<?php bodycontent?>
</body>
</html>
and then have my other PHP pages inherit from Master, so I can insert into those predefined places.
Is this possible in PHP?
Right now I have the top half of my page defined as "Header.html" and the bottom half is "footer.html" and I include_once both of them on each page I create. However, this isn't ideal for when I want to be able to insert into multiple places on my master page such as being able to insert content into the head.
Can someone skilled in PHP point me in the right direction?
You can use Smarty or develop your own template engine.
Basically you can define a simple layout like this:
layout.tpl:
<html>
<head>
<title>My WebSite</title>
{$header}
</head>
<body>
{$bodycontent}
</body>
</html>
define your header:
header.tpl
<script type="text/javascript" src="js/myjs.js"></script>
and your content file:
home.tpl
<div>hello {$var}! </div>
And finally your controller:
index.php
<?php
$header = new Smarty();
$headerOutput = $header->fetch('header.tpl');
$content = new Smarty();
$content->assign('var', 'world');
$contentOutput = $content->fetch('home.tpl');
$layout = new Smarty();
$layout->display('header', $headerOutput);
$layout->display('bodycontent', $contentOutput);
$layout->display('layout.tpl');
?>
Since PHP is a programming language and not a framework, it doesn't have that functionality out of the box.
There are many solutions to this problem, probably the most complex one would be to actually use a framework. There are many PHP frameworks to choose from. Downside would be that you'd be learning a framework and not PHP.
A simpler solution is to use a Templating engine. You'd be closer to PHP but you'd still have to learn how to use such engine.
And you're already using the simplest solution: including files from a main file. You can also include PHP files that is going to get executed and not only static html.
If you don't want to use a Templating engine, one solution could be like this:
<html>
<head>
<title>My WebSite</title>
<?php include('headcontent'); ?>
</head>
<body>
<?php include('bodycontent'); ?>
</body>
</html>
And in bodycontent:
<?php
switch ($_GET['page'];
case 1:
include('page1');
break;
case 2:
include('page2');
break;
}
?>
bodycontent will be like a very simple controller.
Related
Is it possible to use PHP to include the contents of the <body> on one page, and add it to the <body> of the other page, while doing the same thing for the header? Or is it just easier / better to use two pages? This is kind of what I'm going for:
Some Page
<html>
<head>
- nav.php's header -
- stuff special to Some Page -
</head>
<body>
- nav.php's body -
- content special to Some Page -
</body>
</html>
I know the require statement can be used to take the whole contents of a file. Is there some sort of "merge" statement to kind of merge the pages together?
You are going to run into all sorts of security, re-use and maintenance issues if you rely on the inline behaviour of included files in PHP. But if you stick to some simple rules you can avoid these problems:
Any HTML tag opened by PHP must be closed in the same scope (i.e. function)
Included files must only contain namespace, constant, function and object definitions or further include/require statements (but using the autoloader is prefereable).
So applying these to your base page above, and observing the established good practice of putting includes/requires at the top of your page....
<?php
// always start your page with a PHP block - it makes interfering with the headers
// much less painful
require_once('nav.inc.php');
function local_head_content()
{
...
}
function local_body_content()
{
...
}
?>
<html>
<head>
<?php
nav_head_content();
local_head_content();
?>
</head>
<body>
<?php
nav_body_content();
local_body_content();
</body>
</html>
But it would probably be better to invoke local_head_content() / local_body_content() as callbacks from nav content.
(yes it is possible to do what you ask, even without function calls - but it would be a very bad idea which is why I've not explained how to do this).
A more conventional approach to solving the problem of shared content across different files is to use a front controller pattern - instead of the webserver selecting the page specific content, this is done in the PHP code with all URLs pointing to the same entry script.
Since you are including nav.php in the <body> of index.php, nav.php should not contain tags like <html>, etc. since that will result in a final page which does not conform to the HTML spec.
Using your example, this is the contents of the index.php page which will be received by the browser:
<!DOCTYPE HTML>
<html>
<head>
<title>Title</title>
<style>
- styles for index.php -
</style>
</head>
<body>
<!DOCTYPE HTML>
<html>
<head>
<style>
- Style for navigation menu -
</style>
</head>
<body>
<h1>Title</h1>
<nav>
- Navigation -
</nav>
</body>
</html>
<content>
- content here -
</content>
</body>
</html>
As you can see, your final page contains multiple <!DOCTYPE> tags, multiple <html> tags, etc.
nav.php should contain only the tags which you want to be included in that part of the final page. So your nav.php should look more like this:
<nav>
- Navigation -
</nav>
As for your styles in index.php, you should have a <link> tag which pulls in an external style sheet, e.g. <link rel="stylesheet" href="style.css">. All the CSS for all pages would go in style.css.
Hello, I started learning PHP, I set myself a goal to make a website,
which would be similar to social network, as I am newbie, I don't know what is good or bad, I can code simple functions, have fundamentals of HTML, CSS, JS. But I want to learn more deeply, like what practices should I use and which I shouldn't
Here is the code of header.php :
<?php
$page = $_SESSION['page'];
?>
<!DOCTYPE html>
<html>
<head>
<title><?php echo $page ?></title>
</head>
<body>
<h3>HEADER</h3>
</body>
</html>
<hr>
And here is the code of index.php :
<?php
session_start();
$_SESSION['page'] = "Pradinis Puslapis";
require('tpl/header.php');
echo "Hello World!";
?>
<hr>
Of course, I would include footer too, and also in index.php I would implement html code specially designed for that page, but like I wrote, I want to know If I am thinking good - to send page's name through
$_SESSION variable.
You don't need a session in your case. When you include your header you can use your variables directly in your included script. When you have a template engine you take another way. In that case you load a template file and replace your variables and return the parsed HTML code to your PHP file and print them out.
main.php
$page = "Test";
require('tpl/header.php');
header.php
<!DOCTYPE html>
<html>
<head>
<title><?php echo $page ?></title>
</head>
<body>
<h3>HEADER</h3>
</body>
</html>
<hr>
What you try here is good for learning but not really common in production. There are a ton of really good Frameworks that gives you a perfect structure and help you to prevent mistakes. For your Programm you could start with a template engine like Twig or Dwoo for example. So first you should learn the basics then you can build a website on your own or good tools. Building a good framework is really hard.
I'm working with PHP Fat Free and I am attempting to create a layout/sublayout system which will eventually mimic MVC to some extent. I have a main layout which has placeholders (essentially the backend sets different sublayout or partial file paths and then the view takes care of calling the rendering of that file name. This all works great.
The issue I'm running into is when I need inline javascript in my sublayout to run after scripts in the main layout (after the jquery include line, for instance). In a previous framework I was using, I was able to do us output buffering ob_start and ob_get_clean to grab the script in the sublayout and then pass that to the layout to display below the script line. I hope that makes sense, but if not, here's the current code I'm working with in F3.
The route:
$f3->route('GET /test',
function($f3) {
// set the sublayout name
$f3->set('sublayout', 'testpage.php');
// render the whole shebang
echo View::instance()->render('testlayout.php');
}
);
The layout:
<!DOCTYPE html>
<html>
<head>
<title>Test Layout</title>
</head>
<body>
<h1>Test Layout</h1>
<?php echo View::instance()->render($sublayout) ?>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" />
<!-- inline script should go here -->
</body>
</html>
The sublayout:
<h2>My Test Page</h2>
<div id='message'></div>
<script>
// This code needs to be placed AFTER the jquery include in the main layout
$(function(){
$('#message').html('This is my message');
});
</script>
I tried extending the view to include a "beginRegion" and endRegion function that basically handled the ob_start and ob_get_clean portion so that my inline script could be picked up, but once I'm in the sublayout I wasn't able to figure out how to pass that buffered code back to the layout so it could be echo'd after the jquery include.
Before you tell me that I should not be using inline script, I know this and most things I do are in external script files which I have a solution for including, but there are times when I need it inline and that's where I'm stuck.
Is there a way to handle what I'm trying to do with output buffering, or better yet is there a better way to solve this than the output buffering approach?
Update:
Best practices generally dictate that you should include the script at the bottom of the page right before the closing body tag. If I put the script above the sublayout, it breaks both our FE best practices and has the disadvantage of blocking the rest of the page while the script downloads. That's why I'd like to keep it structured the way I have noted instead of placing the jquery include ABOVE the sublayout.
I don't understand what's the problem.
Your layout is:
<!DOCTYPE html>
<html>
<head>
<title>Test Layout</title>
</head>
<body>
<h1>Test Layout</h1>
<?php echo View::instance()->render($sublayout) ?>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" />
<!-- inline script should go here -->
</body>
</html>
You want to include sublayout after jquery usage. So why not to write it like this? :
<!DOCTYPE html>
<html>
<head>
<title>Test Layout</title>
</head>
<body>
<h1>Test Layout</h1>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" />
<!-- inline script should go here -->
<?php echo View::instance()->render($sublayout) ?>
</body>
</html>
Also You can write custom function. Lets say You've folder with partials or something else more structured and want to use it:
$f3->set('partial',
function($file) {
$file .= (strpos($file, '.php')>0)? '' : '.php';
if(!is_file($file)) return '';
return View::instance()->render($file);
}
);
and then use it like:
<!DOCTYPE html>
<html>
<head>
<title>Test Layout</title>
</head>
<body>
<h1>Test Layout</h1>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" />
<!-- inline script should go here -->
{{ #partial('partials/testpage') }}
</body>
</html>
I knew why You want to do so. But what's the problem to decouple scripts in scripts.php file and HTML,php part to another file and render them as needed? (:
From a google groups discussion I had, someone offered up a JS solution that might work:
inside your layout:
<head>
<script>
var callbacks=[];
</script>
</head>
<body>
<script src="...jquery.min.js"/>
<script>
$.each(callbacks,function(i,func){func.call(null,jQuery);}) //<< triggers all queued callbacks
</script>
</body>
inside your sublayout:
<h2>My Test Page</h2>
<div id="message"></div>
<script>
callbacks.push(function($){
//do something with jQuery
});
</script>
Here's the link:
https://groups.google.com/forum/#!topic/f3-framework/iGcDuDueN8c
Our current site is broken down into various easy to work with PHP includes that are brought together using one of those nifty PHP templating libraries.
We currently use an Ant build to optimize most of our front-end code in regards to concatenating, minifying and image optimization. What we would like to do is add an additional Ant task that will parse the PHP template files and output static HTML pages into our build folder.
Could anyone point me in the right direction?
A very basic example below of what I would like to achieve:
PHP template before build
<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/tpl/basic-template.php');
startblock('title');
echo 'Test page';
endblock();
startblock('content');
include($_SERVER['DOCUMENT_ROOT'].'/incl/content-fragment.php');
endblock();
?>
Is it possible through an Ant task to create the static HTML page of the above as so:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test page</title>
</head>
<body>
<p>This paragraph was the contents of content-fragment.php</p>
</body>
</html>
You could use the Ant Get task by hosting files in a build server that is running apache:
<get src="http://buildserver/index.php" dest="app/index.html"/>
As of right now, the way I use includes is to bring the header, footer, and some content for other pages.
This leads to more includes then I really want, because I need to add more content for the includes.
For example:
<!DOCTYPE html>
<?php include('header.php'); ?>
<body>
<?php include('body-top.php');
custom html
</?php include('footer.php');
</body>
It would be nice if I could add variables to the includes and on the pages I want the includes to show.
I am not good at PHP at all, so is there a better way to use Includes?
This can be easily done:
index.php
$title = 'Hello World!';
include 'content.php';
content.php
<!DOCTYPE html>
<html>
<head>
<title><?php echo $title; ?></title>
</head>
<body></body>
</html>
The problem with this approach is, you'll soon run into problems keeping track what went where, so using functions as suggested in other answers might be a good idea. However, for small projects it's IMHO good enough.
sounds like a job for Smarty
It looks like this
<?php
require 'Smarty/libs/Smarty.class.php';
$smarty = new Smarty;
$smarty->assign('title','Hello World');
$smarty->assign('hello','Hello World, this is my first Smarty!');
$smarty->display('test.tpl');
?>
test.tpl
<html>
<head>
<title>{$title}</title>
</head>
<body>
{$hello}
</body>
</html>
Or even better way, use some of the PHP MVC frameworks, which will give you even more stuff (not just template system)
Your includes are already very few, no need to optimize them.
Also don't pay attention to people suggesting Smarty or MVC's because that will increase dramatically the number of includes (in exchange for other benefits, of course)-
You can turn your included files into functions. PHP has a neat trick where anything between curly-brackets (i.e. { and }) is only executed when that part of the code is reached. This includes the HTML code outside of your PHP tags.
This could be our 'header.php' file, where we wrap our current code in a function.
<?php function doHeader($title) { ?>
<html>
<head>
<title><?php echo $title; ?></title>
</head>
<?php } ?>
Then we make a tester for it. Whatever our tester/caller chooses to pass as $title shows up in our output.
<?php
// All included here
include_once('header.php');
?><!DOCTYPE html>
<?php doHeader('My page title'); ?>
<body></body>
</html>
This produces the output,
<!DOCTYPE html>
<html>
<head>
<title>My page title</title>
</head>
<body></body>
</html>