Lightweight, PHP based, layout framework...know of any? [closed] - php

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
I'm looking for a lightweight, PHP based, layout framework. Like how the Zend Framework, uses layouts, I would like to create a layout template and include only the content for the necessary pages.
<html>
<head>
<title><?= $pageTitle ?></title>
</head>
<body>
<?= $content ?>
</body>
</html>
Anyone know of anything that does this? I would use the Zend Framework, but it's just too much for what I want to achieve.

I vote for PHP. (PHP is a templating engine.)
function template($file, $vars) {
ob_start();
if(count($vars) > 0) { extract($vars); }
include 'views/'.strtolower($file).'.php';
return ob_get_clean();
}
Which, incidentally, lets you do the following.
echo template('layout', array( 'content' => template('page', $myData) ));
Should you even bother using another templating/layout engine at all, when PHP itself can suffice in a mere 6 lines?
Edit:
Perhaps I wasn't clear with how this works.
template() is called with the name of the template (subdirectories for organization work too) with an array object as the second parameter. If the variables given aren't blank, like template('index',null) is, then the array is treated as an associative array: and every key becomes a variable containing the value.
So the logic becomes:
template('my_template', array(
'oranges' => 'apples'
));
And "views/my_template.php" is:
<html>
<head>
<title>Are apples == <?= $oranges ?>?</title>
</head>
<body>
<p style="color: <?= $oranges == 'oranges' ? 'orange" : 'darkgreen' ?>">
Are apples == oranges?
</p>
</body>
</head>
So, every time the variable $oranges is used PHP gets the data that was exported from the array, $vars['oranges'].
So all the output is then taken by ob_get_clean() and returned as a string. To output this string just echo or print, or assign it to an array to be passed as content to the layout. If you understand this, then it is very easy to take what I've written and make a layout out of it, or pages with logic that output JSON even.
I would advise you to experiment with this answer before discarding it. It has a tendency to grow on you.
Edit 2:
As requested I'll show the directory layout that my project would use. Do note that other MVC frameworks use a different structure. But, I like the simplicity of mine.
index.php
application/
framework.php
controllers/
welcome.php
views/
template.php
index.php
For security purposes, I have an .htaccess file that routes every request, except those to js/ or css/, to the index.php script, effectively making my directories hidden. You could even make the CSS via a template if you wished, which I've done, for the use of variables, etc.
So, any call made to template('template', array()) will load the file ./views/template.php automatically. If I included a slash in the name, it becomes part of the path, like so: ./views/posts/view.php.
Edit 3:
thanks for your update. So you must have some code in your index.php file that routes the requested url to the appropriate controller, correct? Could you show some of this? Also, it doesn't look like your views mirror your controller directory. Can you explain a little more how urls map to controllers and/or views? What do you have in framework.php? What does it do? Thanks!
The code I've shown is a tiny excerpt of my private framework for web development. I've talked already about potentially releasing it with a dual-license, or as donation-ware for commercial use, but it's nothing that can't be written by anyone else in a short (15-21 days) time. If you want you can read my source code on GitHub... but just remember that it's still alpha material.
The license is Creative Commons SA.

