Is it a good practise, to use the php session object, to store several of my variables, can be arrays of request results.
I need this method, because I would like to do the request in a php file, store the result and immediately, (depending on result) redirect to a page,
It's probably not the best way, that's why I'm asking
thx for any advice,
edit: structure:
index.html
handler.php
view1.php
in index.html, I've got a
<form action="handler.php" ...
in handler.php, I construct a request and get a result,
if ($result->success)
header("location ./view1.php");
else
echo 'failed';
in view1.php, I would like to list the result array
Webshops do it - so why shouldn't you?
Some of the larger eCommerce frameworks store complicated data and objects in sessions and PHP handles this pretty well.
That's what sessions are for! So the general answer is "Yes: it's a good practice".
Here are some alternatives, however:
Consider using ajax calls to update parts of the loaded page without reloading it;
Cookies - not good for big amount of data, but generally can live longer than a session. Not useful in your particular case, however;
SQL servers are usually well-optimized, and when your query returns lots of rows and you cut those into sections with a LIMIT clause, or just repeat exactly the same request soon after the first time, the subsequent requests aren't of such a big load for the database server.
I just seen your update to the question.
AJAX can do the trick for you the best. I can imagine it all done within a single web page:
form data is submitted by an AJAX call to you handler.php, which..
returns either a JSON-packed array of results or a short string NOT FOUND, for example.
Then, the JS on your page either creates a new DOM element - a table, or a set of div's, with the returned results, or just creates a new div with some sad toon face and a "we didn't find anything' message.
// set session
session_start();
$_SESSION['my_session'] = array('var1' => 'value1', 'var2' => 'value2'); // your result list
session_write_close();
// get Session
echo ($_SESSION['my_sesson']['var1']);
if ($result->success)
header("location ./view1.php");
else
echo 'failed';
This is not good practice to use redirects to route requests. You can do it without additional request from the user.
Like this:
if ($result->success) {
include(dirname(__FILE__) .'/'. 'view1.php');
} else {
echo 'failed';
}
Thus, all variables from handler.php will be available in view1.php.
Related
Is it possible to submit a query without updating the URL?
On a dictionary, I want to do first one simple query: www.example.com/?q=word
On the result page there will be a button with which I want to search for more results with another query.
This second query will be done normally with www.example.com/more.php?q=word.
That code would look as follows:
<button onclick="window.location.href = 'more.php?q=<?php echo "$trimmed"; ?>';">search for more results</button>
However, I want that the URL remains unchanged so that the next dictionary query starts again with a simple query. In other words, I want to hide the part "more.php" from the URL.
Assuming that your www.example.com?q=word points to the index.php.
Assuming also that your more.php contains functions.
Assuming as third, that your index.php returns something displayable in the browser even if there is no GET-parameter i.e. the initial page call.
Doing so, a really simple solution would be to fire every query against the index.php.
There you can handle every query, even different types, based on a new GET-parameter type use use.
#index.php
require 'more.php';
// do something here to validate the parameters you use
switch($_GET('type')) {
case 'simple':
return simpleCall();
break;
case 'more':
return additionalInfo();
break;
}
function simpleCall() {
// do stuff here
// access $_GET for other paramters
}
#more.php
function complexCall() {
//do complex stuff here
}
Finally, your HTML would look something like this
<button onclick="window.location.href = '/?type="more"&q=<?php echo "$trimmed"; ?>';">search for more results</button>
Until you get more than these two types it becomes cluttering at your switch-statement.
For this reason, it would be a good idea to think about different solutions like:
having a routing system like this https://medium.com/the-andela-way/how-to-build-a-basic-server-side-routing-system-in-php-e52e613cf241
using asynchronous calls from your frontend with the help of JavaScript to call to different PHP files on the server but stay on the same page in the frontend. This will immediately lead to some kind of API. But this is generally not the badest idea.
Please validate your parameters regardless if POST or GET before you do anything with them in the rest of your code. Having the example of a dictionary sounds extremely like to query a database where SQL injection is, for example, a big thing if data us used unchecked.
I hope this helps a bit.
Im looking for an elegant way to hand over data/params when using $f3->reroute();
I have multiple routes configured in a routes.ini:
GET #sso: /sso/first [sync] = Controller\Ccp\Sso->first, 0
GET #map: /map [sync] = Controller\MapController->second, 3600
Now I reroute(); to #map route, from first();
class Sso {
public function first($f3){
$msg = 'My message!';
if( !empty($msg) ){
$f3->reroute('#map');
}
}
}
Is there any "elegant" way to pass data (e.g. $msg) right into $MapController->second(); ?
I donĀ“t want to use $SESSION or the global $f->set('msg', $msg); for this.
This isn't an issue specific to fat-free-framework, but web in general. When you reroute, you tell the browser to redirect the user's browser page using a 303 header redirect code.
Take a minute to read the doc regarding re-routing: http://fatfreeframework.com/routing-engine#rerouting
There seems to be some contradicting information in your question, which leads me to question the purpose of what you are trying to achieve.
If you are rerouting, you can either use the session, cookies, or use part of the url to pass messages or references to a message.
If you do not need to redirect, but just want to call the function without changing the passed parameters, you could abstract the content of the function and call that function from both routes. You could also use the $f3 globals, which are a great way of passing data between functions in cases where you don't want to pass the data using the function call. is there a reason why you don't want to to use this? The data is global for the single session, so there is no security concern, and the data gets wiped at the end of the request, so there is very little extra footprint or effect on the server.
If you're alright with not using #map_name in re-routes you can do something like this:
$f3->reroute('path/?foo=bar');
Not the prettiest I'll admit. I wish $f3->reroute('#path_name?foo=bar') would work.
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.
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.
I'm new to PHP and I'm trying to do something that may be bad practise and may well be impossible. I'm basically just hacking something together to test my knowledge and see what PHP can do.
I have one webpage with a form that collects data. That is submited to a PHP script that does a bunch of processing - but doesn't actually display anything important. What I want is that once the processing is done, the script then tells the browser to open another page, where the results are displayed.
I know I can use header('Location: page.php'); but I can't work out how to provide POST data with this. How can I do that? Alternatively, is there another way to tell the browser to open another page?
EDIT: What I'm taking from the responses is that it's possible to do this using various hacks but I'd be better off to just have the processing and the display code in one file. I'm happy with that; this was an experiment more than anything.
You could store that data in the session e.g. in the first file that handles the post
session_start();
$_SESSION['formdata'] = $_POST; //or whatever
then you can read it on the next page like
session_start();
print_r($_SESSION['formdata']);
or you could pass it through GET: (but as per comments this is a bad idea)
header('Location: page.php?' . http_build_query($_POST));
If you do that make sure you do additional processing/validation on page.php as a malicious user could change the variables. also you may not need the whole post transmitted to the next page
Edit
I should make clear that I think the second option is possibly worse, as you are limited by the size of data you can send through get and it is possibly less secure as users can more obviously manipulate the data.
Is it really necessary to call another page after the processing is done? I'd probably do the following:
<form method="post" action="display.php">
...
</form>
display.php:
if ($_POST) {
require_once(process.php);
process($_POST);
display_results;
}
with process.php containing the code necessary for processing the post request.
Alternatively, you could use something like the cURL library to pass the results of the processing to a page specified by yourself. Don't know if that's really what you're after though.
You could use JavaScript as a dirty work-around:
<form id="redirect_form" method="post" action="http://someserver.com/somepage.php">
<input type="hidden" name="field_1" value="<?php echo htmlentities($value_1); ?>">
<input type="hidden" name="field_2" value="<?php echo htmlentities($value_2); ?>">
<input type="hidden" name="field_3" value="<?php echo htmlentities($value_3); ?>">
</form>
<script type="text/javascript">
document.getElementById('redirect_form').submit();
</script>
(the script should be below the form)
There's no way to redirect the user's browser to an arbitary page and sent a POST request. That would be a bit security risk, where any link could cause you to make any form submission to an arbitrary site without you having any kind of clue about what was going to happen.
In short, it's not possible
AFAIK this is usually done as a two-step process:
On form.php, POST the data to script process.php
The process.php script processes the data but never outputs anything itself, it always calls header("Location: asdasd") to redirect to a success.php or failure.php page (if applicable)
Do it all in one script and just output different HTML for the results.
<?php if($doingForm) { ?>
html for form here
<?php } else { ?>
html for results
<? } ?>
This problem has vexed me for some time. My custom CMS does some quite complex processing, uploading and manipulation, and so sometimes ouputs quite lengthy error and information messages, which aren't suitable for converting to GET data, and I have always wanted to avoid the reload problem on data INSERT, but not yet found an adequate solution.
I believe the correct way to go about this, is to create message arrays for each possible state - each message or error you could want to display, and then you only need to send error/message numbers which are a lot easier to handle than long data strings, but it's something I have always shied away from personally as I find it a bit tedious and cumbersome. Frankly, this is probably just laziness on my part.
I quite like the SESSION variable storage solution, but this raises the question of how do you ensure the SESSION data is properly destroyed?
As long as you ensure you are only sending information (messages/errors) and not data that should/could be stored (and thus potentially sensitive) this should be an avoidable problem.
I hope i got your qestion right.
You might try this:
Adjust your form to look like this:
form method="POST" action="process_data.php"
2.
Then you create the file process_data.php, wich surprisingly processes the data.
And in this file you use header:
For example:
$head = sprintf("page.php?data1=%d?data2=%d",$data1,$data2);
header($head);
I hope i could help.