PHP: Is it possible to reuse MySQL pdo objects? - php

I am allowing users to vote on content, so I need to save a user input to my database, and then get a COUNT() of the input to return back.
The voting works fine, but reading the results back always returns false. The only work around I have found is to rebuild the database connection a second time to count the votes. Is there any other way to do this?
Here is my code:
$vote = $conn->prepare($voteSQL);
$vote->execute(array(':postId'=>$voteId
, ':voterId'=>$userId
, ':voteType'=> $voteDir
,':voteType2'=> $voteDir
,':voteType3'=> $voteDir));
$tallyVotes = $conn->prepare($tallySQL);
$tallyVotes->execute(array(':postId'=>$voteId));
$updatedTally = $tallyVotes->fetch();

Related

Codeigniter Commands out of sync; you can't run this command now

I've been spent hours trying to figure out how I'm supposed to get around this error in my scenario. I'm trying to run a few queries in sequence.
I have read: codeigniter : Commands out of sync; you can't run this command now, however I am not able to update /system/database/drivers/mysqli/mysqli_result.php
I've tried:
$this->db->reset_query();
$this->db->close();
$this->db->initialize();
$this->db->reconnect();
mysqli_next_result( $this->db->conn_id );
$query->free_result();
But they either give me the same error, or different errors which I will detail in the comments of my code.
The way my code is organized- I have a make_query method that takes a bunch of search options and figures out which tables to join and fields to search based on those. Sometimes, I just want to count results, sometimes I want all of the resulting data, sometimes I just want distinct values for certain fields or to group by certain fields. So I call make_query with my options, and then decide what to select afterwards. I have also been saving my query text to report, so that users can see what query is being run.
One interesting thing I have noted is that when I have no options set (ie there are no WHERE clauses in my SQL), I do not get this error and the multiple queries are able to run with no problem!
Here is my code:
//Get rows from tblPlots based on criteria set in options array
public function get_plot_data($options=array()){
$this->db->save_queries = TRUE;
log_message('debug','before make query 1 get plot data');
$this->make_query($options,'plot');
log_message('debug','after make query 1 get plot data');
$this->db->distinct();
//Now, set select to return only requested fields
if (!empty($options['fields']) and $options['fields']!="all" ){
//Because other tables could be joined, add table name to each select
array_walk($options['fields'], function(&$value, $key) { $value = 'tblPlots.'.$value;} );
$this->db->select($options['fields']);
}
if (!empty($options['limit']) and $options['limit']>0){
$this->db->limit($options['limit'], $options['offset']);
}
//Get the resulting data
$result=$this->db->get('tblProgram')->result();
$query_text = $this->db->last_query(); //tried removing this but didn't help
log_message('debug','query text '.$query_text);
$this->db->save_queries = FALSE;
//get the number of rows
//$this->db->reset_query();
//$this->db->close();
//$this->db->initialize();
//$this->db->reconnect();
//mysqli_next_result( $this->db->conn_id );
//$this->db->free_result(); //Call to undefined method CI_DB_mysqli_driver::free_result()
//$result->free_result(); //Call to a member function free_result() on array
log_message('debug','before make query 2');
$this->make_query($options,"plot");
$this->db->select('pkProgramID');
log_message('debug','before count results');
//this is where my code errors out trying to do the next step:
$count=$this->db->count_all_results('tblProgram');
}
I'm not including the code for make_query because it is long and calls other functions, but it runs successfully the first time and outputs the SQL query I would expect. If it would be helpful, I can include that code as well.
I'm not sure how to correctly call free_result() given that the CI documentation only gives an example using query('SQL QUERY') and I am building the query using Active Record, so I'm not sure how to use free result in my scenario? Maybe that's the issue?
$query2 = $this->db->query('SELECT name FROM some_table');
$query2->free_result();
Thank you for any help!
I ended up posting on a CI forum that suggested https://www.youtube.com/watch?v=yPiBhg6r5B0 which worked! Also I ended up having to join my tables differently to avoid timeouts (I think I was having trouble because I was using AJAX to call many queries asynchronously and one of them was timing out). Hope this helps someone!

How to pass query through an Ajax request

