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?
Related
I'am really very new to PHP.
I have this code:
<?php cms_loop('500');?>
<div class="item">
<p class="contents"></p>
</div>
<?php cms_loop_end('500');?>
I want to output everything between cms_loop and cms_loop_end functions.
I do it this way:
function cms_loop($id){
ob_start();
echo ob_get_contents();
}
and
function cms_loop_end(){
ob_end_flush();
}
But that's not working. Any help appreciated
Below you can find the working code:
<?php
/**
* Start buffering
* #param $id
*/
function cms_loop($id){
ob_start();
}
/**
* Output everything buffered
*/
function cms_loop_end(){
ob_end_flush();
}
?>
<?php cms_loop('500');?>
<div class="item">
<p class="contents">Hello from buffered content</p>
</div>
<?php cms_loop_end('500');?>
Please note that I removed the echo ob_get_contents(); from your cms_loop() function.
Demo: https://onecompiler.com/php/3wuscawt7
(There is an option to run without account)
I'm assuming you're trying to achieve some kind of template rendering as you apparently trying to render some piece of HTML for later use. For that to happen, PHP needs to be aware of that piece. In your example, though, both PHP and HTML co-exist side by side without either side having any knowledge about the other. Your HTML isn't part of PHP's realm yet.
Let's change that.
The piece of HTML you've given is often called a partial, i.e. something that's meant to be part of something bigger. Like a sidebar being a conceptual part of an index.html file, but not a physical one unless included:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Welcome!</h1>
<!-- Partial -->
<?php include_once('sidebar.html') ?>
</body>
</html>
So let's take a similar approach and factor out the HTML into its own file first:
<div class="item">
<p class="contents"></p>
</div>
partial.html.php
Now we need to find a way to transfer this piece of HTML into the realm of PHP. The simplest approach would be to read it and assign it to a variable:
$html = file_get_contents('partial.html.php');
Let's get back to your function for a second, because now you could do:
function cms_loop($html){
echo $html;
}
I have taken $id off of the list of the function's parameters, mostly because of the following reasons:
you don't read nor write to a database yet
if you did, this would be the wrong place
you don't use any variables in your template, so there's no need to pass any in
Though let's ponder the last one a bit. Wouldn't it be nice if we could pass data into our template, for example to dynamically change the classes we have assigned to both HTML elements?
It would most definitely be nice, and it's possible, too - what we need for that is just a little bit of output buffering. But first, let's change our template to meet our new needs:
<div class="<?php echo $class_outer ?>">
<p class="<?php echo $class_inner ?>"></p>
</div>
So we'll have to define both values up front. But we might end up with a lot more template variables once we get the hang of it, so let's best use an array as a container to store our current and any future values:
$data = [
'class_outer' => 'item',
'class_inner' => 'contents',
];
Next, we'll need some function to render our template with the values we just defined, so it'll need two parameters: The path to the template file and our data array. Also, we want it to return our rendered template. That said, it'll probably look like this:
function render(string $template_path, array $data): string {
if (!is_file($template_path)) {
return false; // Or some better error handling
}
// Let's have some sugar in our templates: Import all indexes
// of our data array as variables into the current scope so
// they can easily be accessed by the template we're about to render.
//
// In other words, we now have two new variables:
//
// - $class_outer (extracted from $data['class_outer'])
// - $class_inner (extracted from $data['class_inner'])
//
// Cf. https://www.php.net/manual/en/function.extract.php
extract($data);
// Start output buffering
ob_start();
// Render template
include $template_path; // By including it, it has access to all
// variables defined in the current scope, i.e.
// inside this very function - like the variables
// we just extracted from $data
$rendered = ob_get_contents(); // Assign all output to a variable, so we can return it.
// End output buffering
ob_end_clean();
return $rendered;
}
Now, we can call that like:
$rendered = render('templates/partial.html.php', $data);
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.
I am not sure if I just have a bad structure for my code or this is a problem not normally found, but I don't even know how to start looking for a solution for my problem. I have my own simple translation script which is called like this:
<?php echo $Translate->text("Name"); ?>
It would return (and echo) a string with a keyword 'Name'. The problem is, for several reasons (name: misstranslations, report, development, translation in situ), I might want to retrieve all strings' keywords that are on a page. A simple page (example.com/campus/index.php) looks like this:
<h1> <?php echo $Translate->text(Campus); ?> </h1>
<p style="text-align:justify;">
<?php echo $Translate->text(126); ?>
</p>
<p style="text-align:justify;">
<?php echo $Translate->text(129); ?>
</p>
<a href="<?php $Link->create("campus/about"); ?>">
<h2 class="bodymenu"><?php echo $Translate->text(About); ?> </h2>
</a>
<p style="text-align:justify;">
<?php echo $Translate->text(146); ?>
</p>
<a href="<?php $Link->create("campus/learning_center"); ?>">
<h2 class="bodymenu"><?php echo $Translate->text(Learning_center); ?> </h2>
</a>
<p style="text-align:justify;">
<?php echo $Translate->text(147); ?>
</p>
<a href="<?php $Link->create("campus/residence"); ?>">
<h2 class="bodymenu"><?php echo $Translate->text(Residence); ?> </h2>
</a>
<p style="text-align:justify;">
<?php echo $Translate->text(128); ?>
</p>
And I would like to obtain in some situations: $Translations=array("Campus","126","129","About","146","Learning_center","147","Residence","128"); for further processing (EDIT) from another page.
In some cases there's much more php logic mixed in the page, in some others it's like this. There's much more logic code and classes that it's included automatically before and after every page. So, basically, I'd like to know (for this example but being able to extend it) how could I retrieve all the keywords.
I am thinking about 2 methods basically, but I don't think either is optimal. First would be to parse the php code as is using regex. Since I know the bits that I'm looking for, I thing it would be possible. Second one is that, depending on a SESSION variable, I render the html and parse it, so the echo $Translate->text(Campus); would return something like <span id="Translation">Campus</span> and then parse only the html and retrieve all the ids. Can you think about any other way to retrieve the ids before I get on this?.
PS, I DON'T want to hardcode all the id's in an array at the beginning or end of a page.
Do not reinvent the wheel by implementing a translating system. The gettext extension is there for painless, on the fly, language switching.
Basicly you write your site in a default language:
<?php echo _("Name"); ?>
Do not write <?php echo $Translate->text(147); ?>, noboby knows what that is. Write:
<?php echo _("Learning Centre"); ?>
For managing translations there is a choice of editors for Windows, Linux and Mac, POEdit for example.
Switching to a different language is easy:
public function SetDomain( $path )
{
define( 'DOMAIN', 'messages' );
bindtextdomain( DOMAIN, $path );
bind_textdomain_codeset( DOMAIN, "UTF-8" );
textdomain( DOMAIN );
}
note: if you set short_open_tags to on you can write:
<?= _("Name"); ?>
if i understood it correct,
modify your Translate class a little: add a variable which will collect all the strings you are using, like:
public $aStrings = array();
then, add in your function text($arg) something like:
$this->aStrings[] = $arg;
then you will have all the strings on page in your Translate->aStrings variable, then to print it use somethin like:
print_r($Translate->aStrings);
Subclass the Translate class with one that collects the values in an array, then use that in your page:
class MyTranslate extends Translate {
public $texts = array();
public function text($which) {
$this->texts[] = $which;
return parent::text($which);
}
}
$Translate=new MyTranslate($User->Language);
ob_start();
require('/path/to/other/page');
ob_end_clean();
var_dump($Translate->texts);
Create 2 file in english folder. ( You can specify it later but usually location for languages file in languages directory )
campus.about.php:
<?php
$lang["Name"] = "Name";
$lang["Address"] = "Address";
?>
*campus.learning_center.php*:
<?php
$lang["Learning"] = "Learning";
$lang["Residence"] = "Residence";
?>
Your Class Translate File ( root directory ):
class Translate {
public $_text= array(); // Change it into private properties coz you create
// text method for get the value, I set it public just for easy to debug it.
private $_language;
function __construct($language){ // Set Language
$this->_language= $language;
}
public function create($page){ // Get Language File
// $page= campus/about change into this campus.about
// Get language file Ex: english/campus.about.php
require($this->_language.'/'.$page.'.php');
$this->_text= array_merge($this->_text, $lang);
}
public function text($text){ // Display Keywords
echo $this->_text[$text];
}
}
$Translate= new Translate('english');
$Translate->create('campus.about');
print_r($Translate->_text);
$Translate->create('campus.learning_center');
print_r($Translate->_text);
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.
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();