Best practice: where to put the PHP code? - php

I do admit this question is going to be a bit vague, but I will try to explain what I'm trying to accomplish by a few examples. I have some PHP code that loads a bunch of variables from the MySQL database, contains some declarations, some functions to quickly output HTML code etc. However I would love to do all that stuff before anything is sent to the client.
So I do:
<?php
include("somefile.inc");
function bla()
{
...
}
if (fails)
echo "Error: ...<br />";
?>
<!DOCTYPE>
<html>
<head>
<script>
...
<?php echo $someString; ?>
...
</script>
</head>
<body>
...
</body>
</html>
This is all fine and ok, until I get an error. The echo will not show in the browser because it's before all HTML... So I modified:
<!DOCTYPE>
<html>
<head>
<script>
...
<?php echo $someString; ?>
...
</script>
</head>
<body>
<div class="error_block">
<?php
include("somefile.inc");
function bla()
{
...
}
if (fails)
echo "Error: ...<br />";
?>
</div>
...
</body>
</html>
Now I can actually see errors, which is good. But now the problem arises that in the header, or scrips, I cannot access variables that will be loaded later on in the newly created error_block.
I really don't like splitting the code in the error_clock to some above the HTML document and some in the error_block. And I also don't want to use PHP's die() function which abrubtly ends the execution.
Anyone can give their 2 cents on this issue? Thanks.