I'm working on paginating some data with Ajax requests. When one of the page number buttons is pressed it will send a request to a separate file to generate the next page in a table.
On my main page I'll have something like:
$query = "Select * from table WHERE field = 'something' LIMIT 5";
$result = mysqli_query($con, $query);
$row = mysqli_fetch_assoc($result);
// dump results as table
When I write the script to create a new xmlhttp request object to my "paginate.php" file, how can I carry this same query over to the file since it may dynamically change based on user input?
I was thinking of just passing the whole query string as a function parameter via a POST request, but am wondering if there is a more efficient way of doing this.
I was thinking of just passing the whole query string as a function
parameter via a POST request
Definitely do not do this! It's really really bad security practice to let the browser (ie. user) run queries directly against your database. I made this mistake in early days and my site got 0wned in no time.
Your PHP file should accept parameters, validate them, then use them to run the query
1. You XHR object sends: page_number=5
2. Your PHP validates the input and dynamically builds the query:
//set page to 1 if none was provided.
$pg = isset($_POST['page_number'])? (int)$_POST['page_number']: 1;
$pg = max(1,$pg); // lowest allowed pg number is 1
Once you have the page number, and you are sure it's an integer (not some nefarious SQL command that a user sent to your server), you can use it in your query:
$size = 5; //# of results per page
$start = ($pg-1) * 5;
$query = "SELECT * from myTable WHERE field='something' LIMIT $start,$size";
Note that if the field value something comes from the user, you don't want to include it in the query directly (this goes for any user-supplied value). Instead, you should use prepared statements and parameterized queries
Resource: https://www.owasp.org/index.php/SQL_Injection

mongodb php multiple collections

A bit of weird issue - I am looking to enter data into two separate
collections (same db) and I am getting totally weird results. I am
sure it is the way I am doing this but it is the results which have me
a bit baffled.
Here is a snippet of what I am trying to accomplish:
$mynewconnection = new Mongo(); // create new mongo connection
$collectionDB = $mynewconnection->Datadb; // select db
$collectionA = $collectionDB->DataA; // select collectionA
$collectionB = $collectionDB->DataB; // select collectionB
/* Go off and chop up data and create CriteriaA/B */
$insertA = $collectionA->insert($criteriaA);
$insertB = $collectionB->insert($criteriaB);
So what I am trying accomplish is to enter part of the data set into
one collection and the other part of the dataset into another
collection. What is happening is that sometimes the data will be
entered into Both collections (as desired) and other times data will
be entered into just collectionA and yet other times data will be
entered into just collectionB.
Anyone have any ideas on what I am missing or what would be causing
this strange behavior?
When you fire a query to write something to MongoDB, it does not confirm whether the data is written to database or not. You need to see the page of php's manual for Write Concerns.
The link for the same is: http://www.php.net/manual/en/mongo.writeconcerns.php

how would I return any items in an array that do not match any $_POST results

