Creating Views in PHP - Best Practice [closed] - php

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I am working on a website with 2 other developers. I am only responsible to creating the views.
The data is available in an object, and I have getters to read the data then create XHTML pages.
What is the best practice to do this, without using any template engine?
Thanks a lot.

If you don't want to use a templating engine, you can make use of PHP's basic templating capabilities.
Actually, you should just write the HTML, and whenever you need to output a variable's value, open a PHP part with <?php and close it with ?>. I will assume for the examples that $data is your data object.
For example:
<div id="fos"><?php echo $data->getWhatever(); ?></div>
Please note that, all PHP control structures (like if, foreach, while, etc.) also have a syntax that can be used for templating. You can look these up in their PHP manual pages.
For example:
<div id="fos2">
<?php if ($data->getAnother() > 0) : ?>
<span>X</span>
<?php else : ?>
<span>Y</span>
<?php endif; ?>
</div>
If you know that short tag usage will be enabled on the server, for simplicity you can use them as well (not advised in XML and XHTML). With short tags, you can simply open your PHP part with <? and close it with ?>. Also, <?=$var?> is a shorthand for echoing something.
First example with short tags:
<div id="fos"><?=$data->getWhatever()?></div>
You should be aware of where you use line breaks and spaces though. The browser will receive the same text you write (except the PHP parts). What I mean by this:
Writing this code:
<?php
echo '<img src="x.jpg" alt="" />';
echo '<img src="y.jpg" alt="" />';
?>
is not equivalent to this one:
<img src="x.jpg" alt="" />
<img src="y.jpg" alt="" />
Because in the second one you have an actual \n between the img elements, which will be translated by the browser as a space character and displayed as an actual space between the images if they are inline.

Use a separate file to read the data:
<?php
if ($foo == False)
{
$bar = 1;
}
else
{
$bar = 0;
}
?>
Then reference the resulting state in the HTML file:
require 'logic.php';
<html>
<!--...-->
<input type="text" value="<?php echo $bar; ?>" > //Logic is separated from markup
<!--...-->
</html>

i dont know it i get realy your question. so if my answer not exaclty i will like to de deleted
this class will create simple view
class View
{
public function render($filename, $render_without_header_and_footer = false)
{
// page without header and footer, for whatever reason
if ($render_without_header_and_footer == true) {
require VIEWS_PATH . $filename . '.php';
} else {
require VIEWS_PATH . '_templates/header.php';
require VIEWS_PATH . $filename . '.php';
require VIEWS_PATH . '_templates/footer.php';
}
}
private function checkForActiveController($filename, $navigation_controller)
{
$split_filename = explode("/", $filename);
$active_controller = $split_filename[0];
if ($active_controller == $navigation_controller) {
return true;
}
// default return
return false;
}
private function checkForActiveAction($filename, $navigation_action)
{
$split_filename = explode("/", $filename);
$active_action = $split_filename[1];
if ($active_action == $navigation_action) {
return true;
}
// default return of not true
return false;
}
private function checkForActiveControllerAndAction($filename, $navigation_controller_and_action)
{
$split_filename = explode("/", $filename);
$active_controller = $split_filename[0];
$active_action = $split_filename[1];
$split_filename = explode("/", $navigation_controller_and_action);
$navigation_controller = $split_filename[0];
$navigation_action = $split_filename[1];
if ($active_controller == $navigation_controller AND $active_action == $navigation_action) {
return true;
}
// default return of not true
return false;
}
}
soo now you can create your templates and can call it from any where just like
$this->view->my_data = "data";
$this->view->render('index/index');
//
and on your index/index.php you can call the data $this->my_data;

Related

How can I replace braces with <?php ?> in php file?

