At the end of a page, if something occurs, it needs to be cleared, then the entire page needs to be re-parsed before serving to the client. I was going to echo out a javascript to refresh the page, but that will make them load the page and then reload it...I was wondering if there was a way to just tell the php engine to go back to the beginning and re-parse the entire page?
Thanks!
I will try to explain the problem more clearly but it is complicated and I am a terrible communicator. I on the page that lists products I am giving users the option to select fields to narrow the results. The system remembers this so they don't have to keep selected them. If they narrow a category like metal color and then go to a category that metal color is irrelevant like crystal figurines it will not show any results because none will match the metal color chosen. To generate the query to pull the products from the data-base is very complicated because different categories have different requirements to find the correct products. so once the query is generated I want to test it against mysql_num_rows() and if there is no results clear out the users choices and start over.
You're being a little vague, but if you're merely talking about reparsing the output, you could do that using output buffering.
I'm not entirely clear what the issue is, but couldn't you decide what is to be shown before creating the HTML, and then send the right thing the first time?
To generate the query to pull the products from the data-base is very complicated because different categories have different requirements to find the correct products. so once the query is generated I want to test it against mysql_num_rows() and if there is no results clear out the users choices and start over.
In that case, just put the query inside a function that returns the result, check the row count, and if it's zero clear the filters and call that function a second time.
Output buffering (ob_start and ob_clean), combined with separating the functionality at hand into a separate file and eval()'ing that should do the trick.
Oh, and recent PHP versions actually have a goto statement... although I'll always deny mentioning anything about it. :-)
I think you're going about it a little bit off.
What you should do to reparse the page is to redirect the user to the page again, using
header('Location: thepagefile.php');
however if you actually would like to reparse the file without creating a new page, you could also just include the file again:
include thepagefile.php
But you'd probably get the same result. If you want to actually parse the output of the page you'd do something like:
ob_start(); // this is at the very top of the code/page
// all the code goes here
$output = ob_get_clean();
eval($output); // WTF?
but that actually makes no sense, but I hope it helps.
I'd actually like to know what the real problem you're trying to solve really is.
I think your looking for something like this:
<?php
ob_start(); //we start output buffering, this means nothing is send to the browser
//We do some code stuff
$time = microtime();
echo "Hai \n"; //Note taht mixing logic and output in real life
echo $time; // is terribly practice
echo "\n bai"; //I do it here purely for the example
if(/*some condition */){
$anErrorHappened = true;
}
if($anEroorHappened === true){
//Load the output in a var if you need it
//Otherwise don't
$output = ob_get_clean();
//Do other code stuff
//I.E. send an error page
include('errorPage.html');
}
else{
ob_end_flush(); //Send everything the script has echo()'d, print()'ed and send to the browser in any other way (I.E. readfile(), header() etc.)
}
?>
Related
I am using wordpress for a web site. I am using snippets (my own custom php code) to fetch data from a database and echo that data onto my web site.
if($_GET['commentID'] && is_numeric($_GET['commentID'])){
$comment_id=$_GET['commentID'];
$sql="SELECT comments FROM database WHERE commentID=$comment_id";
$result=$database->get_results($sql);
echo "<dl><dt>Comments:</dt>";
foreach($result as $item):
echo "<dd>".$item->comment."</dd>";
endforeach;
echo "</dl>";
}
This specific page reads an ID from the URL and shows all comments related to that ID. In most cases, these comments are texts. But some comments should be able to point to other pages on my web site.
For example, I would like to be able to input into the comment-field in the database:
This is a magnificent comment. You should also check out this other section for more information
where getURLtoSectionPage() is a function I have declared in my functions.php to provide the static URLs to each section of my home page in order to prevent broken links if I change my URL pattern in the future.
I do not want to do this by using eval(), and I have not been able to accomplish this by using output buffers either. I would be grateful for any hints as to how I can get this working as safely and cleanly as possible. I do not wish to execute any custom php code, only make function calls to my already existing functions which validates input parameters.
Update:
Thanks for your replies. I have been thinking of this problem a lot, and spent the evening experimenting, and I have come up with the following solution.
My SQL "shortcode":
This is a magnificent comment. You should also check out this other section for more information
My php snippet in wordpress:
ob_start();
// All my code that echo content to my page comes here
// Retrieve ID from url
// Echo all page contents
// Finished generating page contents
$entire_page=ob_get_clean();
replaceInternalLinks($entire_page);
PHP function in my functions.php in wordpress
if(!function_exists("replaceInternalLinks")){
function replaceInternalLinks($reference){
mb_ereg_search_init($reference,"\[custom_func:([^\]]*):([^\]]*)\]");
if(mb_ereg_search()){
$matches = mb_ereg_search_getregs(); //get first result
do{
if($matches[1]=="getURLtoSectionPage" && is_numeric($matches[2])){
$reference=str_replace($matches[0],getURLtoSectionPage($matches[2]),$reference);
}else{
echo "Help! An unvalid function has been inserted into my tables. Have I been hacked?";
}
$matches = mb_ereg_search_regs();//get next result
}while($matches);
}
echo $reference;
}
}
This way I can decide which functions it is possible to call via the shortcode format and can validate that only integer references can be used.
I am safe now?
Don't store the code in the database, store the ID, then process it when you need to. BTW, I'm assuming you really need it to be dynamic, and you can't just store the final URL.
So, I'd change your example comment-field text to something like:
This is a magnificent comment. You should also check out this other section for more information
Then, when you need to display that text, do something like a regular expression search-replace on 'href="#comment-([0-9]+)"', calling your getURLtoSectionPage() function at that point.
Does that make sense?
I do not want to do this by using eval(), and I have not been able to accomplish this by using output buffers either. I would be grateful for any hints as to how I can get this working as safely and cleanly as possible. I do not wish to execute any custom php code, only make function calls to my already existing functions which validates input parameters.
Eval is a terrible approach, as is allowing people to submit raw PHP at all. It's highly error-prone and the results of an error could be catastrophic (and that's without even considering the possibly that code designed by a malicious attacker gets submitted).
You need to use something custom. Possibly something inspired by BBCode.
I have a PHP script that can take a few minutes to be done. It's some search engine which executes a bunch of regex commands and retrieve the results to the user.
I start by displaying a "loading page" which does an AJAX call to the big processing method in my controller (let's call it 'P'). This method then returns a partial view and I just replace my "loading page" content with that partial view. It works fine.
Now what I would like to do is give the user some information about the process (and later on, some control over it), like how many results the script has already found. To achieve that, I do another AJAX call every 5 seconds which is supposed to retrieve the current number of results and display it in a simple html element. This call uses a method 'R' in the same controller as method 'P'.
Now the problem I have is that I'm not able to retrieve the correct current number of results. I tried 2 things :
Session variable ('file' driver) : in 'P' I first set a session variable 'v' to 0 and then update 'v' every time a new result is found. 'R' simply returns response()->json(session('v'))
Controller variable : same principle as above but I use a variable declared at the top of my controller.
The AJAX call to 'P' works in both cases, but everytime and in both cases it returns 0. If I send back 'v' at the end of the 'P' script, it has the correct value.
So to me it looks like 'R' can't access the actual current value of 'v', it only access some 'cached' version of it.
Does anyone have an idea about how I'm going to be able to achieve what I'd like to do? Is there another "cleaner" approach and/or what is wrong with mine?
Thank you, have a nice day!
__
Some pseudo-code to hopefully make it a bit more precise.
SearchController.php
function P() {
$i = 0;
session(['count' => $i]); // set session variable
$results = sqlQuery(); // get rows from DB
foreach ($results as $result) {
if (regexFunction($result))
$i++
session(['count' => $i]); // update session variable
}
return response()->json('a bunch of stuff');
}
function R() {
return response()->json(session('count')); // always returns 0
}
I would recommend a different approach here.
Read a bit more about flushing content here http://php.net/manual/en/ref.outcontrol.php and then use it.
Long story short in order to display the numbers of row processed with flushing you could just make a loop result and flush from time to time or at an exact number or rows, the need for the 5 seconds AJAX is gone. Small untested example :
$cnt = 0;
foreach($result as $key => $val) {
//do your processing here
if ($cnt % 100 == 0) {
//here echo smth for flushing, you can echo some javascript, tough not nice
echo "<script>showProcess({$cnt});</script>";
ob_flush();
}
}
// now render the proccessed full result
And in the showProcess javascript function make what you want... some jquery replace in a text or some graphical stuff...
Hopefully u are not using fast_cgi, beacause in order to activate output buffering you need to disable some important features.
I believe you have hit a wall with PHP limitations. PHP doesn't multithread, well. To achieve the level of interaction you are probably required to edit the session files directly, the path of which can be found in your session.save_path global through php_info(), and you can edit this path with session_save_path(String). Though this isn't recommended usage, do so at your own risk.
Alternatively use a JSON TXT file stored somewhere on your computer/server, identifying them in a similar manner to the session files.
You should store the current progress of the query to a file and also if the transaction has been interrupted by the user. a check should be performed on the status of the interrupt bit/boolean before continuing to iterate over the result set.
The issue arises when you consider concurrency, what if the boolean is edited just slightly before, or at the same time, as the count array? Perhaps you just keep updating the file with interrupts until the other script gets the message. This however is not an elegant solution.
Nor does this solution allow for concurrent queries being run by the same user. to counter this an additional check should be performed on the session file to determine if something is already running. An error should be flagged to notify the user.
Given the option, I would personally, rewrite the code in either JSP or ASP.NET
All in all this is a lot of work for an unreliable feature.
Ive got some code that runs html code from a database in order to not have to make a new file for every page that I might want to make, problem with this is that if the page contains php code it wont run, and im pretty sure you can do this with eval however it has security risks so I was trying to find some alternatives. I can paste the code if necessary. Ive got a php script that gets data from table and a main php script that gets the formatting in HTML and PHP for the data however it will just run the PHP code as if it were strings from the database.
Here is an image of the code thats meant to be run from the php script :
Here is the php code in that row
And this is the main script that is meant to run it :
Why not make PHP functions? Like, for example if you wanted to spit out data from your databases using PHP, but not a lot of code, you can do something like... (for user profiles)
Like, you can make a funcs.php
then inside of it do:
function user_page($user_id){
?> [Create user page here] <?php
}
Then inside of any other file just do:
include 'funcs.php';
if(isset($_GET['username']) === true){
user_page($_GET['username']);
} else {
//if not loading user page then do something else
}
EDIT
Okay, I just saw your screenshot.
To do something like that, a function would be good.
Ex:
function print_data($info1,$info2,$info3,$info4){
echo("<center>$info1</center><br>$info2<br>$info3<br>$info4");
}
then just calling the function with the $row[] information you have in your screenshot.
Like so:
print_data($row['email'],$row['name'],$row['username'],$row['ip_addr']);
this question must be added to some "doing it wrong" list, honestly.
but, returning to your question you have 3 options, all of them more or less painful, and only one of them is right.
to do it right: rewrite your engine or take some cms/framework. store text data in database, scripts/template on disk
eval! (which you don't want)
parse. (it will be very hard and slow and totally crazy)
In PHP have a situation where I need the page to be mostly executed, but have an item inserted into the output from that page.
I think output buffering may be of some help, but I can't work out how to implement it in my situation.
My code looks like this:
//this document is part of a global functions file
function pageHeader (){
//I'm using $GLOBALS here because it works, however I would really rather a better method if possible
$GLOBALS['error_handler'] = new ErrorHandler(); //ErrorHandler class sets a function for set_error_handler, which gets an array of errors from the executed page
require_once($_SERVER['DOCUMENT_ROOT'].'/sales/global/_header.php');
//I would like the unordered list from ->displayErrorNotice() to be displayed here, but if I do that the list is empty because the list was output before the rest of the document was executed
}
function pageFooter (){
$GLOBALS['error_handler'] ->displayErrorNotice(); //this function displays the errors as an html unordered list
include($_SERVER['DOCUMENT_ROOT']."/sales/global/_footer.php");
}
Most pages on the site include this document and use the pageHeader() and pageFooter() functions. What I am trying to achieve is to put an unordered list of the PHP generated errors into an HTML list just at a point after _header.php has been included. I can get the list to work as intended if I put it in the footer (after the document has been executed), but I don't want it there. I guess I could move it with JS, but I think there must be a PHP solution.
UPDATE
I'm wondering whether a callback function for ob_start() which searches the buffer by regex where to put the error list, and then inserts it will be the solution.
UPDATE 2 I have solved the problem, my answer is below. I will accept it in 2 days when I am allowed.
Worked it out finally. The key was to buffer the output, and search the buffer for a given snippet of html, and replace it with the unordered list.
My implementation is like this:
function outputBufferCallback($buffer){
return str_replace("<insert_errors>", $GLOBALS['error_handler']->returnErrorNotice(), $buffer);
}
function pageHeader (){
ob_start('outputBufferCallback');
//I'm using $GLOBALS here because it works, however I would really rather a better method if possible
$GLOBALS['error_handler'] = new ErrorHandler(); //ErrorHandler class sets a function for set_error_handler, which gets an array of errors from the executed page
require_once($_SERVER['DOCUMENT_ROOT'].'/sales/global/_header.php');
echo '<insert_errors>'; //this snippet is replaced by the ul at buffer flush
}
function pageFooter (){
include($_SERVER['DOCUMENT_ROOT']."/sales/global/_footer.php");
ob_end_flush();
}
If I'm getting this right, you're trying to insert some calculated code/errors between the header and footer. I'm guessing that the errors are being totalled/summed up at the very end of the page and would be completed after the page footer.
If this is true, I can't think of anyway to do this with pure php. It can only run through a page once, and cannot double back. What you can do is create an element after the footer and move it using javascript to the area where you want to display it. This would be the easiest way I would think. You can do this easily with jquery.
I can explain further if I am on the right track, but I'm not 100% sure what you're asking yet...
The jquery command you would use is .appendTo().
I am working on my personal site, where I want to store my customers recent search result limited to that particular session.
I am using PHP platform and Javascripts.
Here is an example of what I am exactly looking at :
It stores your previously searched domain name for that particular session so that user can make decision by comparing those results.
Thanks.
EDIT- Well Thanks for all of your answers and suggestions.
But If you have noticed
above example
It looks like some kind of script loading a new content on the same page without refreshing it and keeping previous search content <div> as it is.
How to achieve this using javascripts or some sort of div layer ????
UPDATE START
This example uses page reload. If you want to do it without page reload, you can but you'll have to use AJAX to load new search results. But then, it's not a PHP question. I suggest looking at jquery library, as it makes it easy. Tutorials: http://docs.jquery.com/Tutorials and e.g. this one ( http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery#Rate_me:_Using_Ajax ).
When loading data via AJAX, the page rendering result (in my example search.php) should return only HTML for results part, not whole HTML page. This is generally a first part of my tutorial (without session).
But I really think that AJAX in here is not really needed. Session is more reliable and allows access to your page from older / mobile browsers where not always JS works correctly.
UPDATE END
Ok then. Let's try the simple tutorial then. Sorry if too simple, but I don't know your exact level.
PHP has mechanism called sessions. In reality they are just bytes stored on server. Server knows which session is for each client by reading session cookie from client browser.
Not every page uses sessions (not every page needs it, and session uses server space, even if only temporarily), session is not enabled by default. To turn on session you use command
<?php session_start(); ?>
In most cases this is either run by PHP framework you use, or put near the top of your site. Session is definitely needed if you want to authenticate user somehow. Or in your case :)
To access session you can use superglobal $_SESSION variable (superglobal means that you can access it anywhere). It's an array, so session element will be e.g. $_SESSION['search'] etc.
As example, let's assume that your page looks like that
<html>
...
<form action="search.php" method="post">
Search: <input type="text" name="searchQuery" />
<input type="submit" value="Search" />
</form>
...
</html>
this very form will send user search to file named search.php. It can be the same file where the form resides - in simplest case when you put both your code and HTML in one file. Beginners often use this schema, although it's not advisable as result is a mess and hard to further change.
In search.php then, you'll use similar code:
<?php
if (!empty($_POST['searchQuery'])) //we have a new search
{
$result = do_search($_POST['searchQuery']);
}
?>
Then, somewhere below you'll display your search result ($result variable). do_search() function is your search mechanism, I guess you have it somewhere. You may have it not 'wrapped' in a function, then I advise to create it like that, it's much more useful.
function do_search($searchQuery)
{
...
return $result;
}
mind it, the above code doesn't use sessions yet. Let's add saving previous search results in session. The code may then look like that:
<?php
session_start(); //Starting session
//let's create session variable used to store results
if (!isset($_SESSION['searches']))
$_SESSION['searches'] = array();
if (!empty($_POST['searchQuery'])) //we have a new search
{
if (isset($_SESSION['searches'][$_POST['searchQuery']]) //User already searched on this value, delete previous result from sesion
{
unset($_SESSION['searches'][$_POST['searchQuery']]);
}
$result = do_search($_POST['searchQuery']);
//Let's add new search on the begining of session array to make iterations easier.
$result = array($_POST['searchQuery'] => $result); //convert result to same format as session table
$_SESSION['searches'] = array_merge($result, $_SESSION['searches']);
}
?>
In display you'll now not iterate on $result variable as before, but instead you will do something like
foreach ($_SESSION['searches'] as $query => $result)
{
...//display of single result
}
I haven't tested following code and it's not a full program. Parts to display result and to do actual search are not described but I guess you have them already prepared. Also, this is only one possible approach of countless possibilities. But I hope this helps :)
Possible modification - now I always perform search, even if user already searched on this term. You may want to receive the result from cache without second search. Then the code will look like
if (isset($_SESSION['searches'][$_POST['searchQuery']]) //User already searched on this value
{
$result = $_SESSION['searches'][$_POST['searchQuery']];
unset($_SESSION['searches'][$_POST['searchQuery']]);
}
else
{
$result = do_search($_POST['searchQuery']);
}
For more in-depth information about sessions and some other constructs used in my example I suggest PHP manual
http://pl.php.net/manual/en/book.session.php
and various tutorials over the network. Or you can add a comment here :)
Put this code near the beginning of your script(s):
if (!isset($_SESSION['previous_searches']) || !is_array($_SESSION['previous_searches'])) {
$_SESSION['previous_searches'] = array();
}
[edit]
This code snippet checks if if there is already an array with prevous searches and if not it will be created.
[/edit]
Then when the user hits the search page put this code in the receiving script of the search:
$_SESSION['previous_searches'][] = $_GET['what_ever_your_search_value_might_be'];
[edit]
This code snippet adds the current search value to the and of the array with previous search values
[/edit]
Now you have all previous search values in $_SESSION['previous_searches']
If your website is a web application where you never reload the page nor change the page, you can keep it JavaScript in a global store (declare at top level something like var StoredSearch = []; and use it). If not, then use $_SESSION to store this and AJAX to save/load searches from JavaScript to PHP.