I have a strange situation that I've never encountered where the returned HTML from my class methods doesn't output in the correct structure. For some unknown reason, everything is nested inside the HTML within the first loop, second loop, etc.
index.php
<body>
some html...
<div class="usb-port-container">
<?= $generate->output('short_name',id,'hostname'); ?>
</div>
some html...
<div class="usb-port-container">
<?= $generate->output('short_name',id,'hostname'); ?>
</div>
some html...
</body>
class.generate.php
function __construct() {
$this->getCopy = new getCopyData();
$this->getDrive = new getDriveData();
$this->helper = new helper();
}
function output ($short_name,$id,$hostname) {
$portCount = $this->getCopy->portCount($hostname, 'total');
for ($port = 0; $port < $portCount; ++$port) {
if ($this->getCopy->probePort($hostname,$port)) {
$default = $this->usbPortDefault($short_name,$id,$hostname,$port);
return $default;
} else {
$details = $this->usbPortDetails($short_name,$id,$hostname,$port);
return $details;
}
}
}
function usbPortDefault($short_name,$id,$hostname,$port) {
$port_details = '<div>
<div>----</div>
<div>----</div>
</div>';
return $port_details;
}
function outputRecords($hostname,$port) {
//get records data from database
$records = $this->getCopy->records($hostname,$port);
//create empty variable for HTML
$records_html = "";
foreach ($records as $key => $value) {
if ($value) {
$records_html .= '<div><span class="copy-group">' .$key. '</span><span class="copy-instance">' .$value. '</span></div>';
} else {
return '<div>Unable to get any group or instance</div>';
}
}
return $records_html;
}
function usbPortDetails($short_name,$id,$hostname,$port) {
$port_info = '';
$port_info .= 'bunch of HTML';
$port_info .= $this->outputRecords($hostname,$port);
$port_info .= 'bunch of HTML';
return $port_info;
}
My best guess as to the problem, is that there is an issue with the way I am returning the HTML or something with output buffering. I actually don't know if I need it within my class, but I've taken it out and issue is the same. I've also tried adding output buffering to index.html.
Here is a snippet of the source HTML. The first discrepancy I notice is that the <div class="server-details"></div> highlighted in blue doesn't belong there, it should be inside <div class="dc-container"></div> and adjacent to the prior <div class="server-details"></div>. After port-data-left should be port-data-right but it's nowhere to be found. I'm almost convinced at this point that there's a missing closing tag somewhere but I can't find it. It's been several years since I seriously did any development :D
EDIT: After further investigation, it appears that the final $port_info is not outputting and may be causing this problem. Is there an issue with $port_info .= $this->outputRecords($hostname,$port); being there?
Since you reuse you object instance using $generate, the constructor and destructor methods are only called once in this script.
The constructor starts a new output buffer using ob_start(), which means everything outputted by the output method will be buffered until you flush it.
The issue is, the flush only happens in the destructor, with ob_end_flush(), which is only executed once, after the last output call.
Because you echo the result of the method and start a buffer at the same time, the output must indeed be weird and some nesting / repetition occurs because the next output still adds to the buffer.
As pointed out in the comment, the easiest solution is to turn off the output buffering in the class.
You also need to clear $port_info at the beginning of the method to make this work, although it should be fine, unless $port_info is a global var?
This was probably not cleared in the initial Class in order to make it work when called several times, to concatenate the results (and buffer them, before outputting them all at once)
A good usage of buffers in the middle of a page is to redirect the output of a function to a variable.
For example, you could have a function that echoes code but you don't want it echoed.
You could then do something like:
Some HTML
<?php
ob_start();
call_to_some_function_that_normally_outputs_code();
$myvar = ob_get_clean();
?>
Rest of the HTML
Related
Main purpose is to get all categories listing from database by passing variables to url and show it to the main page.here i have omitted some code bt i tried to clarify.
1.can I exclude encodeHtml() method, too difficult for me to understand
2.i am not getting specially this part of code and having my head for 4 days
foreach($cats as $cat) {
echo "<li><a href=\"/?page=catalogue&category=".$cat['id']."\"";//here id is 'category id' from database. this full line will echo what?
echo Helper::getActive(array('category' => $cat['id']));//it will output what ?
echo ">";
echo Helper::encodeHtml($cat['name']);//as from ur answer can we omit encodeHTML() method and use htmlspecialchars($cat['name']); instead ?
echo "</a>
3.any easier solution will be more appreciated
in our database we have 'id' and 'name' of catagory listing
please check below for reference
/*below is the code in header section of template */
<?php
$objCatalogue = new Catalogue();// creating object of Catalogue class
$cats = $objCatalogue->getCategories(); // this gets all categories from database
<h2>Categories</h2>
<?php
foreach($cats as $cat) {
echo "<li><a href=\"/?page=catalogue&category=".$cat['id']."\"";
echo Helper::getActive(array('category' => $cat['id']));
echo ">";
echo Helper::encodeHtml($cat['name']);
echo "</a></li>";
}
?>
/*below is the helper class which is Helper.php */
public static function getActive($page = null) {
if(!empty($page)) {
if(is_array($page)) {
$error = array();
foreach($page as $key => $value) {
if(Url::getParam($key) != $value) //getParam takes name of the parameter and returns us the value by $_GET
{
array_push($error, $key);
}
}
return empty($error) ? " class=\"act\"" : null;
}
}
//CHECK THIS LINE BROTHER
return $page == Url::currentPage() ? " class=\"act\"" : null;// url::currentPage returns the current page but what is 'class =act ' :(
}
public static function encodeHTML($string, $case = 2) {
switch($case) {
case 1:
return htmlentities($string, ENT_NOQUOTES, 'UTF-8', false);
break;
case 2:
$pattern = '<([a-zA-Z0-9\.\, "\'_\/\-\+~=;:\(\)?&#%![\]#]+)>';
// put text only, devided with html tags into array
$textMatches = preg_split('/' . $pattern . '/', $string);
// array for sanitised output
$textSanitised = array();
foreach($textMatches as $key => $value) {
$textSanitised[$key] = htmlentities(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, 'UTF-8');
}
foreach($textMatches as $key => $value) {
$string = str_replace($value, $textSanitised[$key], $string);
}
return $string;
break;
}
}
Firstly, in your URL (/?page=catalogue&category=) you don't need to put &, as this is an HTML entity for actually displaying an ampersand in a web page. Just use /?page=catalogue&category=.
Secondly, you can use urlencode() to prepare strings for sending in the URL, and urldecode() on the other end.
In answer to your first point you just need to make sure that ANYTHING from the user (whether via $_POST or $_GET) is sanitized, prior to being used in code, output to a web page, or used in database queries. Use htmlspecialchars() for cleaning before outputting to a web page, and prepared statements prior to entering user input into a query.
In answer to your second point please read the documentation in the links I have provided above. Just reading the documentation on htmlspecialchars() will help you a lot.
Hope this helps.
Alright then.
<?php
foreach($cats as $cat) {
echo "<li><a href=\"/?page=catalogue&category=".$cat['id']."\"";
echo Helper::getActive(array('category' => $cat['id']));
echo ">";
echo Helper::encodeHtml($cat['name']);
echo "</a></li>";
}
?>
Im just going to kindof skim through it, because honestly if you really want to learn all this you should probably google the shit out of every piece of code you don't understand, it's the way we all learn things.
< ?php announces some php script to follow. And as you can see, there does follow some php code after.
foreach is a way of getting each element from an array or list and doing something to that element.
echo sends whatever string comes after it to the page, or whatever is listening to its output. In this case, it looks like the echo's are printing some <li> list item with an <a> anchor in it.
Helper::getActive(): Helper is some class that is defined somewhere, :: is syntax for calling a static function that belongs to the class (Helper in this case). getActive is the function name.
array('category' => $cat['id'] is a piece of code that creates an array with 1 element in it, being one with key 'category' and a value of whatever is in $cat['id'].
By looking at getActive: it looks like it's a function that checks the url for some value so it can determine which page to display. It also checks if the url contains errors.
By lookingat encodeHtml(): it looks like it's a function that makes sure that whatever text you're trying to put on the screen, isn't something that could cause harm. In some situations, people will try to make your server print javascript that could harm the user (by sending personal data to somewhere). The encodeHtml() will ensure that no such thing can be done by stripping certain characters from the text you're about to send to the page.
USE GOOGLE.
I am wondering if there is any real benefit to using this...
function getSomeContent() {
ob_start(function($content) {
// ... modify content ...
return $content;
}
// ... output stuff ...
return ob_get_clean();
}
...as opposed to this...
function getSomeContent() {
ob_start();
// ... output stuff ...
$result = ob_get_clean();
// ... modify content ...
return $result;
}
...?
Assume the "output stuff" and "modify content" parts are the same in each case. The key point is that the "modify content" has changed its location, being in a callback in the first case, and being "inline" in the second case.
Is there a performance benefit of one over the other? For example, does the second form make two copies of the buffer contents when the first uses only one? Or is it purely a coding style decision? Why would you choose one form over the other?
I can see there are differences in scope access, because any variables in the enclosing scope will be available in the "modify content" part of the second example, where they would have to be "passed in" with a use clause in the first example. In fact this is exactly why I would normally choose the second form.
Now your code is clear yes, in your first samples you given a case where you used $result twice (that wasn't a good idea).
My main idea is : you call ob_start with a callback only if you do not need to use your $result in your current scope. Your first example becomes :
ob_start(function($content) {
// ... modify content ...
return $content;
}
// ... output stuff ...
ob_end_clean();
In this case, the job with $result is made in a new scope and this can make your code cleaner (example: you call ob_start(array($this, 'method'));), and you don't need to unset your $result to free it from your main scope at the end of your job (I assume you're doing something else of course).
Just to clarify Ninsuo's correct answer a bit.
My two code samples actually do not produce the same result. In fact, using the callback in combination with ob_get_clean() is completely useless.
This is because the callback is applied when cleaning or flushing the buffer.
However ob_get_clean() retrieves the contents first, and then cleans the buffer. Which means that the contents returned are not the result returned by the callback, but the input passed to the callback.
I wrote these two simple (and hacky) scripts to demonstrate.
This one uses ob_get_clean() and does not produce the correct result:
// Tests the use of callbacks with ob_get_clean().
class TestWithGetClean {
// This variable is set when obcallback is called.
public $foo = null;
// The output buffer callback.
public function obcallback($value) {
$this->foo = 'set';
return $value . '(modified)';
}
// Main method.
public function run() {
ob_start(array($this, 'obcallback'));
echo 'this is the output', PHP_EOL;
return ob_get_clean();
}
}
// Run the test with ob_get_clean().
$t = new TestWithGetClean();
echo $t->run(); // This method returns a value in this test. (But not the correct value!)
echo $t->foo, PHP_EOL;
The output from running this is:
this is the output
set
The text '(modified)' does not appear anywhere. Note however that the instance variable $foo is set, so the callback is definitely called, however the output is not as I originally expected.
Compare to this one which uses ob_end_flush():
// Tests the use of callbacks with ob_end_flush().
class TestWithEndFlush {
// This variable is set when obcallback is called.
public $foo = null;
// The output buffer callback.
public function obcallback($value) {
$this->foo = 'set';
return $value . '(modified)' . PHP_EOL;
}
// Main method.
public function run() {
ob_start(array($this, 'obcallback'));
echo 'this is the output', PHP_EOL;
ob_end_flush();
}
}
// Run the test with ob_end_flush().
$t2 = new TestWithEndFlush();
$t2->run(); // This method produces output in this test.
echo $t2->foo, PHP_EOL;
This one produces the following output:
this is the output
(modified)
set
However, this is of course not as useful because the output goes directly to the client, so we cannot further manipulate the result. (For example, wrapping the text in a Symfony HttpFoundation Component Request object).
Output buffering in PHP is fun. It simplifies many things. I use ob_start() at the top of the script and ob_get_clean() (or any other function) at the bottom.
Between those two calls is it possible to call those functions again, without interfering the parent calls.
Is this type of code valid ? (it works fine, but...) Is this a good habit ?
<?php
ob_start(); //NOTICE !!!
echo '<p>echos of the top of the script</p>';
echo GetSomeOtherData(true);
echo '<p>echos after GetSomeOtherData()</p>';
$data = ob_get_clean(); //NOTICE !!!
echo $data;
//just a function to return something, with the help of output buffering
function GetSomeOtherData($toReturn)
{
ob_start(); //NOTICE !!!
echo '<p>This has been rendered inside a function</p>';
$function_data = ob_get_clean(); //NOTICE !!!
if($toReturn===true)
{
return $function_data;
}
else
{
//may be an error | return something else
return '<p>An Error</p>';
}
}
?>
From the ob_start() manual:
Output buffers are stackable, that is, you may call ob_start() while
another ob_start() is active. Just make sure that you call
ob_end_flush() the appropriate number of times. If multiple output
callback functions are active, output is being filtered sequentially
through each of them in nesting order.
So it is perfectly valid to assume that an ob_end/get will end/return the matching ob_start e.g.:
ob_start();
echo "<div class=outer>";
ob_start();
echo "<div class=inner></div>";
$inner = ob_get_clean(); // <div class=inner></div>
echo "</div>";
$outer = ob_get_clean(); // <div class=outer></div>
In all honesty, I don't see any problem with that. Every call to ob_start() is matched by an ob_get_clean() call, so the use of such functions is completely transparent to the "parent" ob_start(). It would be a horrible habit if pairs (of calls to ob_start() and ob_get_clean()) didn't match -- but as long as they do, it shouldn't (and won't) cause you any trouble.
I am trying to implement a SAX based parser but somehow it only recognizes the start of the element and the end, the content is not provided in the logs. The variable holding the XML is filled correctly, I checked through a simple log.
Here is the code:
<?php
function startElementHandler($parser, $name, $attribs) {
if($name == "id"){
$id = TRUE;
}
}
function endElementHandler($parser,$name){
$id = FALSE;
}
function characterDataHandler($parser,$data){
if($id == TRUE){
echo $data;
}
}
global $id;
$id = FALSE;
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElementHandler","endElementHandler");
xml_set_character_data_handler($parser,"characterDataHandler");
$xml = file_get_contents("http://itunes.apple.com/de/rss/topfreeapplications/limit=100/xml");
xml_parse($parser,$xml);
//xml_parser_free($parser);
?>
Any suggestion how I could recieve the content? Maybe I am missing something strange I am not aware of at the moment.
best regards
tim
Per your comment, $id never becomes true. Maybe you want attribs to have an id and not the name of the element. For example, if you have the XML
<div id="x"> blah </div>
You get
$name="div", $attribs={"id":"x"}
(this came out a bit of php-python, but i hope you get my point)
Is that really your bug?
According to http://www.phpcatalyst.com/php-compare-strings.php you should always compare strings using ===. Is that your bug?
You only used the xml_set_element_handler-callbacks. Those only:
Set up start and end element handlers
If you also want to retrieve the content of those tags, you'll also need to register the xml_set_character_data_handler-callback. Because this one:
Set up character data handler
I am trying to insert messages to a function
function addMessage($item) {
if ($result) {
$message = '<p class="ok">
<span> Item added </span>
</p>
';
header("Refresh: 2; url=?page=$item");
}
else{
$message = '<p class=not><span>There is an error blah blah</span></p>';
}
return $message;
}
When I use it : addMessage('contents') it only returns to second condition. How can I fix this?
You are checking $result inside the if but its neither been assigned any value before that nor been declared as global . I think you meant to check $item:
if ($item) {
Hi jasmine
Your function always returns the second condition because you haven't assigned a value to $result, eider inside the function or when you call the function (like unicornaddict mentioned by other words).
To get your code working the way you probably want, your function should be like this:
function addMessage($item, $result) {
if ($result) { // It will return this condition, case $result has any value assigned and is different from FALSE (boolean)
$message = '<p class="ok">
<span> Item added </span>
</p>
';
header("Refresh: 2; url=?page=$item");
}
else{ // It will return this condition, case $result doesn't has any value assigned or is equal to FALSE (boolean)
$message = '<p class="not"><span>There is an error blah blah</span></p>';
}
return $message;
}
And then you can call the function like you where already calling it, but don't forget to include a variable or a value that should be handled as the $result variable inside the function
addMessage('contents', $result);
Note:
In your $message variable you have <p class=not> and should be <p class="not">.
Remember that header() must be called before any actual output is sent to the browser.
Hope it Helps.
Is $result defined in your script? Use if ($item) instead.
Be very careful that PHP allows the usage of undefined variables.
what they said :-)
Btw, a decent IDE (like Zend) will analyze your code and warn you about things like that.
Such static code analysis is known as "linting", so google for "PHP lint" or see questions like Is there a static code analyzer [like Lint] for PHP files?
But this code sample is so small that I guess you are a beginner (no offence interned - we all had to start somewhere), so do a lot of reading and gather a lot of tools and experience.
For instance, a decent IDE (like Zend or Eclipse PDT) would let you step through your code, line nby line, and examine the value of each variable and then you ought to have seen the problem.
Welcome to PHP and good luck!