If you want super-lightweight, you could use an auto-prepend file, mixed with some output buffering to build what you want. For starters, you need to set up your prepend and append files - put the following lines in your .htaccess file (you'll probably want to make the prepend and append files unreadable to visitors, too):
php_value auto_prepend_file prepend.php
php_value auto_append_file append.php
Then in your prepend.php file, you'll want to turn on output buffering:
<?php
ob_start();
In append.php, you'll want to grab the contents of the output buffer, clear the buffer and do any other processing of the content you want (in this example, I set a default page title).
<?php
if (!isset($page_title)) {
$page_title = 'Default Page Title';
}
$content = ob_get_contents();
ob_end_clean();
?>
<html>
<head>
<title><?php echo $page_title; ?></title>
</head>
<body>
<?php echo $content ?>
</body>
</html>
After this, you can write each page normally. Here's an example index.php
<?php
$page_title = "Index Page!";
?>
<h1>This is the <?php echo __FILE__; ?> page</h1>
...and an example other.php that does something halfway interesting:
<?php
$page_title = "Secondary Page!";
?>
<h1>This is the <?php echo __FILE__; ?> page</h1>
<p>enjoy some PHP...</p>
<ol>
<?php for ($i = 1; $i <= 10; $i++) : ?>
<li><?php echo "$i $i $i"; ?></li>
<?php endfor ?>
</ol>
And you're done. You can grow on this a bit, such as initializing DB connection in the prepend, but at some point, you'll probably want to move to a more abstract system that breaks out of a fixed mapping of URLs to paths and files.

I'm actually about to release one at europaphp.org along with examples and a full documentation. It's very similar to the Zend Framework in conventions and coding standards. I'll post something when it is done; probably within the next week.
You can get the code at: [http://code.google.com/p/europa/source/browse/#svn/trunk/Sandbox - Default][1].
That link will bring up the latest svn for the Sandbox which you can just download and start using without any configuration.
Currently, it's faster than most any other PHP framework out there.
[1]: http://code.google.com/p/europa/source/browse/#svn/trunk/Sandbox - Default

BareBones: a one-file, no-configuration, MVC framework for PHP5

FryPHP is about as lightweight as it gets.

Limonade might also be useful... not strictly layout.

I've been using Smarty for ages.
It's mature, actively maintained, and widely supported.
Anyway, you'll find a whole range of template engines here:
http://en.wikipedia.org/wiki/Template_engine_(web)
If you click the languages column, you'll easily see what's available for PHP, and how the engines compare.

Just to throw in another framework: CodeIgniter is IMHO very nice, uses an MVC approach, so you'd output your files as views and says to have a small footprint. It also has a template parser on board.
Cheers,

Related

Converting a site from a PHP site into a full LemonStand e-commerce site

Brand new to LemonStand, and it's my front-runner for developing a client's web site.
This first candidate for utilizing LemonStand is a newly built web site I built in PHP.
I've got all of the non-e-commerce pages (things like about and contact) pulling from the LemonStand CMS.
But now I am trying to convert what were simple PHP includes to partials:.
Example:
<? include 'standard_include.php'; ?>
<? include 'header.php'; ?>
to LemonStand's
<? $this->render_partial('standard_include') ?>
<? $this->render_partial('header') ?>
I get an unhandled exception related to undefined variables:
This is what the beginning my page/template looks like
<?php
require_once('lib/php/configuration.php');
$pagetype = 'home';
$subpagetype = 'index';
$titleValue = 'Client Name';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title><?php echo $titleValue ?></title>
<? $this->render_partial('standard_include') ?>
</head>
<body>
<? $this->render_partial('header') ?>
Do the partials not render till later in the page load process (as compared to PHP includes)?
Am I utilizing partials incorrectly? If so, what do I do to put the PHP includes into the LemonStand backdoor system?
I've never used Lemonstand, but if its MVC works like other MVC systems, then you need to inject the variables needed by standard_include into the view. Something like:
$this->renderPartial('standard_include', array('pagetype'=>$pagetype, ...)) ?>
Otherwise the partial won't have access to the variables you defined in your parent template because the partial is rendered in a different context.
PHP include works differently. It just literally inserts the included file in place at that point before the script is executed.
I'm thinking the render_partial is happening after the pages start rendering, while the include happens prior, so it has a value for pagetype.
I'm thinking the solution is going to be to keep them includes. I just won't be able to have every file in their admin/backend system.
For common elements, the included templates with LemonStand don't seem to do anything but have them inline, which obviously isn't optimal for making a change across a site for something like a header or footer.

Beginner's guide to making a template driven PHP site

Do you know of any site that can help me start with making template driven sites in PHP?
First off I'll go ahead and start out with Smarty, since I've used it quite a lot. Since this is a community wiki, feel free to plug in examples of your own templating engine should you choose.
Installing Smarty
Templating provides a great way of structuring your HTML and separating out your HTML content from your logic code. It also provides a way to organize individual components of your HTML page, so it's easier to manage, and is more re-usable.
To start, we'll take at showing a simple page with Smarty. First off you need to actually get Smarty. So we'll head down to the Smarty download page. As of this writing, the latest stable version is Smarty 3.0.7, so we'll go ahead and download that. Downloading the .tar.gz file or the .zip file is up to the system you have. For Windows and Mac users (most likely using MAMP or XAMPP), .zip is probably a good choice, though you can always get programs to handle .tar.gz files. Users with Linux or *BSD type systems can grab the .tar.gz version.
Now then, we extract the file and get the following directory layout:
COPYING.lib
demo/
libs/
|__ Smarty.class.php
|__ ... some other files and folders ...
README
SMARTY2_BC_NOTES
Now, Smarty.class.php is the main file we're going to include to use Smarty. It's located in the libs directory. As 'libs' is a pretty generic sounding name, we're going to copy this to our document root folder, and rename it to Smarty. Now our theoretical document root folder is currently empty, so it will end up looking like this:
Smarty/
|__ Smarty.class.php
|__ ... some other files and folders ...
A Simple Template
Now that Smarty is installed, we'll create a very basic template and php script to show how it works. First off, to keep things organized we'll make a templates folder to keep our templates in. Then we'll create a mypage.php file, and a mypage.tpl file in our templates folder:
mypage.php
templates/
|__ mypage.tpl
Smarty/
|__ Smarty.class.php
|__ ... some other files and folders ...
mypage.php
<?php
require_once('Smarty/Smarty.class.php');
$smarty = new Smarty();
$smarty->assign("MYVAR", "Hello World");
$smarty->display("templates/mypage.tpl");
?>
templates/mypage.tpl
<html>
<head>
<title>My Sample Page</title>
</head>
<body>
<h1>{$MYVAR}</h1>
</body>
</html>
Now if we navigate to mypage.php, for example http://localhost:8000/mypage.php, "Hello World" will be displayed in large bold text. So what happend? Let's step through the code:
require_once('Smarty/Smarty.class.php');
Here we include the main Smarty class. We need this for any and all Smarty functionality.
$smarty->assign("MYVAR", "Hello World");
You'll be using this a lot. The assign command takes a value, "Hello World" in this example, and assigns it to a name, "MYVAR". If you look at the template:
<h1>{$MYVAR}</h1>
You'll notice {$MYVAR}. The {}'s indicate to Smarty that it needs to evaluate the expression inside. This could be a command or simply a variable. It could produce output or simply set a variable value. In this case, it simply outputs the value of $MYVAR that we assigned.
$smarty->display("templates/mypage.tpl");
Finally, we tell Smarty to parse the template, then display it as if you had simply echo'ed out HTML in a PHP page. Fancy eh? Now, a lot of people will want to iterate through arrays (ie. a set of db results), so let's take a look at an example of how to achieve that.
Looping Through Arrays
First we'll make adjustments to our code. The new listings are as follows:
mypage.php
<?php
require_once('Smarty/Smarty.class.php');
$myarray = array(
"John",
"Jane",
"Henry",
"Nancy",
"Gorilla"
);
$smarty = new Smarty();
$smarty->assign("MYARRAY", $myarray);
$smarty->display("templates/mypage.tpl");
?>
templates/mypage.tpl
<html>
<head>
<title>My Sample Page</title>
</head>
<body>
<h1>Results</h1>
<ul>
{foreach $MYARRAY as $myvalue}
<li>{$myvalue}</li>
{/foreach}
</ul>
</body>
</html>
If you reload the page, you'll get something like this:
Now, there are only a few changes to note:
$smarty->assign("MYARRAY", $myarray);
Instead of a string value, we assigned a variable which holds an array. This was passed to Smarty which used the data in the {foreach} loop:
<ul>
{foreach $MYARRAY as $myvalue}
<li>{$myvalue}</li>
{/foreach}
</ul>
The foreach in Smarty is much like the foreach of PHP. In this case, Smarty takes the array that was assigned to $MYVALUE and loops through it, setting $myvalue to the result of the current loop value. From there we can use {$myvalue} to refer to each individual item. Now, let's say we want to make this unordered list a widget to reuse in other places. We can do that through using templates themselves as variables.
Template Modularization
HTML can get very long very quickly. Smarty helps manage this by letting you break out parts of the page into individual components. So what we'll do is take our unordered list and put it into a separate page. Our new code will look like this:
mypage.php
<?php
require_once('Smarty/Smarty.class.php');
$myarray = array(
"John",
"Jane",
"Henry",
"Nancy",
"Gorilla"
);
$smarty = new Smarty();
$smarty->assign("MYARRAY", $myarray);
$content = $smarty->fetch("templates/mycontent.tpl");
$smarty->assign("MYCONTENT", $content);
$smarty->display("templates/mypage.tpl");
?>
templates/mypage.tpl
<html>
<head>
<title>My Sample Page</title>
</head>
<body>
<h1>Results</h1>
{$MYCONTENT}
</body>
</html>
mycontent.tpl
<ul>
{foreach $MYARRAY as $myvalue}
<li>{$myvalue}</li>
{/foreach}
</ul>
The result we get is the same, however the backend is now more organized. We can now reuse this mycontent.tpl file in other pages if we want. Common usages of this organization is making header, footer, and other parts of the page individual templates. This lets you narrow down to relevant pieces.
So what happened on the backend? The important command to take note of here is:
$content = $smarty->fetch("templates/mycontent.tpl");
fetch() works like display, except that instead of outputting it right away, it returns the result as a string of the rendered HTML. Note that because $MYARRAY is used in the mycontent.tpl, we have to assign the array right before it, not right before the final display() call. This ordering is important!
Conclusion
This concludes the very basic introduction to Smarty, and using a templating engine to work with managing your content. The Smarty Documentation provides a great resource for seeing all that smarty is capable of. Be sure to look through all the available commands to make sure you're using it efficiently!
Smarty for PHP is an adequate templating system. You can try and use that, plus their documentation to help develop a template driven website.
Depending on your needs you can create your own templateing system with a couple of included files.
Symfony, in addition to being a good framework, offers Twig.

Is there any way to find in which file - file is included

Am sure the question is vague.
Let me try to explain.
Assume zend frame work - PHP - jquery combination.
I include jquery files in layout.phtml.
i include some files in controller.php.
some file in view.phtml
Atlast when i run and view the page . Is there any way or any tool to find which file is included through which file (layout controller or view) ??
In addition can some one explain which is the best way include js files and where . using zend framework in layout or controller or view
The only way to find where a public, static asset (JS, CSS, image, etc) is included is to trawl through the source code (using something that can "find in files" would save time).
In regards to how and where to include such assets... for global includes (common stylesheets, scripts, etc), include these in your layouts.
For specific page includes, place these in your views.
The best way to include a static asset is using the appropriate view helper. These are generally displayed in your layout file, for example
<?php echo $this->doctype() ?>
<html>
<head>
<?php
echo $this->headMeta()->prependHttpEquiv('Content-Type', 'text/html; charset=' . $this->getEncoding());
// I use "prepend" here so it comes before any page specific stylesheets
echo $this->headLink()->prependStylesheet($this->baseUrl('/css/common.css'));
echo $this->headScript();
?>
</head>
<body>
<!-- content -->
<?php echo $this->inlineScript() ?>
</body>
</html>
You can then add to these placeholders in your view scripts, for example
<?php
// index/index.phtml
$this->inlineScript()->appendFile('https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js')
->appendFile($this->baseUrl('/js/my-jquery-script.js'));
To "include" a file means very different things in PHP (where it is analogous to copying and pasting source code from another file into the current file) and HTML/JavaScript (where you are referencing another file, which the browser must make a separate HTTP request to download). What do you consider "including"? Are image tags "including" the images? At least we can easily count those references by examining HTTP requests; from the client side, it's impossible to tell what include()s went into the source code behind the rendered output. Even naive source code searching couldn't tell you thanks to autoloading. As is, your question is not well enough defined to provide a clear answer.
Controversal answer:
You don't need that.
If you need that then it's something wrong with the way your designed your application.
Note: I've learned (trial and error) that 90% of things I don't know how to do and that seem to be impossible in ZF are a result of wrong application design.

How could you create a "content_for" equivalent in PHP?

I've been working on a small page in PHP, one that doesn't need the power of a full-fledged framework behind it. One thing that I'm really missing from previous work in Ruby-on-Rails is the ability to effectively pass content up the page using "content_for".
What I was wondering is, how could you create a page lifecycle that would accomplish this same effect in PHP?
So, here's a simple example:
Let's say you have a template that defines an index page, just a recurring header and menu you want to use on all your pages. So your index.php file looks basically like this:
...header stuff...
<body>
<?php include $file.'.php'; ?>
</body>
...footer stuff...
EDIT: Thanks for the tips on URL security, but let's just assume I'm getting the user request safely :)
Now, lets say in the header you want to put this:
<head>
<title><?php echo $page_title; ?></title>
</head>
It would be nice to be able to specify the title in the included file, so at the url http://example.com/index.php?p=test you're loading test.php, and that file looks like this:
<?php $page_title = 'Test Page'; ?>
... rest of content ...
Now, obviously this doesn't work, because the including page (index.php) is loaded before the variable is set.
In Rails this is where you could pass stuff 'up the page' using the content_for function.
My question is this: What would be the simplest, leanest way that you all can think of to effect this kind of 'content_for' functionality in PHP?
Ideally I'd like suggestions that don't involve strapping on some big framework, but some relatively light boilerplate code that could be used in a lot of different applications.
Never do include $_GET['p']. This opens a huge security hole in your site, as include accepts filenames and URLs, so anybody would be able to read any file on your site and also execute any code on your server. You may want to check and sanitize the value first.
If you need something simple, you may put header and footer in separate files, execute your test.php which would set the variables, capture its output using output buffering, then include the header, output the middle part and include the footer. Example:
<?php ob_start(); ?>
<body>
<?php include $filename.'.php'; ?>
</body>
<?php $content = ob_get_clean();
include 'header.php';
echo $content;
include 'footer.php';
?>
If I understand you correctly (I have not used RoR extensively), you could put your data in a variable or a function. If your content was in a variable, your "test.php" could simply hold all your variables and you could load it at the very beginning of your index file (likewise for a function depending on how complicated your needs are; if you're doing a lot of extra work, you may need to use a function as a variable won't work).
For example, your test.php would look something like this:
<?php
$page_title = "Test Page";
$page_content = "Some sort of content";
// Or
function page_content()
{
// Run some functions and print content at the end
}
?>
Then, in your index.php
<?php include $_GET['p'].'.php'; ?>
...header stuff...
<title><?php print $page_title; ?></title>
<body>
<?php print $page_content; ?>
<!-- OR if function -->
<?php page_content(); ?>
</body>
...footer stuff...
This way everything should load properly. You could also split things up, but that would complicate your structure (especially if there is no need for an elaborate framework, this would be unnecessary).
Good luck!
Dennis M.
Are you worried about XSS? Or are you going to filter/whitelist the "filenames" from the query string?
My answer would be to use mod_rewrite -- if you're using PHP, you're likely using Apache!
You could filter out files with a RewriteCond and your RewriteRule could be:
RewriteRule /index.php?p=(.*)$ $1 [L,QSA]
This may be a different approach than the PHP functionality you were looking for, but it comes to mind...

How is duplicate HTML represented in your codebase, in a non-duplicate way?

Most HTML in a large website is duplicated across pages (the header, footer, navigation menus, etc.). How do you design your code so that all this duplicate HTML is not actually duplicated in your code? For example, if I want to change my navigation links from a <ul> to a <ol>, I'd like to make that change in just one file.
Here's how I've seen one particular codebase handle this problem. The code for every page looks like this:
print_top_html();
/* all the code/HTML for this particular page */
print_bottom_html();
But I feel uncomfortable with this approach (partially because opening tags aren't in the same file as their closing tags).
Is there a better way?
I mostly work with PHP sites, but I'd be interested in hearing solutions for other languages (I'm not sure if this question is language-agnostic).
I'm not a php programmer, but I know we can use a templating system called Smarty that it works with templates(views), something like asp.net mvc does with Razor.
look here http://www.smarty.net/
One solution at least in the case of PHP (and other programming languages) is templates. Instead of having two functions like you have above it would instead be a mix of HTML and PHP like this.
<html>
<head>
<title><?php print $page_title ?></title>
<?php print $styles ?>
<?php print $scripts ?>
</head>
<body>
<div id="nav">
<?php print $nav ?>
</div>
<div id="content">
<?php print $content ?>
</div>
</body>
</html>
Each variable within this template would contain HTML that was produced by another template, HTML produced by a function, or also content from a database. There are a number of PHP template engines which operate in more or less this manner.
You create a template for HTML that you would generally use over and over again. Then to use it would be something like this.
<?php
$vars['nav'] = _generate_nav();
$vars['content'] = "This is the page content."
extract($vars); // Extracts variables from an array, see php.net docs
include 'page_template.php'; // Or whatever you want to name your template
It's a pretty flexible way of doing things and one which a lot of frameworks and content management systems use.
Here's a really, really simplified version of a common method.
layout.php
<html>
<body>
<?php echo $content; ?>
</body>
</html>
Then
whatever_page.php
<?php
$content = "Hello World";
include( 'layout.php' );
Sounds like you need to use include() or require()
<?php
include("header.inc.php");
output html code for page
include("footer.inc.php");
?>
The header and footer files can hold all the common HTML for the site.
You asked for how other languages handle this, and I didn't see anything other than PHP, so I encourage you to check out Rails. Rails convention is elegant, and reflects #codeincarnate 's version in PHP.
In the MVC framework, the current view is rendered inside of a controller-specific layout file that encapsulates the current method's corresponding view. It uses a "yield" method to identify a section where view content should be inserted. A common layout file looks like this:
<html>
<head>
<% #stylesheet and js includes %>
<body>
<div id="header">Header content, menus, etc…</div>
<%= yield %>
<div id="footer">Footer content</div>
</body>
</html>
This enables the application to have a different look and feel or different navigation based on the controller. In practice, I haven't used different layout files for each controller, but instead rely on the default layout, which is named "application".
However, let's say you had a company website, with separate controllers for "information", "blog", and "admin". You could then change the navigation for each in a clean and unobtrusive manner by handling the different layout views in their respective layout files that correspond to their controllers.
You can always set a custom layout in the controller method by stating:
render :layout => 'custom_layout'
There are also great helper methods built into Rails so you don't have to rely on $global variables in PHP to ensure your CSS and Javascript paths are correct depending on your development environment (dev, staging, prod…). The most common are:
#looks in public/stylesheets and assumes it's a css file
stylesheet_link_tag "filename_without_extension"
#looks in public/javascripts and assumes it's a js file
javascript_include_tag "jquery"
Of course, each of these sections could be expounded upon in much greater detail and this is just brushing the surface. Check out the following for more detail:
http://guides.rubyonrails.org/layouts_and_rendering.html
What you suggested works OK. As long as print_top_html and print_bottom_html stay in sync (and you can use automated tests to check this), then you never need to worry about them again, leaving you to focus on the real content of the site -- the stuff in the middle.
Alternatively, you can combine print_top_html and print_bottom_html into a single call, and send it HTML code (or a callback) to place in the middle.
I use the partials system of Zend_View (very similar to Rails). A partial is essentially a small HTML template that has its own variable scope. It can be called from inside views like:
<?php echo $this->partial('my_partial.phtml', array( 'var1' => $myvar ));
The variables that get passed into the construct get bound to local variables inside the partial itself. Very handy for re-use.
You can also render a partial from inside normal code, if you're writing a helper object where you have more complex logic than you'd normally feel comfortable putting in a view.
public function helperFunction()
{
// complex logic here
$html = $this->getView()->partial('my_partial.phtml', array('var1' => $myvar ));
return $html;
}
Then in your view
<?php echo $this->myHelper()->helperFunction(); ?>

Categories