So I had a question on general organization of code for the Zend framework with regard to the layout.
My layout is basically this:
(LAYOUT.PHTML)
<div id='header'>
<?= $this->Layout()->header ?>
</div>
<div id='main'>
<?= $this->Layout()->main ?>
</div>
<div id='footer'>
<?= $this->Layout()->footer ?>
</div>
and so on and so forth. Now, in order to keep my code in my header separate from the code of my main and the code of my footer, I've created a folder for my view that holds header.phtml, main.phtml, footer.phtml. I then use this code to assign the content of header.phtml into $this->layout()->header:
(INDEX.PHTML)
$this->Layout()->header = file_get_contents('index/header.phtml');
$this->Layout()->main = file_get_contents('index/main.phtml');
$this->Layout()->footer = file_get_contents('index/footer.phtml');
That was working great, but I've hit a point where I don't want main to be static HTML anymore. I would like to be able to insert some values with PHP. So in my Controller in indexAction, I want to be able to load from my database and put values into index/main.phtml. Is there a way to do this without restructuring my site?
If not is there a way to do it so that I can have:
The ability to put code into different sections of my layout, such as Layout()->header, Layout->footer.
Separate these pieces into different files, so that they're easy to find and organize, like my index/footer.phtml, index/main.phtml etc.
Not have to put that code into quotes unnecessarily to turn it into a string to pass it to Layout()->header etc.
Thank you guys so much for your help.
-Ethan
Here is an idea:
Assign layout()->header the filename instead of the contents.
Put your code in this file
In your layout file, include() or require() the layout->header().
Since your layout headers/footers are now parsed, you can use them just like a view.
The ->header in $this->layout()->header is response segment. You can render parts of response using $this->_helper->viewRenderer->setResponseSegment('header'); in an action.
If you use
$this->layout()->header = $this->render('index/header.phtml');
It will even use the view, therefore keeping all your variables defined when rendering the header.
I would suggest using something like
<?php echo ($header = $this->layout()->header)?
$header : $this->render('headerDefault.phtml'); ?>
in your layout file - it will render a default header from the layout folder if the view script doesn't override it.
Have you tried looking at view helpers. They are a way of structuring view logic into reusable and modular code. In this case you would use a view helper to generate each of your required segments. So your example view script would look like
$this->Layout()->header = $this->header();
$this->Layout()->main = $this->main();
$this->Layout()->footer = $this->footer();
The benefit of using view helpers over include and require statements is that all of the file handling and name resolution is handled by the framework. The manual has more information on how to set up the paths and usage examples etc.
helpers are good. Another option is like the above, putting filenames in header/footer - put the template names and use $this->render($this->layout()->header)), etc etc. This is just like the include/require above, but more consistent.
Related
I don't want to use an MVC framework. I don't want to use a template engine. I am a few man shop where the developers where all the hats, no graphic artists. We do it all (all layers). I do not want code mixed with presentation, like I have with Classic ASP.
But, I do not know what my code is suppose to look like between server side and the actual presentation.
If I'm not emitting HTML in my server side code, how does it get to the HTML page so I can do things like <span><?= $myvar ?></span>? and put loops in the html page?
Thank you for any advice.
For using loops and all, I use the alternative syntax for the control structures.
An example:
<div id="messages"<?php if(!(isset($messages) && count($messages))): ?> class="hidden"<?php endif; ?>>
<?php if(isset($messages)): ?>
<?php foreach($messages as $message): ?>
<div class="message"><?php echo $message; ?></div>
<?php endforeach; ?>
<?php endif; ?>
</div>
For more information, see this: http://php.net/manual/en/control-structures.alternative-syntax.php
Oh also, I use a semi-MVC structure, where I have a class that handles templates (views), basically it's just a class that I create an instance of, pass a set of variables, then render the template when the instance get destroyed. I have an array of variables in that class, and then use extract to pass all variables in the include, like so:
extract($this->variables, EXTR_SKIP);
include($this->file);
EDIT: Here is the same example in Smarty:
<div id="messages"{if isset($messages) && !count($messages)} class="hidden"{/if}>
{if isset($messages)}
{foreach from=$messages item=message}
<div class="message">{$message}</div>
{/foreach}
{/if}
</div>
Simple PHP projects usually generate the full HTML in-place instead of populating templates, so you'd just echo it out in your PHP code.
This gets messy, so you WILL end up coding some kind of templating system for any moderately complex website.
A possible alternative is to serve your page as completely static HTML/CSS and use AJAX to fetch the actual contents dynamically (JSON would be a good transport format, it's native to JS and can easily be generated from PHP). This gets you rid of all the HTML littered across your PHP code. Whether this is a viable alternative or not depends on the case.
<span><?= $myvar ?></span> works.
A loop would look like:
<html>
<body>
<?php
for ($i=1; $i<=5; $i++)
{
echo "The number is " . $i . "<br />";
}
?>
</body>
</html>
Example taken from here.
I really recommend that you use the php Template Inheritance system. (Don't let it scare you, it's only one file.) This is a simple set of functions that helps you to build extensible PHP views without the problems and limitations of manual includes.
It's still Pure PHP, so you don't need to learn some strange template language. It may not look like much, but it's really powerful once you start using it.
To be sure, you can do it all by yourself - but what you want is still MVC pattern, or separation of concerns ("I do not want code mixed with presentation"). Or at least MV, for very simple applications (although it's still dirty, having models directly influence the view).
The easiest way to achieve this is to first collect and process all data, then just print them. No complex code allowed in the php files directly exposed to the web.
<?php
require('model.inc');
process_capuchin_monkey_order_form();
?>
...
<h1>Thank you for your order of <?php echo $order->num_monkeys; ?> monkeys.</h1>
...
typically you would want to just make sure you have as little PHP in your HTML as possible. This means doing all of the data processing before hand, and simply passing a set of variables in one way or another to a method or function that includes the HTML.
Any HTML with PHP intermixed could be considered a template. Here's a simplified example:
// view class
class View {
public function render($html_template) {
include('view_path/' . $html_template . '.php');
}
}
// html template file 'view_path/main.php'
<html>
<body>
<h1><?= $this->title ?></h1>
</body>
</html>
// usage
$view = new View();
$view->title = 'Some Title';
$view->render('main');
You should use an MVC-like separation of concerns no matter what you do. This means:
At least one file is all html and is given a handful of variables. (view/template)
At least one file is all php and only talks to the database. (model)
At least one file processes the http request, pulls data from database, and executes the view.
The core of every php templating language is the use of extract() and include inside a function:
function render_template($___filename, $___data) {
extract($___data, EXTR_SKIP);
include $__filename;
}
You can pretty this up with a class interface (view objects) or with output buffering, but this is the core of every template system. Your controller's responsibility is simply to assemble that $__data argument (usually with data from a database) for a given view.
If I have 10 images, 2 javascript files, and 4 css files that need to be included inside a Ci view... How is the best way to call all the files? I've tried calling all the external files using $this->load->view('image1.png') and $this->load->view('style.css'). But it doesn't seem to work properly. Any ideas on how to better approach this problem?
You're not using the view method correctly there.
You typically assign one view and pass things like js and css to the template. This can vary depending on how you use the framework.
$this->load->view('path-to-view'); will look for a view in the view folder and not an arbitrary file.
You might look into this:
http://codeigniter.com/user_guide/helpers/html_helper.html#img
for loading images, though I personally think it's pointless to call a framework's method for a basic html element like an image.
There are cases when you would use multiple views, like views to be returned as strings - loops and such may need these - but that doesn't look like the case in your question.
Just in case though here's the view docs:
http://codeigniter.com/user_guide/general/views.html
To elaborate further, the general idea is to use the CI controller to handle the data for your page, pass the necessary template data to the template (like your js and css specific to this page) then assign the necessary data to the view and pass that view to the template. You may be wondering what I mean by template too, since out of box CI loads views progressively if you just call them sequentially.
in your controller you may pass the view an array of header info:
$data['css'] = array('some-path.css','another-path.css');
$this->load->view('your-view', $data);
so in your view that handles the header you might call something like this:
<head>
<?php foreach($css AS $c): ?>
<link rel="stylesheet" type="text/css" href="<?php echo $c; ?>">
<?php endforeach; ?>
</head>
Here's a fair link to CI templates:
How to Deal With Codeigniter Templates?
It's a versatile framework with many options for using it however you are most comfortable.
I have been designing websites for a while now, but there is one thing that I have never been quite sure of when using PHP and HTML. Is it better to have the whole document in PHP and echo HTML like so:
<?php
doSomething();
echo "<div id=\"some_div\">Content</div>";
?>
Or have a HTML file like so and just add in the PHP:
<html>
<body>
<?php doSomething(); ?>
<div id="some_div">Content</div>
</body>
</html>
It seems tidier to echo HTML, especially if lots of PHP gets used throughout the page, but doing so loses all formatting of the HTML i.e. colors in the IDE etc.
There are varying opinions on this. I think there are two good ways:
Use a templating engine like Smarty that completely separates code and presentation.
Use your second example, but when mixing PHP into HTML, only output variables. Do all the code logic in one block before outputting anything, or a separate file. Like so:
<?php $content = doSomething();
// complex calculations
?>
<html>
<body>
<?php echo $content; ?>
<div id="some_div">Content</div>
</body>
</html>
Most full-fledged application frameworks bring their own styles of doing this; in that case, it's usually best to follow the style provided.
I think this would depend on your group's or your own decided convention. And it can and should vary depending on what type of file you're working in. If you follow the MVC pattern then your views should be the latter. If you're writing a class or some non-output script/code then you should use the former.
Try to keep a separation of display or formatting of output and the logic that provides the data. For instance let's say you need to make a quick page that runs a simple query and outputs some data. In this case (where there is no other existing infrastructure or framework) you could place the logic in an include or in the top or the bottom of the file. Example:
<?php
# define some functions here that provide data in a raw format
?>
<html>
<body>
<?php foreach($foo = data_function($some_parameter) as $key => $value): ?>
<p>
<?=$value;?>
</p>
<?php endforeach; ?>
</body>
</html>
Or you could place the logic and function definitions in an include file or at the bottom of the file.
Now if you're producing some sort of class that has output (it really shouldn't) then you would echo the HTML or return it from the method being called. Preferably return it so that it can be output whenever and however the implementer would like.
The syntax highlighting is an important benefit of the second method, as you said. But also, if you're following good practices where logic and presentation are separated, you will naturally find that your files that contain HTML are almost entirely HTML, which then, naturally, leads to your second method again. This is the standard for MVC frameworks and the like. You'll have a bunch of files that are all PHP, doing logic, and then when that's done they'll include a presentation file which is mostly HTML with a sprinkling of PHP.
Simple:
More PHP - close HTML in PHP. When you generate HTML code in PHP, when you are doing something like a class, so it is better to make it in echo.
Less PHP - close PHP in HTML. This is stuff like just putting vars into fields of HTML stuff, like forms... And such.
The best approach is to separate the HTML from the PHP using template system or at least some kind of HTML skeleton like:
<main>
<header/>
<top-nav/>
<left-col>
<body />
</left-col>
<right-col />
<footer/>
</main>
Each node represents a template file e.g. main.php, hrader.php and so on. Than you have to separate the PHP code from the templates as something like functions.php and fineally use your second approach for template files and keeping functions clean of "echos" and HTML.
If you can, use a template engine instead.
Although it is slightly easier at first to mix your HTML and PHP, separating them makes things much easier to maintain later on.
I would recommend checking out TemplateLite which is based on Smarty but is a little more light weight.
I've reached a conclusion that using views in MVC framework e.g. Laravel, Yii, CodeIgniter is the best approach even if you are not displaying the html straight away.
Inside the view do all the echoing and looping of prepared variables, don't create or call functions there, unless formatting existing data e.g. date to specific format date('Y-m-d', strtodate(123456789)). It should be used only for creating HTML, not processing it. That's what frameworks have controllers for.
If using plain PHP, create you own view function to pass 3 variables to - html file, array of variables, and if you want to get output as string or print it straight away for the browser. I don't find a need for it as using frameworks is pretty much a standard. (I might improve the answer in the future by creating the function to get view generated HTML) Please see added edit below as a sample.
Frameworks allow you to get the HTML of the view instead of displaying it. So if you need to generate separate tables or other elements, pass the variables to a view, and return HTML.
Different fremeworks may use various type of templating languages e.g. blade. They help formatting the data, and essentially make templates easier to work with. It's also not necessary to use them for displaying data, or if forced to use it by the framework, just do required processing before posting the variables, and just "print" it using something like {{ yourVariable }} or {{ yourVariable.someProperty }}
Edit: here's a plain PHP (not framework PHP) - simple-php-view repository as a sample view library that allows to generate HTML using variables. Could be suitable for school/university projects or such where frameworks may not be allowed.
The repository allows to generate HTML at any time by calling a function and passing required variables to it, similar to frameworks. Separately generated HTML can then be combined by another view.
It depends on the context. If you are outputting a lot of HTML with attributes, you're going to get sick of escaping the quotation marks in PHP strings. However, there is no need to use ?><p><? instead of echo "<p>"; either. It's really just a matter of personal taste.
The second method is what I usually use. And it was the default method for me too. It is just to handy to get php to work inside html rather than echo out the html code. But I had to modify the httpd.conf file as my server just commented out the php code.
Is there any way I can pre-process a PHP view script without using a particular MVC framework?
Basically I want to render the view and pass it as an HTML string to another view. The view I'm trying to render has some references like $this->rows, and, of course, I would need to add the values of those references to the script before generating the HTML.
Is this possible?
Yes it is completely possible. You'll want to utilize output buffering to ensure the initial view isn't displayed and then store that views output in a variable.
ob_start();
include ('/path/to/file.php');
$contents = ob_get_contents();
ob_end_clean();
The way to do it depends on the framework you're using.
But this can be done with PHP by just using nested includes.
For example
page.php
<?php include(HEADER) ?>
<?= $var ?>
<?php include(FOOTER) ?>
All variables available to page.php will be available to the header and footer views as well.
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(); ?>