I wanna replace braces with <?php ?> in a file with php extension.
I have a class as a library and in this class I have three function like these:
function replace_left_delimeter($buffer)
{
return($this->replace_right_delimeter(str_replace("{", "<?php echo $", $buffer)));
}
function replace_right_delimeter($buffer)
{
return(str_replace("}", "; ?> ", $buffer));
}
function parser($view,$data)
{
ob_start(array($this,"replace_left_delimeter"));
include APP_DIR.DS.'view'.DS.$view.'.php';
ob_end_flush();
}
and I have a view file with php extension like this:
{tmp} tmpstr
in output I save just tmpstr and in source code in browser I get
<?php echo $tmp; ?>
tmpstr
In include file <? shown as <!--? and be comment. Why?
What you're trying to do here won't work. The replacements carried out by the output buffering callback occur after PHP code has already been parsed and executed. Introducing new PHP code tags at this stage won't cause them to be executed.
You will need to instead preprocess the PHP source file before evaluating it, e.g.
$tp = file_get_contents(APP_DIR.DS.'view'.DS.$view.'.php');
$tp = str_replace("{", "<?php echo \$", $tp);
$tp = str_replace("}", "; ?>", $tp);
eval($tp);
However, I'd strongly recommend using an existing template engine; this approach will be inefficient and limited. You might want to give Twig a shot, for instance.
do this:
function parser($view,$data)
{
$data=array("data"=>$data);
$template=file_get_contents(APP_DIR.DS.'view'.DS.$view.'.php');
$replace = array();
foreach ($data as $key => $value) {
#if $data is array...
$replace = array_merge(
$replace,array("{".$key."}"=>$value)
);
}
$template=strtr($template,$replace);
echo $template;
}
and ignore other two functions.
How does this work:
process.php:
<?php
$contents = file_get_contents('php://stdin');
$contents = preg_replace('/\{([a-zA-Z_][a-zA-Z_0-9]*)\}/', '<?php echo $\1; ?>', $contents);
echo $contents;
bash script:
process.php < my_file.php
Note that the above works by doing a one-off search and replace. You can easily modify the script if you want to do this on the fly.
Note also, that modifying PHP code from within PHP code is a bad idea. Self-modifying code can lead to hard-to-find bugs, and is often associated with malicious software. If you explain what you are trying to achieve - your purpose - you might get a better response.