If you're looking for an alternate solution, I have one for you. What I like doing is having the logic in before the DOCTYPE
if(error) { $error = "Please do something" }
Than, down in the document I have a div just for the error (Thanks #Dave for the input)
<?php echo $error != '' ? '<div id="error">' . $error . '</div>' : ''; ?>
This div will not appear if there isn't an error (meaning $error is empty) and it makes it easier for you to style the error message the way you would like
#error { color:red; }
If you want to get fancy, you can use some jQuery to hide/show the div so that the error doesn't have to persist.
$('#error').show().delay(7000).fadeOut();

You should look into using try-catch blocks and generating exceptions if you want to do some post-processing with the error message, which includes display.

What is often forgotten is that PHP is an INLINE programming language in essence, this means it is designed to be processed by the server as the server reads down the page, and with this it is designed to be split up into chunks. Recently OOP (Object Oriented Programming) has been introduced to PHP making it more flexible.
So with this information in hand I would take the OOP path in this case and do something like:
<!DOCTYPE>
<?php
include("somefile.inc");
function bla()
{
...
}
function failureError($code){
if(!empty($code)) ...
}
if ($a = $b) {
code goes here
} else {
$code = 'error123';
}
?>
<html>
<head>
<script>
...
<?php failed($code); ?>
...
</script>
</head>
<body>
...
</body>
</html>
By writing using functions you can cut down your development time and group the majority of your code just calling what you need when you need it.
Another way of declaring your error class(es)/functions to help with server response time is to do something like:
if ($a = $b) {
code goes here
} else {
include("errorStuff.php");
}
This will only include the error class(es)/functions when an error is encountered.
Just remember when you're writing PHP with OOP techniques like this that the server will take longer to process the script than if you write inline. The biggest advantage to an OOP basis is it will cut down your development time and if done correctly it will make it easier to administer future updates to your script.

Related

Is it correct to print long HTML via PHP?

I would like to know if it is correct to print long html through php classes with echo instead of just print it in a normal way, for example do the following:
Supose i have an user class
User.php
class User {
private $name, $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
public function printProfile($name, $age) {
echo '<div class="panel panel-profile">
Name: '.$this->name.'<br />
Age: '.$this->age.'<br />
</div>';
}
}
And my profile.php would look something like
profile.php
<html lang="en">
<head>
<?php
require_once __DIR__ . "/Head.php
$head = new Head();
$head->printPanel();
?>
</head>
<body>
<?php
require_once __DIR__ . "/Header.php
$header = new Header();
$header->printPanel();
?>
<div class="content">
<?php
require_once __DIR__ . "/User.php
$user = new User();
$user->printProfile();
?>
</div>
<?php
require_once __DIR__ . "/Footer.php
$footer = new Footer();
$footer->printPanel();
?>
</body>
</html>
So.. I know it's possible but i don't know if is it correct to do that, am i making a proper use of the code? will influence the processing speed?
I like this way because i can reduce the code in all the pages, and just by changing the class it modify all the code. I also know that i could make something like
<?php require_once __DIR__ . "/header.php ?>
And include all the code there without making a class
header.php
<header>
some stuffs
</header>
But i don't really like this because it is not object-oriented.
Sorry about my english as you may have noticed i'm not really good at it.
Turns out, object orientation isn't everything. If you can do just as much procedurally, do it. In your case, for a simple website, you can get away with storing all of your chunks in a separate file, say, Chunks.php. Use one function for each of the pieces you want to add. You don't need 20 different classes with constructors for each element on the page. Just use static methods.
As for code style, put all your requires at the top so your page doesn't crash half way through rendering:
<?php require_once __DIR__ . "/Chunks.php ?>
<html lang="en">
<head>
<?php Chunks::printHead(); ?>
</head>
<body>
<?php Chunks::printHeader(); ?>
<div class="content">
<?php Chunks::printUserProfile(); ?>
</div>
<?php Chunks::printFooter(); ?>
</body>
</html>
Simple, easy to read, and does exactly what you expect without 30 different 20-line files clogging up your view.
Using echo to output the html to the screen is more typical today.
PHP echo and print Statements echo and print are more or less the
same. They are both used to output data to the screen.
The differences are small: echo has no return value while print has a
return value of 1 so it can be used in expressions. echo can take
multiple parameters (although such usage is rare) while print can take
one argument. echo is marginally faster than print.
You can read more about that here
You should add the require imports to the top of the page. which is what most people do.
Thanks! Your answers have been very useful, i'll begin using more statics methods.
I've been doing some simples websites, with javascript, jquery, html and php but i'm about to start a larger project and i wanted to clarify some stuffs.
You said In your case, for a simple website, ... but what about a larger website? the same applies?

Can't use document.write more than one time in PHP

Here is my HTML and I call external PHP
<!DOCTYPE html>
<html>
<body>
<h1>My First Heading</h1>
<script src="index.php"></script>
<p>My first paragraph.</p>
</body>
</html>
and my PHP Script
<?
$strFileName = "poom.bis";
$objFopen = fopen($strFileName, 'r');
if ($objFopen) {
while (!feof($objFopen)) {
$file = fgets($objFopen, 4096);
// echo $file;
echo "document.writeln('$file'+);";
}
fclose($objFopen);
}
$test = "hello world";
echo "document.writeln(
'<ul>'+
'<li>.$test.</li>'+
'<li>test2</li>'+
'<li>test3</li>'+
'</ul>'
);";
?>
It error when using document.write more than one time
What should I do to solve this problem
Please Advice
PS. use echo "document.writeln('$file'+);"; for one time there is no error and show a result
First error: your line
echo "document.writeln('$file'+);";
should be
echo "document.writeln('$file');";
(without the plus sign). Also make sure that the file poom.bis doesn't contain a newline, not even at the end. If it does, you have to strip them away (trim()).
Second error was (until you edited it) the use of document.writeIn (which doesn't exist) instead of document.writeln (which does).
Tested and it works.
Also, while I'm at it, since you asked for advice how to solve this problem: look at your browser's error console and try to debug it.
echo '<script>document.writeln(';
echo '"<ul><li>test1</li><li>test2</li><li>test3</li></ul>"';
echo ');</script>';
;

Get php out of body

I've read and heard it is really sensible to separate your PHP and HTML tags as much as possible. Now my question is how should I do that? I couldn't really find the answer so I decided to ask you.
I was thinking about to use the POST function.
Check out my code:
<div class="aftelklok rondenSB">
<a href="?page=agenda">
<?php
// countdown function
// parameters: (year, month, day, hour, minute, seconds)
countdown(2013,2,24,18,0,0);
function countdown($year, $month, $day, $hour, $minute, $seconds)
{
// make a unix timestamp for the given date
$the_countdown_date = mktime($hour, $minute, $seconds, $month, $day, $year, -1);
// get current unix timestamp
$today = time();
$difference = $the_countdown_date - $today;
if ($difference < 0) $difference = 0;
$days_left = floor($difference/60/60/24);
$hours_left = floor(($difference - $days_left*60*60*24)/60/60);
$minutes_left = floor(($difference - $days_left*60*60*24 - $hours_left*60*60)/60);
$seconds_left = floor($difference - $days_left*60*60*24 - $hours_left*60*60 - $minutes_left*60);
if($difference > 0){ echo "Nog ".$days_left." dagen ".$hours_left." uur .$minutes_left." minuten tot de dienst"; }
else{ echo "De vorige dienst is afgelopen."; }
}
?>
</a>
</div>
So what i want is just the echo but then have all the php code not in my div but above the html code. like:
<?php ..... ?>
<html>
<body>
echo
</body>
</html>
As pemeon said, Smarty is quite a smart (pun intended) approach for that.
If you want to learn more about the backgrounds, you might want to google for "Model-View-Controller in php" or something like that. Basically, it's about separating your view (all the presentation stuff, e.g. HTML) from your code logic (controller) and your data objects / sources (model).
Smarty is nice but you'll need a bit of learning time to figure out how the template engine is designed, how to use it and how to apply it to your specific challenges.
If you don't want such a big solution at the moment and want to start a bit smaller and easier, you could write your own very simple template "engine" around the functions file_get_contents(...) and str_ireplace. The idea looks like this: You put your HTML stuff in template-files (for example *.html or *.tpl file ending) that don't contain any php code but place holders for dynamically created content:
Example: main-layout.tpl
<html>
<head><title>${Title}</title></head>
<body>
<img src="yourfancylogo.png" alt="Header logo"><br>
Here some navigation | ... | ... <br>
${Content}
<hr>
<div id="footer">© 2013 John Doe - Contact us</div>
</body>
</html>
Example: welcome.tpl
<h1>Hello, ${Username}! Nice to see you!</h1>
<p>So your username is ${Username}? Then you might want to read our terms of service before starting to use our app:</p>
<pre>${TOS}</pre>
Example: tos-document.txt
1) An apple a day keeps the doctor away!
2) No Smoking!
3) ...
In your php script you do something like this:
<?php
$template = file_get_contents('main-layout.tpl');
if (isset($_GET['requestedpage'])) {
// Parameter given!
$requestedPage = $_GET['requestedpage'];
} else {
// No page parameter. Assume "home".
$requestedPage = "home";
}
$username = "Monty"; // get from session data
if ($requestedPage == 'home') {
// -- begin handler code for page "home" --
$title = "Start Page - Welcome";
$content = file_get_contents('welcome.tpl');
$tos = file_get_contents('tos-document.txt');
$content = str_ireplace('${TOS}', $tos, $content);
// -- end handler code for page "home" --
} else if ($requestedPage == 'aboutus') {
...
} else {
$title = "Page Not Found - Error";
$content = file_get_contents('error404.tpl');
$content = str_ireplace('${PageThatWasNotFound}', htmlentities($requestedPage), $content);
}
$output = str_ireplace('${Content}', $content, $template);
$output = str_ireplace('${Title}', htmlentities($title), $output);
$output = str_ireplace('${Username}', htmlentities($username), $output);
die($output);
?>
Using such a separation of the template and the data to insert, you can later modify your layout / template without having to touch your php scripts. For example, if you want to modify your header or footer shown on all pages, you have a single point of change as you can modularly assemble your site from several template-bricks.
To keep the php source above readable, while your source is becoming larger, you can put all the handler codes into separated php files. You'd include them by include or require into your main source file.
But watch out: You have to escape all placeholder values that might come from user inputs - regardless, if you get them from a database or directly from $_GET or $_POST (-> XSS vulnerabilities). All input is evil!
You cannot use a php function or variable outside of a PHP block. However, it is possible to store a value in a php variable then use it in a tiny PHP block.
For example:
<?php
// ...
$foo = 42;
// ...
?>
Then
<html><body>
<p>Answer is <?php echo $foo; ?></p>
</body></html>
or
<html><body>
<p>Answer is <?= $foo; ?></p>
</body></html>
You could put your php in a separate file, and then use include or require.
do_stuff.php:
<?php
// some calculations
echo "stuff";
?>
Then in your html...
index.php:
<html>
<body>
<?php include 'do_stuff.php'; ?>
</body>
</html>
About include
The best way is to use some template engine like smarty or twig. If you do not have time to learn you can for now just write code at the top and when you want to use some calculations in i.e you use .
<?php
// calculations
$foo = 'foo';
?>
<html>
<body>
<div><?=$foo?></div>
</body>
</html>
And when you start to use this kind of 'separation' (php code in the top of the file) and html at the bottom and you will use this shortcut version of the echo function, you will easily transform into using template system.
The goal should not be keeping php away from html code, the goal should be keeping business logic from presentation logic. One of the ways to do this is utilising a Model-View-Controller layout, or you could use one of many other paradigms. The main point of this approach is making changing one part independent of the other: imagine creating a separate mobile or json front end, that does all the exact same logic, but outputs it completely differently. If the business logic and presentation logic are completely entangled, you will have a hard time, probably needing to both reproduce or blatantly copy code, as well as creating two different branches that need to be kept in-sync, making maintaining it a nightmare.
I`m using right now this sort of frame, its sort of like the frame MrSnurb made, but then in HTML in stead of php. what do you think about this framework guys?
<?php
if(isset($_GET['page'])) {
$page = $_GET['page'];
}else{
$page = "home";
}
?>
<!DOCTYPE html>
<html>
<head>
<title> Younited - <?php echo $page; ?></title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="js/slides.min.jquery.js"></script>
</head>
<body>
<div class="container ronden">
<?php
include "partials/header.php";
include "partials/menu.php";
?>
<div class="content">
<?php
if (file_exists("partials/pages/".$page.".php")) {
include "partials/pages/".$page.".php";
}
else{ echo "<p>De pagina <b>".$page."</b> bestaat niet.</p>";
}
include "partials/sidebar.php";
?>
</div>
</div>
<?php
include "partials/footer.php";
?>
</body>
</html>
Use some template engine like smarty. To create template of your html code and push there varibles.

php jquery append

does anyone know a way to get php working with jquery append()?
say we have
$('.class0').click(function(){
$('.class1').append('<?=PHPCODE?>');
});
How do we get the php to work after append?
Thanks!
Jquery is javascript and it is executed on the browser while php is a server-side script so in theory a PHP script always run first before any javascript. If you wish to run any php script after the page has finished loading (e.g. when a user click on a button), you need to do an AJAX call. ($.get(), $.load(), etc are examples using jquery)
In more details to your editted question:
With your code, the php script you write inside append will be rendered as plain text. Instead, do the ajax call before the append, and store the result of the ajax call in a variable. Then use: append(variable).
You might also be interested to do some DOM manipulation, which is more efficient if you're loading a huge text from your php script. You can return a JSON object from the php script then use a combinations of appends to create the desired result. This reduces the amount of data that needs to be transfered, but the javascript code could be lengthy.
Try this:
Document HTML(index.php)
<?php
include( 'config.php' ); // Example
$foo = "<span style='color:red;'>WTF</span>" //OR <span style="color:red;">WTF</span>
?>
<html>
<head>
<script type="text/javascript">
$.ready(function()
{
$('.element').click(function()
{
$(this).append('<?php echo str_replace("'","\'",$foo);?>');
return false;
});
});
</script>
</head>
<body>
Element
</body>
</html>
Use <?php echo $foo; ?>, <?=$foo;?> not is recomendated.
Escape especial characters, example : ' (simple quot).
Use Smarty Template PHP Framework
Smarty Template PHP Framework
vista.php( MVC OOP )
<?php
class myClass
{
public function myMethodName()
{
$var = '<span>text</span>';
$this->template->assign( 'foo' , $var );
$this->template->display('myTemplate.html');
}
}
?>
vista.php( NO OOP )
<?php
$var = '<span>text</span>';
$smarty = new Smarty;
$smarty->assign( 'foo' , $var );
$smarty->display( 'myTemplate.html' );
?>
myTemplate.html
<html>
<head>
<title>{$title}</title>
</head>
<body>
{if $text}
{$text}
<ul>
{foreach from=$list item=li}
<li>{$li}</li>
{/foreach}
</ul>
{/if}
</body>
</html>
See and read Smarty Documentation

How do I keep multiple similar 'view/layout' files DRY without using using 'if()' statements everywhere in CakePHP?

I'm developing a application with CakePHP, and I have two layouts: one for the home page, and another for the rest of the application. Except for some coding on the header, they're almost exactly the same. Is there something I can do to keep DRY, without using if () statements all over the layout?
I'd suggest using a ton of elements. This way, you can still keep all of the code in one place. For example, if this is your home page layout (boilerplate excluded):
<body>
<?php echo $this->renderElement('pageHeader'); ?>
<?php echo $this->renderElement('frontPageNotification'); ?>
<?php echo $this->renderElement('navAndOtherStuff'); ?>
...
</body>
And this is your interior layout (where you want to display everything except for the frontPageNotification stuff:
<body>
<?php echo $this->renderElement('pageHeader'); ?>
<?php echo $this->renderElement('navAndOtherStuff'); ?>
...
</body>
Now, if they're almost exactly alike, I would probably just use a single layout and have a few if statements within the layout itself to determine what's to be displayed. Also, you can choose which elements get displayed by looking at the $this->params array to figure out which controller and action is behind the page being loaded. Like:
<body>
<?php echo $this->renderElement('pageHeader'); ?>
<?php if($this->params['controller'] == 'pages' && $this->params['action'] == 'index') { echo $this->renderElement('frontPageNotification'); } ?>
<?php echo $this->renderElement('navAndOtherStuff'); ?>
...
</body>
Which is, admittedly, rather ugly. Just trying to present all the options I could think of :)
Good luck
Define an interface to a layout type. Every place you have an "if layout main" or "if layout other" define an interface function
interface IMyLayout
{
function DrawArea1(...)
...
}
class CMyMainLayout implements IMyLayout
{
function DrawArea1()
{
//... draw area 1 for main
}
...
}
class CMyOtherLayout implements IMyLayout
{
function DrawArea1()
{
//... draw area 1 for other
}
}
Then you just select one or the other by newing the correct object
if ($main)
{
$layout = new CMyMainLayout;
}
else
{
$layout = new CMyOtherLayout;
}
$layout->DrawArea1();

Categories