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);
Related
i would to know what is good practice for writing code to put all HTML code inside PHP function and in my front index.php file just call function to show code.
class.php:
public function test() {
$sql='select id,title from test ';
$nem=$this->db->prepare($sql);
$nem->execute();
$nem->bind_result($id,$title);
echo '<ul class="centreList">';
while($nem->fetch())
{
echo '<li>'.$id.'<a href="'.$title.'" >Download</a></li>';
}
echo '</ul>';
}
index.php:
<?php $connection->test(); ?>
This work fine, but I would like to know is this proper way or is not a good practice to use html code inside PHP functions?
It's ok to build HTML within PHP, but I would not echo to the screen directly from within the function. Instead, return the built HTML string.
$html = '<ul class="centreList">';
while($nem->fetch())
{
$html .= '<li>'.$id.'<a href="'.$title.'" >Download</a></li>';
}
$html .='</ul>';
return $html
The function should not be responsible for pushing content to the browser because it really limits what you can do with your code. What if you wanted to further process the HTML? What if you run into a condition later in the code and decided to abort? What if you wanted to set some response headers later? Some content would already be gone so none of these things would be possible without clever workarounds.
In general you want to separate your responsibilities: I would even break things down further:
one piece of code is in charge of retrieving info from the DB and returning
Another piece is in charge of building the HTML string
A third piece is in charge of displaying the HTML (probably your index.php)
New index.php
<?= $connection->test(); ?>
Do not use echo to print the html directly, wrap the html within while loop surrounded by php tags
public function test() {
$sql='select id,title from test ';
$nem=$this->db->prepare($sql);
$nem->execute();
$nem->bind_result($id,$title);
return $nem;
}
<ul class="centreList">
<?php $res = test()->fetch();
while( $res->fetch() ) { ?>
<li> <?php echo $id ?> Download </li>;
<?php } ?>
</ul>
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);
My website consists of many products that are each contained in a div with the id content block. The link, image, background, description and price are all loaded from a mySQL table. My original plan was to save the below html code as a string and loop over the rows in the mySQL table filling the string I created with php/mySQL values.
I was wondering if I am going about this the right way, or is there a better way to create html code from php variables?
<div id="contentblock" style="background-image:url(images/$BACKGROUND.png);">
<div id="picture"><img src="$IMAGELINK"/></div>
<div id="description"><p>$DESCRIPTION</p></div>
<div id="price"><p class=price>$PRICE</p></div>
</div>
Firstly PHP is a template engine - in my experience template engines that layer ontop of PHP are only good for the simplest of cases and are easily outgrown.
Secondly the original code is as good as any method. At risk of stating the obvious to make it better abstract it into a function;
function output_block($BACKGROUND, $LINK, $IMAGELINK, $DESCRIPTION, $PRICE)
{
echo "<div id='contentblock' style='background-image:url(images/$BACKGROUND.png);'>
<div id='picture'><a href='$LINK'><img src='$IMAGELINK'/></a></div>
<div id='description'><p>$DESCRIPTION</p></div>
<div id='price'><p class=price>$PRICE</p></div>
</div>";
}
If you want to make it much better then adopt a framework, an entire admin config page is show below. All of the HTML glue is provided by the framework - the following code is real, but really to illustrate how a framework can provide a lot of the grunge work for you.
In the example below if I want to edit a single entity I'd change the TableViewEdit into a FormView and provide an instance of an entity rather than an iterable list.
$entity = new CbfConfig(); // Database entity
$page = new AdminWebPage("Site Configuration"); // Page for output
/*
* build the view
*/
$vil = new ViewItemList();
$col = &$vil->add(new ViewItem("description","Description"));
$col->get_output_transform()->allow_edit(false); // this field cannot be editted
$col = &$vil->add(new ViewItem("value","Value"));
$v1 = new TableViewEdit($entity, $vil,"admin_values"); // present as standard editable table
/*
* output the page
*/
$page->begin();
$iterable_list = CbfConfig::site_begin();
$page->add_body($v1->get_output($iterable_list,'admin_config'));
$page->end();
Id just have all my html code outside of php tags, then whereever I need a variable from php do as follows
<div id="description"><p><?php echo $DESCRIPTION; ?></p></div>
You can loop around non php code too. For example
<?php
for($i = 0; $i < 10; $i++) {
?>
<div id="description"><p><?php echo $i; ?></p></div>
<?php
} //end for loop
?>
Obviously this is just an example.
well if im without a template engine for somereason i usually do something like:
function partial($file, $args = array()) {
extract($args);
ob_start();
include($file);
return ob_get_clean();
}
Really, there are 3 ways of doing this. Use whichever is easiest for you in the context that you are using it in.
<?php
while(($row=mysql_fetch_assoc($result))!==false)
{
echo "<div>{$row['fieldName']}</div>";
}
?>
<?php
while(($row=mysql_fetch_assoc($result))!==false)
{
echo '<div>'.$row['fieldName'].'</div>';
}
?>
<?php
while(($row=mysql_fetch_assoc($result))!==false)
{
?>
<div><?= $row['fieldName']; ?></div>
<?php
}
?>
I'm new to zend and i'm struggling with some items.
I tried using Helpers, but then realized it doesn't do what I wanted it to do...
either i'm using $this->placeHolder... wrong or it doesn't do what I want it to do
I want to do the following:
I want to create a custom class that basically has 2 methods addScriptContent, and getScriptContent...
addScriptContent adds what ever is passed into it to a string that is global for the page.
getScriptContent will just output whatever data that has been added using addScriptContent
i.e.
this->addScriptContent('var x="foo";')
....some html
this->addScriptContent('var y="feee";')
....some html
echo this->getScriptContent() //writes out var x="foo"; var y="fee";
The placeholder helper does exactly what you are after:
<?php $this->placeholder('scriptContent')->set('var x="foo";') ?>
....some html
<?php $this->placeholder('scriptContent')->append('var y="feee";') ?>
....some html
<?php echo $this->placeholder('scriptContent')?>
the key methods on the helper are set, append and prepend; which overwrite, add to, and add to the start of the content respectively.
If you really want to write your own helper for this, this wouldn't be too difficult. Take a look at the headTitle or headScript helpers for an example, but would be something along the lines of:
class My_View_Helper_ScriptContent extends Zend_View_Helper_Placeholder_Container_Standalone
{
public function scriptContent($script)
{
$this->append($script);
}
}
usage would then be:
<?php $this->scriptContent('var x="foo";') ?
....some html
<?php $this->scriptContent('var y="feeee";') ?>
....some html
<?php echo $this->scriptContent() ?>
I have some HTML code portions that repeat a lot through pages. I put this html code inside a function so that it is easy to maintain. It works perfectly. I, however feel this may not be very good practice.
function drawTable($item){
?>
HTML CODE HERE
<?php
}
I also run into the problem that when I want to return data using json the following won't work as it will be NULL:
$response['table'] = drawTable($item);
return json_encode($response);
What's the correct way to handle HTML code that repeats a lot??
Thanks
You may want to look into using templates instead of using ugly heredoc's or HTML-embedded-within-PHP-functions, which are just plain unmaintainable and are not IDE-friendly.
What is the best way to include a php file as a template?
If you have a repeating segment, simply load the template multiple times using a loop.
Although templates help with D.R.Y., the primary focus is to separate presentation from logic. Embedding HTML in PHP functions doesn't do that. Not to mention you don't have to escape any sort of quotes or break the indentation/formatting.
Example syntax when using templates:
$data = array('title' => 'My Page', 'text' => 'My Paragraph');
$Template = new Template();
$Template->render('/path/to/file.php', $data);
Your template page could be something like this:
<h1><?php echo $title; ?></h1>
<p><?php echo $text; ?></p>
function drawTable( $item ) { return '<p>something</p>'; }
function yourOtherFunction() {
$response['table'] = drawTable($item);
return json_encode($response);
}
Use this function definition
function drawTable($item){
return 'HTML CODE HERE';
}
Called with
print drawTable($item);
Which will also work for your json return value.