PHP If Else Statement with PHP Include [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
how do you create an if else statement that contains an include statement?
In ASP you need to have the double quotes but I am not sure how to do it in PHP.
I believe the issue lies with this:
<?php include 'i_main-nav-wohl.php' ?>
I Tried the following:
<?php $url = $_SERVER["REQUEST_URI"];
if (strpos($url, "/occupational/wohl/") === 0) {
echo '<?php include ''i_main-nav-wohl.php'' ?>';
} else {
echo '<?php include ''i_main-nav-wohl.php'' ?>';
}
?>
<?php $url = $_SERVER["REQUEST_URI"];
if (strpos($url, "/occupational/wohl/") === 0) {
echo '<?php include "'i_main-nav-wohl.php'" ?>';
} else {
echo '<?php include "'i_main-nav-wohl.php'" ?>';
}
?>
<?php $url = $_SERVER["REQUEST_URI"];
if (strpos($url, "/occupational/wohl/") === 0) {
echo '<?php include 'i_main-nav-wohl.php' ?>';
} else {
echo '<?php include 'i_main-nav-wohl.php' ?>';
}
?>
Echoing in php means that it displays in the browser and does not implement itself. Just set the include directly in the if statement instead of echoing it.
You dont need a second php tag within your if-else-statement. Otherhwise your PHP output will result in a PHP document containing the content of your if or else branch.
Thus, if you want to produce conditional HTML or CSS use echo. Otherwhise just write your PHP commands without additional php tags.
You can do that like that :
<?php
$url = $_SERVER["REQUEST_URI"];
if (strpos($url, "/occupational/wohl/") === 0) {
include 'i_main-nav-wohl.php';
} else {
include 'i_main-nav-wohl.php';
}
?>
Or even better :
<?php
$url = $_SERVER["REQUEST_URI"];
$fileToInclude = strpos($url, "/occupational/wohl/") === 0 ? 'i_main-nav-wohl.php' : 'i_main-nav-wohl.php';
include($fileToInclude);
?>
BTW you are including the same file in both cases.
You shouldn't echo php tag in php code .
If you want your php code to be executed by your server,
Instead of this code :
echo '<?php include ''i_main-nav-wohl.php'' ?>';
just do this :
include 'i_main-nav-wohl.php';

PHP include() wiping rest of HTML document?

So I have a simple html page that looks like this.
<html>
<head>
<?php include("scripts/header.php"); ?>
<title>Directory</title>
</head>
<body>
<?php include("scripts/navbar.php"); ?>
<div id="phd">
<span id="ph">DIRECTORY</span>
<div id="dir">
<?php include("scripts/autodir.php"); ?>
</div>
</div>
<!--Footer Below-->
<?php include("scripts/footer.php"); ?>
<!--End Footer-->
</body>
</html>
Now, the problem is, when I load the page, it's all sorts of messed up. Viewing the page source code reveals that everything after <div id="dir"> is COMPLETELY GONE. The file ends there. There is no included script, no </div>'s, footer, or even </body>, </html>. But it's not spitting out any errors whatsoever. Just erasing the document from the include onward without any reason myself or my buddies can figure out. None of us have ever experienced this kind of strange behavior.
The script being called in question is a script that will fetch picture files from the server (that I've uploaded, not users) and spit out links to the appropriate page in the archive automatically upon page load because having to edit the Directory page every time I upload a new image is a real hassle.
The code in question is below:
<?php
//Define how many pages in each chapter.
//And define all the chapters like this.
//const CHAPTER_1 = 13; etc.
const CHAPTER_1 = 2; //2 for test purposes only.
//+-------------------------------------------------------+//
//| DON'T EDIT BELOW THIS LINE!!! |//
//+-------------------------------------------------------+//
//Defining this function for later. Thanks to an anon on php.net for this!
//This will allow me to get the constants with the $prefix prefix. In this
//case all the chapters will be defined with "CHAPTER_x" so using the prefix
//'CHAPTER' in the function will return all the chapter constants ONLY.
function returnConstants ($prefix) {
foreach (get_defined_constants() as $key=>$value) {
if (substr($key,0,strlen($prefix))==$prefix) {
$dump[$key] = $value;
}
}
if(empty($dump)) {
return "Error: No Constants found with prefix '" . $prefix . "'";
}
else {
return $dump;
}
}
//---------------------------------------------------------//
$archiveDir = "public_html/archive";
$files = array_diff(scandir($archiveDir), array("..", "."));
//This SHOULD populate the array in order, for example:
//$files[0]='20131125.png', $files[1]='20131126.png', etc.
//---------------------------------------------------------//
$pages = array();
foreach ($files as $file) {
//This parses through the files and takes only .png files to put in $pages.
$parts = pathinfo($file);
if ($parts['extension'] == "png") {
$pages[] = $file;
}
unset($parts);
}
//Now that we have our pages, let's assign the links to them.
$totalPages = count($pages);
$pageNums = array();
foreach ($pages as $page) {
//This will be used to populate the page numbers for the links.
//e.g. "<a href='archive.php?p=$pageNum'></a>"
for($i=1; $i<=$totalPages; $i++) {
$pageNums[] = $i;
}
//This SHOULD set the $pageNum array to be something like:
//$pageNum[0] = 1, $pageNum[1] = 2, etc.
}
$linkText = array();
$archiveLinks = array();
foreach ($pageNums as $pageNum) {
//This is going to cycle through each page number and
//check how to display them.
if ($totalPages < 10) {
$linkText[] = $pageNum;
}
elseif ($totalPages < 100) {
$linkText[] = "0" . $pageNum;
}
else {
$linkText[] = "00" . $pageNum;
}
}
//So, now we have the page numbers and the link text.
//Let's plug everything into a link array.
for ($i=0; $i<$totalPages; $i++) {
$archiveLinks[] = "<a href='archive.php?p=" . $pageNums[$i] . "'>" . $linkText[$i] . " " . "</a>";
//Should output: <a href= 'archive.php?p=1'>01 </a>
//as an example, of course.
}
//And now for the fun part. Let's take the links and display them.
//Making sure to automatically assign the pages to their respective chapters!
//I've tested the below using given values (instead of fetching stuff)
//and it worked fine. So I doubt this is causing it, but I kept it just in case.
$rawChapters = returnConstants('CHAPTER');
$chapters = array_values($rawChapters);
$totalChapters = count($chapters);
$chapterTitles = array();
for ($i=1; $i<=$totalChapters; $i++) {
$chapterTitles[] = "<h4>Chapter " . $i . ":</h4><p>";
echo $chapterTitles[($i-1)];
for ($j=1; $j<=$chapters[($i-1)]; $j++) {
echo array_shift($archiveLinks[($j-1)]);
}
echo "</p>"; //added to test if this was causing the deletion
}
?>
What is causing the remainder of the document to vanish like that? EDIT: Two silly syntax errors were causing this, and have been fixed in the above code! However, the links aren't being displayed at all? Please note that I am pretty new to php and I do not expect my code to be the most efficient (I just want the darn thing to work!).
Addendum: if you deem to rewrite the code (instead of simply fixing error(s)) to be the preferred course of action, please do explain what the code is doing, as I do not like using code I do not understand. Thanks!
Without having access to any of the rest of the code or data-structures I can see 2 syntax errors...
Line 45:
foreach ($pages = $page) {
Should be:
foreach ($pages as $page) {
Line 88:
echo array_shift($archiveLinks[($j-1)];
Is missing a bracket:
echo array_shift($archiveLinks[($j-1)]);
Important...
In order to ensure that you can find these kinds of errors yourself, you need to ensure that the error reporting is switched on to a level that means these get shown to you, or learn where your logs are and how to read them.
See the documentation on php.net here:
http://php.net/manual/en/function.error-reporting.php
IMO all development servers should have the highest level of error reporting switched on by default so that you never miss an error, warning or notice. It just makes your job a whole lot easier.
Documentation on setting up at runtime can be found here:
http://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors
There is an error in scripts/autodir.php this file. Everything up to that point works fine, so this is where the problem starts.
Also you mostlikely have errors hidden as Chen Asraf mentioned, so turn on the errors:
error_reporting(E_ALL);
ini_set('display_errors', '1');
Just put that at the top of the php file.

Basic Template Engine Fix

I am attempting to make a (very) basic template engine for php. Based on my research I have found that a method that I am using is strongly disliked. I was wondering if anyone knew a great alternative to get the same result so I am not using it. And if anyone sees any other improvements that can be made please share!
the method that is not advised is the eval() method!
Here is the php file
<?php
class Engine {
private $vars = array();
public function assign($key, $value) {
$this->vars[$key] = $value;
}
public function render($file_name) {
$path = $file_name . '.html';
if (file_exists($path)) {
$content = file_get_contents($path);
foreach ($this->vars as $key => $value) {
$content = preg_replace('/\{' . $key . '\}/', $value, $content);
}
eval(' ?>' . $content . '<?php ');
} else {
exit('<h4>Engine Error</h4>');
}
}
}
?>
here is the index.php file
<?php
include_once 'engine.php';
$engine = new Engine;
$engine->assign('username', 'Zach');
$engine->assign('age', 21);
$engine->render('test');
?>
and here is just a test html file to display its basic function
My name is {username} and I am {age} years old!
outputs:
My name is Zach and I am 21 years old!
Many thanks in advance!
If you just want to output some text to the page, just use echo:
echo $content;
This is better than eval('?>' . $content . '<?php') for quite a few reasons: for one, if someone types in <?php phpinfo(); ?>, for example, as their username, it won't execute that code.
I would, however, note that you have some other problems. What if I do this?
$engine = new Engine;
$engine->assign('username', '{age}');
$engine->assign('age', 21);
$engine->render('test');
The {age} in the username value will be replaced with 21. Usually you don't want replacements to be replaced like that, particularly as it's order-dependent (if you assigned username later, it wouldn't happen).

Can PHP include work for only a specified portion of a file?

I have a PHP include that inserts an html form into another html form. When the form gets included I now have two form headers. Is there a php tag I could use that would allow me to...
<form id="orderform">
<!-- <?php for the include FROM here?> -->
PROD:<input class="ProductName" type="text" size="75">|
Discount:<input class="Discount" type="text" size="3">|
QTY:<input class="qty" type="text" size="6">|
Line/Total:<input class="LineTotal" type="text" size="9" disabled>
<!-- <?php for the include TO here?> -->
</form>
So the include would go into that file with the form in it and get the specified HTML?
Is this possible?
EDIT
<?php
$dom = new DOMDocument();
$html = 'phptest3.php';
$dom->loadHTMLFile($html);
$div = $dom->getElementById("divtagid");
echo $div->nodeValue;
?>
This only returns the text. How do I get the HTML form elements in the divtagid?
You should best look into php functions for this.
<?php
function form_tag_wrapper($form) {
return '<form id="orderform">'. $form .'</form>';
}
function form_contents() {
return 'PROD:<input class="ProductName" type="text" size="75">
...
Line/Total:<input class="LineTotal" type="text" size="9" disabled>';
}
?>
You will use this as:
$form = form_contents();
print form_tag_wrapper($form);
Or, as a oneliner:
print form_tag_wrapper(form_contents());
No, there isn't an alternate way to include a portion of a file. Consider: how would you describe to such a function where to start and end inclusion? How would the function know what you want?
As suggested, the best approach would be to refactor the included file. If that isn't an option (I can't imagine why it wouldn't be), another route is to use variables or constants in the included file to denote which portions should be output. Something like this:
#File: form_template.php
<?php if (!isset($include_form_header) || $include_form_header == true) { ?>
<form id="orderform">
<?php } ?>
PROD:<input class="ProductName" type="text" size="75">|
Discount:<input class="Discount" type="text" size="3">|
QTY:<input class="qty" type="text" size="6">|
Line/Total:<input class="LineTotal" type="text" size="9" disabled>
<?php if (!isset($include_form_header) || $include_form_header == true) { ?>
</form>
<?php } ?>
Now, when you want to stop the form header from being output:
$include_form_header = false;
include('form_template.php');
This is nasty, IMO. When someone else (or the future you) edits form_template.php, it may not be apparent when or why $include_form_header would be set. This kind of reliance on variables declared in external files can lead to spaghetti code.
You're far better building separate templates for different purposes (or directly echoing trivial output, like one line of html to open or close a form), for instance:
<?php
#File: order_form_wrapper.php
echo '<form id="orderform">';
?>
<?php
#File: product_fields.php
echo 'PROD:<input class="ProductName" type="text" size="75">';
echo 'Discount:<input class="Discount" type="text" size="3">';
echo 'QTY:<input class="qty" type="text" size="6">|';
echo 'Line/Total:<input class="LineTotal" type="text" size="9" disabled>';
?>
// form with wrapper
include 'order_form_wrapper.php';
include 'product_fields.php';
echo '</form>';
// different form with wrapper
include 'some_other_form_wrapper.php';
include 'product_fields.php';
include 'some_other_fields.php';
echo '</form>';
Last option, if you have absolutely no access to the template, can't modify it, can only include it, then you could use output buffering to include the file, load the resulting HTML into DOMDocument, then peal off the wrapping form tags. Take a look at the code... this isn't exactly "neat" either:
function extract_form_contents($template)
// enable output buffer, include file, get buffer contents & turn off buffer
ob_start();
include $template;
$form = ob_get_clean();
ob_end_clean();
// create a new DOMDocument & load the form HTML
$doc = new DOMDocument();
$doc->loadHTML($form);
// since we are working with an HTML fragment here, remove <!DOCTYPE, likewise remove <html><body></body></html>
$doc->removeChild($doc->firstChild);
$doc->replaceChild($doc->firstChild->firstChild->firstChild, $doc->firstChild);
// make a container for the extracted elements
$div = $doc->createElement('div');
// grab the form
$form = $doc->getElementsByTagName('form');
if ($form->length < 1)
return '';
$form = $form->item(0);
// loop the elements, clone, place in div
$nb = $form->childNodes->length;
if ($nb == 0)
return '';
for($pos=0; $pos<$nb; $pos++) {
$node = $form->childNodes->item($pos);
$div->appendChild($node->cloneNode(true));
}
// swap form for div
$doc->replaceChild($div, $form);
return $doc->saveHTML();
}
$contents = extract_form_contents('my_form_template.php');
You can structure your include file like an XML file with processing instructions­XML (DOMProcessingInstruction­Docs). Such a file would only miss the XML root element, which could be added on the fly.
The benefit of this is, that it is compatible with both XHTML and PHP as long as you write PHP with the standard tags like <?php ... ?> because those are a valid XML processing instruction. Let's start with a simple, XHTML only example, the principle with PHP code is actually the same, but why make it complicated?
include.php:
<form id="orderform">
Text: <input name="element" />
</form>
To create an include function that can deal with this, it only needs to parse the XML file and return the fragment in question, e.g. everything inside the <form> tag. XML parsing ships with PHP, so everything is already ready to action.
function incXML($file, $id = NULL)
{
if (!($xml = file_get_contents($file)))
throw new Exception('File IO error.');
$xml = '<template>' . $xml . '</template>';
$doc = new DOMDocument();
if (!$doc->loadXML($xml))
throw new InvalidArgumentException('Invalid file.');
// #todo add HTML namespace if you want to support it
// fetch the contents of the file however you need to,
// e.g. with an xpath query, I leave this for a training
// and just do a plastic getElementById here which does NOT
// work w/o proper DTD support, it's just for illustration.
if (NULL === $id)
{
$part = $doc;
}
else
{
if (!$part = $doc->getElementById($id))
throw new InvalidArgumentException('Invalid ID.');
}
$buffer = '';
foreach($part->childNodes as $node)
{
$buffer .= $doc->saveXML($node);
}
return 'data:text/html;base64,' . base64_encode($buffer);
}
Usage:
<?php
include(incXML('include.php', 'orderform'))
?>
You don't need to change any of your template files as long as they contain XHTML/PHP in the end with such a method.

Categories