Better method to prevent users from changing data attributes in developer tools? - php

I am trying to find an efficient way of preventing the users from changing data attributes in a form. I need it as I use those values when making queries, and It wouldn't be great if a user changed a data-id atrribute, and the query would delete a completely different record.
I have a table called 'groups' and am listing groups from it to HTML. A data attribute holds the group id, and users can delete groups through the UI. What I have done so far is the following:
I do not display the actual group id in the html, instead I generate a random string (substring of a hash value) and that is what I insert in the data attribute as the value. Then, I create a session variable, that hold an array in which I store all the group IDs and the displayed random strings: the random string is the key, and the actual ID is the value. Later, when the AJAX call is sent, I check if the data attribute value is exists amongst the array keys, and if not, I reject the request as the random string was modified. Otherwise the key exists, and I get the value associated with it.
Here's code so far:
<?php
$groups = $user->getGroupsByAuthor();
foreach($groups as $group):
$group_id = generateGroupId();
$_SESSION['listed-group-ids'][$group_id] = $group['id'];
?>
<li>
<div class="group-image" style="background-image: url('uploads/<?php echo $group['image'] ?>')"></div>
<h4><?php echo $group['name'] ?></h4>
<small><?php echo $group['description'] ?></small>
<span class="btn-delete-group" data-group-id="<?php echo $group_id ?>"><i class="ion-close"></i></span>
</li>
<?php endforeach; ?>
And in the parser file, I check if the key exists:
if( empty($_SESSION['listed-group-ids'][$_POST['group-id']]) ){
exit('Do not try to modify values!');
}
delete the record from database...
Can it be a good way or it is unefficient? Any other experiences or methods you do?
Thanks in advance.

Related

How to enable onclick type events with the output of a mysqli_fetch_array($result))

I have been trying to get my head around how to approach this problem. I am writing a web page book library with the categories ('nodes') as MySQL records. I want to print the list of categories at each level, starting at the highest level, and then allow the user to select a category to travel deeper into the library. The PHP codes runs a saved procedure in MySQL:
//loop the result set
while ($row = mysqli_fetch_array($result)) {
if ($row[1] <> 0) {
echo $row[0];
echo "<br />";
} else { // the first row is just the heading
"</strong>Category: ";
echo $row[0];
echo " : <br />";
}}
Because there are only two test categories, this produces output:
Books :
Nature
Children's Books
However, I want to be able to create an onclick event over 'Nature' and 'Children's Books' so the user can select a category and drill down t the next level via a php function. I can convert the php output into html eg:
<?= "<p>{$row[0]}</p>" ?>
but I can't see how I can identify the row in an onclick event to pass a parameter to the function. Perhaps I need to have a completely different approach?
Add an onclick attribute to the element that calls a JavaScript function that does what you want.
<?= "<p onclick='someFunc({$row['id']})'>{$row[0]}</p>" ?>
Replace id with the actual name of the column containing the ID of the row in the table. someFunc() can use that ID to look up information in an array or object, or send an AJAX request.

How to make php dynamic queries