I am writing a PHP/MySQL application that maintains a masterlist of user preferences and I've gotten myself stuck trying to remove items from that list. Currently the application generates a list of items and marks a checkbox next to the ones a user has previously selected, the user can then change their selections (either adding or removing checkmarks) and resubmit. The form only submits supplyid's for items the user has checked.
I have the list sorted so that unmarked selections are shown first and I've got the code to insert/update items in the database working, but I'm having problems figuring out how to delete the items the user has unchecked (and which now do not return supplyid's).
At this point, I've written a MySQL query to return only results that were previously included on the list (as those are the only ones which could need to be removed.) What I need are the items in the array returned by the query that do not match any $_POST results. I've been successfully comparing the array to the $_POST results of items previously included, but I can see my logic is wrong in the part where I'm trying to get back the results which don't match. While I'm able to view which items match, I'm not sure how to eliminate them as possibilities. Am I going about this in the wrong way entirely?
$iduser = $_SESSION["iduser"];
$possibleresults = $_POST["possibleresults"];
$sql_onlist = "select supply.idsupply from supply, kit
where supply.class = 'basic'
and kit.iduser = '".$iduser."'
and supply.idsupply = kit.idsupply";
$possible_delete = $connection->query($sql_onlist);
//for each record we know is already in the database, check to make sure it has been checked, otherwise delete
for ($i=0; $i<$possibleresults; $i++) {
$count = 0;
$item_delete = $possible_delete->fetch_assoc();
if ($_POST['item_'.$i.'']) {
$idsupply = $connection->real_escape_string($_POST['item_'.$i.'']);
//if there is a match, increase the counter
if ($idsupply == $item_delete["idsupply"]) {
$count++;
//this does successfully return a count = 1 - idsupply = number for all rows which should have matches
echo "count = ". $count . " - idsupply = " . $idsupply;
}
//this statement doesn't work because it doesn't know which idsupply
if ($count < 1) {
$idsupply = $item_delete["idsupply"];
$sql_delete = "delete from kit
where idsupply = '".$idsupply."'
and iduser = '".$iduser."'";
$result_delete = $connection->query($sql_delete);
}
}
There are a couple different solutions to this problem; here's a few strategies I've used before.
-- Delete all the entries every time you update a user's preferences
Not terribly efficient, but it's easy to implement. Every time they save their preferences, first set all the values in the database to whatever the 'unchecked' value is. Then, save their preferences as normal.
-- Give unchecked boxes a value
If you put a hidden input element right before a checkbox and give it the same name as the checkbox, the hidden element will submit its value whenever the checkbox is not checked. E.g.,
<input type='hidden' name='box1' value='off' />
<input type='checkbox' name='box1' value='on' />
This will let you know which IDs to unset in the database.
There may be a more database-oriented solution as well, but I'd have to know more about your structure to suggest anything.
Holy moly, what a tangled mess... kinda painted yourself into a corner eh? No worries it happens to all of us. :)
So I think that once you have a truly working algorithm the code just kinda comes together around it. So lets analyze your problem:
Your main objective is to store a users settings.
You are using a form and checkboxes to both display the current settings and to allow the user to change their current settings. This is graceful enough.
Generate a list of the users POSTed settings (aka get the new settings from the POST array) and store those results in a dedicated data container like an array or a linked list.
Once you have a list of new settings, you need to use that list as a map to set/unset various fields within a database table.
Get a list of ALL of the users saved settings from the database storing that in a different data container
Do a case by case comparison, seeing if the variables match, record the results in yet another data container, or do an immediate write to the database.
Present the user with a human readable result of their operation.
NOTE: Incidentally, you probably already know this, but if you use isset($_POST['mychkbox1']) and it returns a positive value, then that checkbox was checked. If isset() returns false, the checkbox was not set, or does not exist. Like I said you probably already knew that, but I figured I toss it in there.
Good luck
h
I didn't quite understand your code, but I think you need something like this
$to_keep = array();
for ( $i=1 ; $i < 10 ; $i++ ) {
// Add ids of elements we want to save
$to_keep[] = $i;
}
if ($to_keep) {
mysql_query("DELETE FROM table WHERE id NOT IN (". implode(',', $to_delete) . ")");
}

PHP IF statement not taking variable into account!

I have a tabled view in a while loop, where a user can view information on books.
For example, book ISBN, book name, read status...
Basically, when the user sets their 'readstatus' to 'complete' I want that specific table row to become grey! The logic is very straight forward, however I can't get my IF statement to recognise this:
if ($readstatus == 'complete') {
echo '<tr class="completed">';
}
else if ($readstatus != 'complete') {
echo '<tr class="reading">';
}
I'm obviously doing something wrong here, table content to change if the value of 'readstatus' = 'complete', if not, then output is the default
Why are you using $_GET? Does this information come from an HTML form or a URL etc... ?
I suspect you meant to change $readstatus = $_GET['readstatus']; to $readstatus = $row['readstatus'];.
$_GET is an aray of GET parameters which come from the query string.
$row is a row in your database, so if the information is in the database - which I suspect it is - you want to use $row instead of $_GET.
Try changing $readstatus = $_GET['readstatus']; to $readstatus = $row['readstatus'];
The $_GET function relies on the value being contained in the query string of the URL, and it has nothing to do with the database. I have a hunch you're trying to get the value from the database here and you're using the wrong function to do it.
$_GET['readstatus'] says the value is coming from the browser.
$row['readstatus'] says the value is coming from the database.
You need to decide which should take precedence-- probably the $_GET['readstatus']` because it's what the user wants to change. If that's the case, you need to update your database with the new readstatus before you requery the db for the dataset.

Categories