how do I select a url parameter? - php

So I have a backoffice called biblioteca.php where I have some requests and I can validate them trough a button called "Validar". That button redirects to a page like this: http://localhost/pap_16gpsi21/validacao.php?nproposta=87 where I can fill the form and submit.
What I want is to validate the request related to that url.
Example:
I've a request and his number is 90, I click on "Validar", then redirects me to a page like this http://localhost/pap_16gpsi21/validacao.php?nproposta=90, I fill the form and click submit. Then it updates the request number 90 in the database ($updateEstado = "UPDATE propostas SET validacao='Validado'";)
biblioteca.php
$selectProp = "SELECT nproposta, prioridade,disponibilidade,validacao,
autorizacao,aquisicao,registo,biblioteca,docente
FROM propostas
ORDER BY nproposta DESC";
$resultado = mysqli_query($ligaBD, $selectProp);
if (mysqli_num_rows($resultado) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($resultado)) {
<td><a class="btn btn-default" href="./validacao.php?nproposta=<?= $row["nproposta"] ?>">Validar</a></td>
valida.php
// gets nproposta from propostas
$npropostaLinha = "SELECT nproposta FROM propostas";
$resultado=mysqli_query($ligaBD, $npropostaLinha);
$nproposta = "";
printf($npropostaLinha);
$row = mysqli_fetch_array($resultado,MYSQLI_NUM);
printf("==> ");
print_r($row[0]);
$nproposta = $row[0];
$insertValidacao = "INSERT INTO validacao
(nproposta,nome_validacao,nif_validacao,
email_validacao,preco_validacao)
VALUES ($nproposta,'$nome_validacao','$nif_validacao',
'$email_validacao','$preco_validacao')";
$updateEstado = "UPDATE propostas SET validacao='Validado'";
$resultado = mysqli_query($ligaBD, $insertValidacao);
$resultado = mysqli_query($ligaBD, $updateEstado);
The problem is that if I have 3 requests (90,91,92) and I decide to validate just the number 91 it updates the first which is the number 90.
Also I know this isnt the safest method but this is just a test.
Hopefully, I explained explicitly. Sorry for any grammatical mistakes. Thank you

You need a couple of changes in your code as there are a few logical mistakes that I think you want to avoid.
You need to target a variable to specify from your SELECT that you desire a specific proposta;
You need, when updating, to specify which row, otherwise you will update every single record in your DB;
For such, go to your valida.php and add the following:
At the very top, check you have the variable ready
if (!isset($_POST['nproposta']) || empty($_POST['nproposta'])) {
//Do here what you desire to stop the script from running. Redirect back if you wish;
echo "No proposal id was found";
die;
}
$nPropostaID = $_POST['nproposta'];
Once you have your ID to target the row in your DB, update your query to consider it;
UPDATE propostas SET validacao='Validado' WHERE nproposta = $nPropostaID
Go to your form view and add below line within the form
<input type='hidden' value="<?php echo $_GET['nproposta']?>" name="nproposta">
NOTE: Because you mentioned you are aware of the SQL injections and this is a test I won't go with those, but always good to remember to be careful with them :) My proposal for the queries is just to get you going and in no way good for a script!

Related

PHP and SQLite Service in Memory

I have a single page responsive HTML page. One section of the page has a product search. User can enter search criteria in a form and get back the results. The results are paged.
<form id="filterform" name="filterform" method="post" action="./loaddata.php">
...
</form>
The form is submitted by Ajax and the results are returned as an HTML fragment that gets dynamically inserted into the DOM to refresh the results.
That's all working OK, but sometimes the results from loaddata.php are very slow, usually the first time called from the page.
In loaddata.php I'm using a Sqlite3 database. It is read only. Something like the following:
$filename = "../datafile.sqlite3";
$db = new SQLite3($filename);
$q = "SELECT distinct productId, title, price, name FROM datatable LIMIT 16";
$results = $db->query($q);
while ($row = $results->fetchArray()) {
echo "<h1>Results</h1>";
}
$db->close();
Is there a way to make loaddata.php load and stay in memory to respond to the form submit? It seems like it will reload every submit.
Depending on the size of the datatable you can save it on SESSION, use functions like shmop_open/shmop_write/shmop_read or (better yet) use some cache service like redis, but in one way or another the data will be stored and processed every time you pass by that place. I would tere the page in pieces, create one webservice to deal with the form post and another to show the form.
The easiest (not necessary safest or best way to do) would be ...
PS: I assume you are working with PDO and (obviously) the code bellow is an elaboration, it will not actually work
if (isset($_SESSION['db_datatable'])) {
foreach ($_SESSION['db_datatable'] AS $item) {
echo "<h1>".$item['some_row']."</h1>";
}
} else {
$filename = "../datafile.sqlite3";
$db = new SQLite3($filename);
$q = "SELECT distinct productId, title, price, name FROM datatable LIMIT 16";
$results = $db->query($q);
while ($row = $results->fetchArray()) {
$_SESSION['db_datatable'][] = $row;
echo "<h1>Results</h1>";
}
$db->close();
}
Hope I have been of some help. Cheers!

Logging profile updates in PHP

I have a edit profile page in my social media website.
When users click submit on the form. I run an update query to obviously update the users field in the database.
How can I optimize this scenario to include the logging of which particular fields are updated?
So for e.g.
One scenario could be:
Chris updated his profile picture.
Another scenario would be:
Chris updated his profile, inc:
Email
Username
Address
Address 2
Can anyone offer a solution to this?
I feel there is no need for code as all it is, is an update query.
Thanks
When writing out the form, save the current states in the $_SESSION-variable. The check the submitted forms and compare with the data in the $_SESSION-variable. Then only make an update on the forms that have changed.
if($_SESSION['name'] != $myform['name']) { $sql[] = "name = '{$myform['name']}'"; }
if($_SESSION['img'] != $myform['img']) { $sql[] = "img = '{$myform['img']}'"; }
$sqlstring = "UPDATE mytable SET " . implode(",",$sql);
// run the sql
EDIT: to implement logging:
// populate the variables (name, img) from the db/session with the highest revision number.
// ie SELECT * FROM mytable where userid = $userid ORDER BY revision DESC LIMIT 1
$revision = $_SESSION['revision'] + 1;
$sql = "INSERT INTO mytable SET img = '$img', name='$name', revision='$revision'";
Did you put all that information in a $_SESSION or something? If so, you can unset the session and declare it again, with the new info.
You can use custom setters / getters to do this. Check the code below.
You can also add additional checks to make sure the values have changed, or use magic methods to make things more dynamic.
class MyObject
{
protected $modifiedFields = array();
public function setField($value) {
if (!in_array('field', $this->modifiedFields)) {
$this->modifiedFields[] = 'field';
}
}
}
If you have the modified fields, you can just run the update query to contain only these fields.

PHP form submits to itself. When clicking on paginating links. All except the Form, vanishes

It is a self-submitting Form. I have 3 independent Select lists whose selected values are passed as the WHERE parameters for the sql query.
When I click on the button, all data are displayed just fine, well LIMITed, and the link pages are below. But:
When I get to click on the page links, the result set and all the links disappear from sight (only the select lists remain in sight). I believe it is related to the isset condition that, if the values have not been set, display the form, if the values have been set, then process the form. So, the first result set displays correctly, but when you try to go to the second page my form interprets that the Select Lists are not set because they are reset and because i have not clicked on the button if i click on the links instead and therefore, it wipes out everything that it not an html Form.
There is no error in the paginating code. The error is in how I link this form with this paginating method. And I can't get to know how I should.
if (isset($_POST['submitted'])) { /***************IF IT IS SET, WE PROCESS THE VALUES*************************/
$oldcountry = FALSE;
$oldfrom = FALSE;
$oldinto = FALSE;
// Here just checking that all variables have been selected
if (isset($_POST['country']))
{
$oldcountry = $_POST['country'];
$country = filter_var($oldcountry, FILTER_SANITIZE_STRING);
}
else {
echo 'Please, select a country';
}
if (isset($_POST['from_language']))
{
$oldfrom = $_POST['from_language'];
$from_language = filter_var($oldfrom, FILTER_SANITIZE_STRING);
}
else {
echo 'no has metido el from language';
}
if (isset($_POST['into_language']))
{
$oldinto = $_POST['into_language'];
$into_language = filter_var($oldinto, FILTER_SANITIZE_STRING);
}
// so, once we have selected them and clicked the button, we go for the query
// and paginate the results
require_once('bdd1.php');
$per_page = 6;
$pages_query = mysql_query("SELECT COUNT(FName)
FROM work_assignment, developer
WHERE AES_DECRYPT(country, 'elperrodesanroquenotienerabo') = '".$country."'
AND from_language = '".$from_language."'
AND into_language = '".$into_language."'
AND work_assignment.developer_id = developer.developer_id
ORDER BY FName ASC ");
$pages = ceil (mysql_result($pages_query, 0) /$per_page);
$page = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
$start = ($page - 1) * $per_page;
$query = mysql_query("SELECT FName
FROM work_assignment, developer
WHERE AES_DECRYPT(country, 'elperrodesanroquenotienerabo') = '".$country."'
AND from_language = '".$from_language."'
AND into_language = '".$into_language."'
AND work_assignment.developer_id = developer.developer_id
ORDER BY FName ASC LIMIT $start, $per_page");
while ($query_row = mysql_fetch_assoc($query)){
echo '<p>', $query_row['FName'], '</p>';
}
if ($pages >=1) {
for($x = 1; $x <=$pages; $x++){
echo ''.$x.' ';
}
}
} /************* END OF IF ISSET TO PROCESS *******************************/
?>
UPDATE UPDATE
After all the help, I managed to write a URL string that makes the page links work. Yet, still I need to tweak it as I hardcoded the name of the country (basically Estonia) instead of embedding the variable that represents it, but I can't make that URL properly be written:
This works:
echo '<a href="?country=Estonia&from_language=Russian&into_language=Latvian&submitted=true&
page='.$x. '">'.$x.'</a> ';
I would just need to replace Estonia by $country, and Russian by $from_language and Latvian by $into_language. But I have tried all possible combinations of single and double quotes and dots and I get syntax errors. Does anybody know how to write that?
The POST variables are lost because the form isn't submitted when you click the link, just as Slomo pointed out.
Unless you want those values hidden from the user, you may set the form's method to GET instead of POST. That way the variables are added to the URL, just like $_GET['page'].
The links would then have to be rendered in a way that keeps the URL intact except for the page variable, that needs to be changed. It can be done like this (just change currentpage to page):
A problem of a repeated parameter in the pagination links?
Update:
If you want to insert variables inside a string you can either place them inside double quotes (and escape other double quotes inside the string), or concatenate the string and variables, see these two examples:
echo "$x";
echo '' . $x . '';
$_POST values are only set if information is sent with a POST request, for example your has most likely method=POST. When you submit your form with method POST (button=submit) the $_POST values are set. Whenever you klick another link, only a request for a new page will be sent to the server.
If you need the information to be available after the first form submit, you should use a Session. (http://php.net/manual/de/features.sessions.php)
Sessions are stored for each client (webbrowser) and are available until the session times out (please see manual). You would have to set the session variables the first time the form gets submitted. Afterwards you can use the values from the session.
/Edit
If you do not want to use a session, you could add the filter criteria as url parameters (index.php?groupby=country) to the normal links. They would then be accessed with $_GET.

How to show a link counter change live?

What this code does is taking links from the db and compare it to a keyword, if it compares then KeywordCounter++, and in every time LinkCounter++
I want to type LinkCounter after every link it goes through but in the code I wrote it only shows me after the loop ends (after all the links crosses). How can I see the LinkCounter every time a link is checked?
How will I be able to see live the counter jumps?
<?php //holdes the db connection include('Connect.php');
$KeyWord = 'googoo';
$LinkCounter = "0";
$KeywordCounter = "0";
$query = mysql_query("SELECT * FROM doalgo where Pass != '0'") or die(mysql_error());
while ($info = mysql_fetch_array($query)) {
$id = $info['id'];
$link = $info['link'];
$num_rows = mysql_num_rows($query);
mysql_query("UPDATE doalgo SET Pass = '1' WHERE id = '$id'");
$CurrentFile = file_get_contents($link);
if (!strpos($CurrentFile, $KeyWord)) {
//nothing
} else {
mysql_query("UPDATE doalgo SET Posted = '1' WHERE id = '$id'");
$KeywordCounter++;
}
$LinkCounter++;
if ($id == $num_rows) {
die();
}
}
echo "<br />KeywordCounter: ".$KeywordCounter;
echo "<br />LinkCounter: ".$LinkCounter;
? >
Its better you calculate the average speed of update (for example number of updates per hour) and send just a single integer to the browser every 1 hour.
using jquery you can change the value shown to user with that speed.
If I understand your question correctly, you want the web page to display immediately, then constantly update the LinkCounter display as the SQL queries progress?
If this is a correct understanding, to do this requires AJAX. Your server has to send constant updates to the web browser every time $LinkCounter is updated, then the JavaScript running in the browser will update the display with that information. Obviously, it's a much more complicated thing to do than what your script currently does. It's an entirely different design pattern.
If this is truly something you want to learn to do, there are many books on the subject of AJAX, or google can help you, too.

Best practice: Use same form for creation and update

I'm just curious and was wondering how you guys handle it if you want to use the same html form and as far as possible the same php code to create and update an item.
Example:
On one page you can create a database entry with name, email address and age.
On a different(?) page you see the form fields filled with your data and you can edit and save it.
I have my ways to accomplish this using pretty much the same code - but I'm hoping to learn something here. So how would you handle this task?
Thanks & Cheers, sprain
Pretty easily - if an ID of an existing item (which the user is authorised to edit) is supplied in the query string, then it's an edit operation.
If no ID is supplied in the query string, it's a create operation.
The fields are pre-populated based on the existing values from the database if it's an edit operation, or based on default values or empty strings if it's a create operation.
The way I see it is that reusing identical markup for form between create/edit works for some cases, but not for all. I find that forms -- though they may map to the same database table -- are really defined by their context. For example, if you had a 'users' table, you might have a 'create' form with username, email, password, but after that user exists you want them to retain their identity on their site, so the username field would not appear in an 'edit' context. I'm classically a PHP developer, but I have come to appreciate the approach that Django takes, where you create a model (table) that defines the basic validation for each field and you can create as many forms as you that build off of, or modify/extend from that definition. If you're writing from scratch, you'll probably find it practical to make your validation methods very portable and/or find ways to make your form fields context-sensitive.
That's the way I always do it now. Are you using an MVC system at all? I use one controller with two different actions (urls = person/new + person/edit/xxxx_id).
the code is then something like:
function new()
errors = []
if (get)
data = blank_record()
elseif (post)
data = posted_data
if (create(data))
redirect_to_listing()
else
errors = describe_errors
show_form(data, errors)
function edit()
errors = []
if (get)
data = get_from_db(id)
elseif (post)
data = posted_data
if (save())
redirect_to_listing()
else
errors = describe_errors
show_form(data, errors)
Note that once it gets to the form there's always an object called data that the form can render, it may be blank, from the db, or posted data. Either way it should always be the same format.
The reason I split new and edit is that I find that often enough they are actually quite different in their behaviours and the load and save steps.
I guess this is not the right answer but it might be interesting for you anyway.
There is an orm project called doctrine:
http://www.doctrine-project.org/projects/orm/1.2/docs/en
// User Id might be an existing id, an wrong id, or even empty:
$user_id = 4;
$user_id = null;
// Fetch the user from the database if possible
$user = Doctrine::getTable('Model_User')->find($user_id);
// If there was no record create a new one
if ( $user === false )
$user = new Model_User();
// Change some data
$user->title = $newValue;
// Perform an update or an insert:
$user->save();
As you see you don't have to care about sql.
Doctrine does that for you and your code becomes easier to read and to debug.
Yes, that's the only acceptable solution.
Here is a little example of CRUD application which store the input form in a template:
<?
mysql_connect();
mysql_select_db("new");
$table = "test";
if($_SERVER['REQUEST_METHOD']=='POST') { //form handler part:
$name = mysql_real_escape_string($_POST['name']);
if ($id = intval($_POST['id'])) {
$query="UPDATE $table SET name='$name' WHERE id=$id";
} else {
$query="INSERT INTO $table SET name='$name'";
}
mysql_query($query) or trigger_error(mysql_error()." in ".$query);
header("Location: http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']);
exit;
}
if (!isset($_GET['id'])) { //listing part:
$LIST=array();
$query="SELECT * FROM $table";
$res=mysql_query($query);
while($row=mysql_fetch_assoc($res)) $LIST[]=$row;
include 'list.php';
} else { // form displaying part:
if ($id=intval($_GET['id'])) {
$query="SELECT * FROM $table WHERE id=$id";
$res=mysql_query($query);
$row=mysql_fetch_assoc($res);
foreach ($row as $k => $v) $row[$k]=htmlspecialchars($v);
} else {
$row['name']='';
$row['id']=0;
}
include 'form.php';
}
?>
form.php
<form method="POST">
<input type="text" name="name" value="<?=$row['name']?>"><br>
<input type="hidden" name="id" value="<?=$row['id']?>">
<input type="submit"><br>
Return to the list
</form>
list.php
Add item
<? foreach ($LIST as $row): ?>
<li><?=$row['name']?>
<? endforeach ?>
Of course, some fancy form constructor, like HTML_QuickForm2 coud be used instead of plain HTML template - you know its constant programmer's hunger not to repeat himself, even in naming an HTML field, field value and error key :)
But personally I prefer plain HTML.

Categories