im trying to change query depending on what user has selected. In my case there are displayed two photos with labels pulled from data base. And depending which image is clicked i want that label to be used in query who will display items associated in database with that label. I tried using global variables, but it i didn't work for me. I cant figure out how to insert data into query after user clicked something
There is code fragment where i pull photos with labels from database, and depending on which i select i want "$modeliai_results['Modelis']" (vehicle model label) to be sent and used in another query below
<div class="eile">
<?php
echo '
<a href="standartiniskatalogas.php?page=kategorijos"/>
<img src="data:image/jpeg;base64,'.base64_encode( $modeliai_results['Nuotrauka'] ).'"/>
<div class="description">'.$modeliai_results['Marke'].' '.$modeliai_results['Modelis'].'
</div></a>';
?>
Page from second image which should execute query depending on selection from previous page:
<?php
$kategorijos_sql="SELECT * FROM kategorijos (HERE SHOULD BE ADDED: "WHERE Modelis='MODEL NAME WHICH WAS SELECTED WHEN PRESSED ON IMAGE'";
$kategorijos_query=mysqli_query($dbconnect, $kategorijos_sql);
$kategorijos_results=mysqli_fetch_assoc($kategorijos_query);
do{
echo '
<div class="eile2">
<a href="isore/isore.html">
<img src="data:image/jpeg;base64,'.base64_encode( $kategorijos_results['Nuotrauka'] ).'"/>
<div class="description">'.$kategorijos_results['Kategorija'].'</div>
</a></div>'; /* uzdaro echo*/
}
while ($kategorijos_results=mysqli_fetch_assoc($kategorijos_query))
?>
ps. Im not using any extra tools or libraries.
Selecting object
Display data associated with object
My mistake was that i concentrated on "onclick" event which would set global variable and that global variable would be used in query. Problem was that, php with java script not so big friends and would create not linkable URLs to same content. The solution was to use simple thing "$_GET". Assign $_GET to some php variable, and then use it in "href". That way when you click on any kind of object with "a href="'.$variable.'"> bla bla /a>" you get redirected to page with added tail to URL from which you can access to use in other queries
<?php
$model= $_GET['model']; //variable from URL tail
$category= $_GET['category'];
$category_sql="SELECT * FROM service WHERE Model='$model' AND Category='$category'"; //my SQL where i use variables selected from URL
$category_query=mysqli_query($dbconnect, $category_sql);
$category_results=mysqli_fetch_assoc($category_query);
do{
echo ' //print html together with php code
<tr class="data">
<td>
<a href="catalogue.php? page=service&model='.$model.'&category='.$category.'&service='.$category_results['Name'].'"> //here i make href which when clicked will pass values named with $ sign
<img src="data:image/jpeg;base64,'.base64_encode( $category_results['Image'] ).'"/>//Here i take image from data base
<br><button>'.$category_results['Name'].'</button></a>
</td>
<td> <p>'.$category_results['Description'].'</p> //I take values from data base
</td>
<td>'.$category_results['Price'].' €</td>
</tr>';
}
while ($category_results=mysqli_fetch_assoc($category_query)) //loop which cycles through all data base items
?>

Declare order to show foreach output with PHP

I am currently trying to set up a custom sortable list. Without getting into too much detail as this would become a very large post, I would like to use the PHP foreach function to show the list.
I currently have
$video_id = $row['videos'];
$res = preg_replace("/[^0-9,.]/", "",$video_id);
$exclude = explode(',', $res);
} ?>
....
<ul id="sortable2" class="connectedSortable">
<?php foreach ($video_list as $key => $item): ?>
<?php if(in_array($item['id'], $exclude)){ ?>
<li id="video-<?php echo $item['id'] ?>"><?php echo $item['id'],
$item['title'] ?></li>
<?php } ?>
<?php endforeach; ?>
</ul>
This generates a list of items from the database excluding items with an ID from an array which is also fetched from another table.
In this example, it will only show videos with the id 3,4 and 2. This is all working as expected. My issue is once I have reordered the items and refreshed the page they are loaded in numerical order. I need these to be load in the order specified (3,4 and 2 for this example).
Any help would be highly appreciated.
Thanks
I think what you are looking for is ORDER BY FIELD (MySql), this lets you order by a field in a specific way.
I need these to be load in the order specified (3,4 and 2 for this example).
Sounds like a good fit to me!
For example
SELECT * FROM table WHERE id IN(3,4,2) ORDER BY FIELD(id, 3,4,2)
This will select rows from table where the id is in the list and then order the results by id in the order they are place there, 3 then 4 then 2.
excluding items with an ID
This might cause some issue, the Field order by assumes you know at least some of the values in the field. Excluding implies that you know what you don't want but not necessarily what you do want, if that makes sense.
Maybe it's not an issue, I don't have enough information on your particular use case to determine that, so I am just mentioning it as a cautionary thing.
Thanks!

Using concatenated variables individually for database fields

I am new to stackoverflow and am after a little help. I have already tried searching for what I am about to ask, but cannot find any relevant topics, so here goes:
I have a PHP page, that gets a list of venues and it's town/city from a table within a MySQL database, which I have then concatenated to populate a dropdown, e.g. each <option> will display "[venue], [town/city]".
What I am trying to do is when the user selects one of the options, I want to store the [venue] and [town/city] as separate fields in another table within the MySQL database.
I would really appreciate any help.
More details might be needed. For instance do you need to know how to insert records on database? or are you also having trouble getting values of option tag?
But from what I understood:
First remember to set value attribute of option tags:
<option value="venue,town">venue,town</option>
Then after submitting the form, you can slice the returned string.
Assume you stored "venue,town" inside a variable named $str
$results = explode(",",$str);
$results will be an array with two elements. $results[0] contains "venue" and $results[1] contains "town"
I am not sure how much it helped but you can give more details and I'll get back
I think the best way is to put the datarecord ids (primary key value) into the value attribute of the <option> tags, then on the server side requery the data of the selected id from the database. This way your form can't be manipulated with unwanted data.
To be more clear, I would do it like in this simplified semi pseudocode:
<?php
$action = isset($_GET['action']) ? $_GET['action'] : null;
if($action == "save") {
$id = $_POST['venue'];
if(!empty($id)) {
/* fetch data belonging to $id from database and then save venue and town/city
as separate fields in another table */
}
}
/* fetch all data for the selectbox from the db and store it in $data */
?>
<form action="?action=save" method="post">
<select name="venue" size="1">
/* iterate through $data and create $id and $caption */
<option value="<?php echo $id; ?>"><?php echo $caption; ?></option>
/* iteration end */
</select>
<input type="submit" value="save" />
</form>

CakePHP: Form helper with saveMany() to edit multiple rows at once

In my view (/View/Tests/admin_edit.ctp) I want to edit multiple rows (from a different model) by pointing the form to the QsetsController and the "admin_order" action then use the saveMany($this->request->data) to update all changes.
/View/Tests/admin_edit.ctp:
echo $this->Form->create( 'Qset', array('action'=>'order', 'admin'=>1));
$n = 1;
foreach ($qsets as $qset) : ?>
<h3>Question set <?php echo $n; $n++;?></h3>
<?php echo $this->Form->input('Qset.'.$n.'.order'); ?>
<?php echo $this->Form->input('Qset.'.$n.'.id', array('type'=>'hidden') ); ?>
...
$n++;
endforeach;
echo $this->Form->end('save');
/Controller/QsetsController.php
public function admin_order() {
$data = $this->request->data; //maybe just $this->data ?
$this->Qset->saveAll($data);
$this->Session->setFlash( "Order saved.");
$this->redirect( Controller::referer() );
}
Currently, my data does not get saved (although there are no errors).
Also, only the first input echoed by the foreach loop appears with a correct order field value. Each subsequent one has no value at all.
Update:
I changed $n = 1 to $n = 0 and now the first AND second input appear with their correct order values.
update2:
The markup for the form starts like this:
<form action="/admin/qsets/order" id="QsetOrderForm" method="post" accept-charset="utf-8">
The markup for the input fields which appear correct:
<div class="input number"><label for="Qset2Order">Order</label>
<input name="data[Qset][2][order]" type="number" value="3" id="Qset2Order">
</div>
The markup that results for the empty input fields:
<div class="input number"><label for="Qset3Order">Order</label>
<input name="data[Qset][3][order]" type="number" id="Qset3Order">
</div>
Update3:
I solved the problem with the inputs not displaying correctly! Notice I was incrementing $n before echoing the the inputs, so this was creating duplicates at the end of the loop. I moved $n++ to after the inputs and now they appear correctly. Phew. Now I just need to get them to save.
Useful references:
Cake book chapter on saveMany()/saveAll()
Similar question
You reference the manual but probably haven't read it well enough :)
Quoting from the section for saveMany():
Note that we are passing numerical indices instead of usual $data
containing the Article key. When saving multiple records of same model
the records arrays should be just numerically indexed without the
model key.
So instead of $data pass $data['Qset'] to saveAll()/saveMany().
Also Controller::referer() is not a static method use $this->referer()

Categories