I'm trying to insert an array of IDs into a database table, but at the moment it only inserts 1 row when it's meant to do multiple rows. My array of IDs contains just (filmid) Does anyone know what the problem is?
$pm = "2";
$id = "2";
if($stmt1->execute())
{
$films=array();
foreach($_SESSION['products'] as $key=>$product)
{
array_push($films, $product['filmid']);
$f_id = implode(",", $films);
$stmt2 = $this->conn->prepare("INSERT INTO `filmPurchase` (`fpid`, `payid`, `filmid`, `shopid`, `custid`, `price`) VALUES (NULL, :id, :f_id, :pm, :pm, '8')");
$stmt2->bindParam('pm',$pm);
$stmt2->bindParam('id',$id);
$stmt2->bindParam('f_id',$f_id);
$stmt2->execute();
}
}
I've tried to loop over the array with:
foreach($_SESSION['products'] as $key=>$product)
{
var_dump($key);
var_dump($product);
}
This is what outputted:
int(29) array(4) { ["qty"]=> int(1) ["filmtitle"]=> string(45) "The Lord of
the Rings: The Return of the King" ["filmid"]=> string(2) "29" ["price"]=>
float(6.99) }
If your placeholder is :id and :pm (as in prepare()) then you must use :id in bindParam()
See php documentation
Related
I am trying to provide a count of certain sizes of lockers. My SQL statement is:
$sql = "SELECT Concat(`Height`, 'x', `Width`, 'x', `Depth`) as Locker, count(*) from lockers GROUP BY `Height`, `Width`, `Depth` ";
a var_dump in a loop of the rows gives me the following (many more rows are possible):
array(2) { ["Locker"]=> string(8) "15x30x45" ["count(*)"]=> int(6) }
array(2) { ["Locker"]=> string(8) "45x30x45" ["count(*)"]=> int(4) }
I want to obtain a JSON string that looks like this:
{
"SizeList": {
"15x30x45": 6
"45x30x45": 4
}
}
I have tried a lot of different methods (including converting it into an object, but I can't get the value of the size as an index. For example, I get different variations of:
[0]=> string(31) "{"Locker":"15x30x45","count(*)":6}"
[1]=> string(31) "{"Locker":"45x30x45","count(*)":4}"
Any help appreciated...
You could just manually create the object like this:
$sizeList = new stdClass();
foreach ($results as $row) {
$sizeList->{$row['Locker']} = $row['count(*)'];
}
echo json_encode(array('SizeList' => $sizeList));
I have an array called $columns :
array(3) {
[0]=>
string(8) "Food"
[1]=>
string(6) "Calories"
[2]=>
string(3) "Carbs"
}
array(3) {
[0]=>
string(8) "Food"
[1]=>
string(6) "Calories"
}
Another called values
array(5) {
[0]=>
string(4) "'Fish'"
[1]=>
string(7) "'100'"
[2]=>
string(13) "'0'"
}
array(6) {
[0]=>
string(4) "'Tatoe'"
[1]=>
string(7) "'100'"
}
I have columns in my database that represent all possible columns that an array has.The arrays could have 5,6 more or less columns depending on the item.
I have this code that is suppose to generate the sql statement in this sense :
INSERT INTO MEALS (the columns in that array) VALUES (the values in the value array)
Here is the code :
for($i = 0; $i < count($column); $i++)
{
echo("INSERT INTO 'MEALS` ($column[$i]) VALUES ($values[$i])\n");
}
The problem is for each "MEAL":
n(per column) number of sql queries will be generated.
as such :
INSERT INTO `MEALS` (Food) VALUES ('Fish')
INSERT INTO `MEALS` (Calory) VALUES ('100')
INSERT INTO `MEALS` (Carbs) VALUES ('0')
Instead of it all being on the same query.
INSERT INTO MEALS (Food,Calory,Carbs) VALUES ('Fish','100','0')
So if i insert in the database, 3 rows will be created.
I know i am missing the logic, any help is appreciated
Why aren't you genererating the two parts of your query (1 variable for columns in insert and 1 variable for values) inside your array loop?
Once your loop is done, simply concatenate your strings :
$query = "INSERT INTO 'MEALS' (" . $var_column_list . ") VALUES (" . $var_values_list . ")";
$query = "insert into table(".join($colomn,','). ") values (\"".join($values,'","')."\")";
Try using variant of above according to your need
Try This....
$colums = implode(',', $array_of_colums);
$values = implode(',', $array_of_values);
$query = "INSERT INTO `tableName` (".$colums.") VALUES(".$values.") ";
I am trying to insert each answer for each question in the database. Problem is that there is a possibility that a question may have no answers, so I tried the code below but it does not insert a db row if a question has no answer, what I was trying to do is that if no answer then display the string No Answer under the Answer column for that question:
$answersql = "INSERT INTO Answer (QuestionId, Answer)
VALUES (?, ?)";
if (!$insertanswer = $mysqli->prepare($answersql)) {
// Handle errors with prepare operation here
echo __LINE__.': '.$mysqli->error;
}
if( $insert && $insertanswer)
{
$c = count($_POST['numQuestion']);
$question_ids = array();
for($i = 0; $i < $c; $i++ )
{
... //Question INSERT goes here
$questionId = $mysqli->insert_id;
$question_ids[$questionNo] = $questionId;
}
$results = $_POST['value'];
foreach($results as $id => $value)
{
$answer = $value;
$quesid = (int)$question_ids[$id];
foreach($value as $answer)
{
if($answer == '' || $answer === null){
$answer = 'No Answer';
}
$insertanswer->bind_param("is", $quesid, $answer);
$insertanswer->execute();
if ($insertanswer->errno) {
// Handle query error here
echo __LINE__.': '.$insertanswer->error;
break 7;
}
}
}
//close your statements at the end
$insertanswer->close();
}
The ['value'] comes from an input:
var $newBtn = $(("<input class='answerBtnsRow answers' type='button' style='display:%s;' onclick='btnclick(this, " + gQuestionIndex + ");' />").replace('%s', $this.is(':visible') ? 'inline-block' : 'none')).attr('name', "value[" + gQuestionIndex + "][]").attr('value', $this.val()).attr('class', $this.attr('class')).attr('id', $this.attr('id') + 'Row');
Below is the SHOW CREATE TABLE for the Answer Table:
CREATE TABLE `Answer` (
`AnswerId` int(10) NOT NULL AUTO_INCREMENT,
`QuestionId` int(10) NOT NULL,
`Answer` varchar(10) DEFAULT NULL,
PRIMARY KEY (`AnswerId`)
) ENGINE=InnoDB AUTO_INCREMENT=280 DEFAULT CHARSET=utf8
Below is a var dump where if I set question 1 to have answers B and C, question 2 to have no answers, question 3 to have answer B and question 4 to have no answer, it outputs the following from var dump:
var_dump($question_ids);
var_dump($results);
array(4) {
[1]=> int(265)
[2]=> int(266)
[3]=> int(267)
[4]=> int(268)
}
[1]=> array(2) {
[0]=> string(1) "B"
[1]=> string(1) "C"
}
[3]=> array(1) {
[0]=> string(1) "B"
}
So it outputs those set of answers in questions 1 and 3. But does not post No Answer for question 2 and 4.
If all questions had an answer as thisL
question 1: B C
question 2: A
question 3: B
question 4: A C
Then the var dump displays this in var dump:
array(4) {
[1]=> int(277)
[2]=> int(278)
[3]=> int(279)
[4]=> int(280)
}
array(4) {
[1]=> array(2) {
[0]=> string(1) "B"
[1]=> string(1) "C" }
[2]=> array(1) {
[0]=> string(1) "A"
}
[3]=> array(1)
{
[0]=> string(1) "B"
}
[4]=> array(2)
{
[0]=> string(1) "A"
[1]=> string(1) "C"
} }}
As you can see for each question is inserts the relevant answers. So the issu is if the question has no answers that it does not insert a db row and state No Answer. My question is how to include a No Answerfor each question in the db that has no answers selected in those questions?
Simply do not insert anything into Answer table when there is no answer. Rest of your solution is basically correct.
When displaying questions with answer, check if there is answer (empty select result or null in left joined column) to show and if not, show "No answer". But there is no "No answer" in database.
When your code get to $results = $_POST['value'];, $question_ids is populated with the ids of questions that must be included in the table.
My suggestion is to remove elements from this array right after including the first answer to the related question. This way, after the foreach($results as $id => $value) loop, this array will contain only questions without explicit answers. The next step is just to include these pseudo-answer "No answer" in the DB.
The relevant code for you (inserted lines are //* commented):
$notAnswered = $question_ids; //* Make a copy
$results = $_POST['value'];
foreach ($results as $id => $value) {
$answer = $value;
$quesid = (int)$question_ids[$id];
$pos = array_search($quesid, $notAnswered); //* Search for it
if ($pos !== false) //* It's in the array
array_splice($notAnswered, $pos, 1); //* Delete it from the array
foreach ($value as $answer) {
$insertanswer->bind_param("is", $quesid, $answer);
$insertanswer->execute();
if ($insertanswer->errno) {
// Handle query error here
echo __LINE__.': '.$insertanswer->error;
break 7;
}
}
}
//* Insert 'No Answer' for each question not answered
foreach ($notAnswered as $id) {
$insertanswer->bind_param('is', $id, 'No Answer');
$insertanswer->execute();
if ($insertanswer->errno) {
// Handle query error here
echo __LINE__.': '.$insertanswer->error;
break 7;
}
}
// Close your statements at the end
$insertanswer->close();
One important thing to note here: array_splice is very slow in PHP for big arrays (>100 elements). But I don't think this is the case here.
I am having trouble being able to insert QuestionId into the Answer Table.
The Question inserts with no problem, but I am trying to retrieve the QuestionId from the Question Table which is an auto increment into the Answer Table by finding the SessionId and QuestionNo that particular QuestionId belongs to. Instead it keeps displaying 0 for QuestionId when inserted into Answer Table.
Now I know the query which tries to perform the select for each QuestionId from the Question Table is correct as this has been tested. I think the problem is where I have placed my code but I am not sure?
Here are the db tables:
Question Table
QuestionId (auto) SessionId QuestionNo
4 2 1
5 2 2
6 2 3
Answer Table at moment:
AnswerId (auto) QuestionId Answer
7 0 A
8 0 C
9 0 A
10 0 B
11 0 True
What Answer Table should look like:
AnswerId (auto) QuestionId Answer
7 4 A
8 4 C
9 5 A
10 5 B
11 6 True
Below is the code:
$questionsql = "INSERT INTO Question (SessionId, QuestionNo)
VALUES (?, ?)";
if (!$insert = $mysqli->prepare($questionsql)) {
// Handle errors with prepare operation here
echo __LINE__.': '.$mysqli->error;
}
$answersql = "INSERT INTO Answer (QuestionId, Answer)
VALUES (?, ?)";
if (!$insertanswer = $mysqli->prepare($answersql)) {
// Handle errors with prepare operation here
echo __LINE__.': '.$mysqli->error;
}
//make sure both prepared statements succeeded before proceeding
if( $insert && $insertanswer)
{
$sessid = $_SESSION['id'] . ($_SESSION['initial_count'] > 1 ? $_SESSION['sessionCount'] : '');
$c = count($_POST['numQuestion']);
for($i = 0; $i < $c; $i++ )
{
$insert->bind_param("ii", $sessionid, $_POST['numQuestion'][$i]);
$insert->execute();
if ($insert->errno)
{
// Handle query error here
echo __LINE__.': '.$insert->error;
break 1;
}
}
$results = $_POST['value'];
foreach($results as $id => $value)
{
$answer = $value;
$lastID = $id;
$questionidquery = "SELECT QuestionId FROM Question WHERE (QuestionNo = ? AND SessionId = ?)";
if (!$questionidstmt = $mysqli->prepare($questionidquery)) {
// Handle errors with prepare operation here
echo __LINE__.': '.$mysqli->error;
}
// Bind parameter for statement
$questionidstmt->bind_param("ii", $lastID, $sessionId);
// Execute the statement
$questionidstmt->execute();
if ($questionidstmt->errno)
{
// Handle query error here
echo __LINE__.': '.$questionidstmt->error;
break 2;
}
// This is what matters. With MySQLi you have to bind result fields to
// variables before calling fetch()
$questionidstmt->bind_result($quesid);
// This populates $optionid
$questionidstmt->fetch();
$questionidstmt->close();
foreach($value as $answer)
{
$insertanswer->bind_param("is", $quesid, $answer);
$insertanswer->execute();
if ($insertanswer->errno) {
// Handle query error here
echo __LINE__.': '.$insertanswer->error;
break 3;
}
}
}
//close your statements at the end
$insertanswer->close();
$insert->close();
}
?>
UPDATE:
Results from var_dump($_POST);
array(8) {
["numberAnswer"]=> array(2) {
[0]=> string(1) "1"
[1]=> string(1) "1"
}
["numQuestion"]=> array(2)
{
[0]=> string(1) "1"
[1]=> string(1) "2"
}
["questionText"]=> array(2) {
[0]=> string(12) "What is 2+2?"
[1]=> string(12) "What is 4+4?"
}
["gridValues"]=> array(2) {
[0]=> string(1) "4"
[1]=> string(1) "4"
}
["reply"]=> array(2) {
[0]=> string(6) "single"
[1]=> string(6) "single"
}
["textWeight"]=> array(2) {
[0]=> string(1) "5"
[1]=> string(1) "5"
}
["submitDetails"]=> string(14) "Submit Details" ["value"]=> array(2) {
[1]=> array(1) {
[0]=> string(1) "B"
}
[2]=> array(1) {
[0]=> string(1) "D"
}
}
}
Right now your QuestionID is coming from $_POST['value'], which is probably not what you want... you need to get the automatically generated QuestionID from mysql after each question is inserted.
You can retrieve the last generated ID using $mysqli->insert_id. Do this after each call to $insert->execute();, then use those IDs when you go to insert your answers.
Edit 1:
You should be using $mysqli->insert_id, because insert_id is only valid on a connection object (yours is called $mysqli).
You also need to assign the insert_id to something. I'm having trouble following your code but I think what you want is to store question IDs in an array for later use, something like this:
$question_ids[$i] = $mysqli->insert_id
I'm at a loss for what you're trying to do after this, I guess you pull in some answers with a corresponding question number but... perhaps if you can post the output of var_dump($_POST) we will understand a bit better. In any case you will need some kind of a loop that inserts the answers for each question, and you can (hopefully) use the array $question_ids[$i] to retrieve the QuestionIDs.
Edit 2:
Here is some sample code (untested), try to get this working before getting fancy with $_POST and $_SESSION
<?php
$questions = array(
array(2, 1),
array(2, 2),
# etc
);
$answers = array(
array(A, C),
array(A, B),
);
$questionsql = "INSERT INTO Question (SessionId, QuestionNo) VALUES (?, ?)";
if (!$insert = $mysqli->prepare($questionsql)) {
die('couldn\'t prepare statement 1');
}
$answersql = "INSERT INTO Answer (QuestionId, Answer) VALUES (?, ?)";
if (!$insertanswer = $mysqli->prepare($answersql)) {
die('couldn\'t prepare statement 2');
}
$c = count($questions);
for($i = 0; $i < $c; $i++)
{
$insert->bind_param("ii", $questions[$i][0], $questions[$i][1]);
$insert->execute();
if ($insert->errno)
{
die("Error inserting question $i");
}
$lastID = $mysqli->insert_id;
foreach ($ans in $answers[$i])
{
$insertanswer->bind_param("is", $lastID, $ans);
$insertanswer->execute();
if ($insertanswer->errno) {
die("Error inserting answer to question $i");
}
}
}
$insertanswer->close();
$insert->close();
?>
I am using
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
to get all the rows of my table.
The schema is defined as "id INTEGER PRIMARY KEY, title TEXT, year INTEGER, price REAL"
A row from he results of the fetchAll is
array(4) {
[0]=>
string(1) "1"
[1]=>
string(14) "The Dark Night"
[2]=>
string(4) "2008"
[3]=>
string(5) "19.95"
}
Why are all the data types being returned as strings? I want them to be returned as defined in the schema. I understand the 'typeless' nature of SQLite, but they do define the limited data types as TEXT, INTEGER, and REAL. How can I get the data to be returned with the specified data types? I don't want to iterate through each row, and convert it with PHP - that just seems to be too slow.
The Complete Test Code as Follows:
<?
class sqlite_test {
function __construct()
{
$this->dbase_filename = "test.sqlite";
$this->init_dbase();
}
function init_dbase()
{
$this->pdo = new PDO("sqlite:".$this->dbase_filename);
}
function open_table()
{
$table = "dvds";
if ( ! ($test_to_see_if_table_exists = $this->pdo->query("SELECT 1 from $table")) ) {
$schema = "id INTEGER PRIMARY KEY, title TEXT, year INTEGER, price REAL";
$query = "CREATE TABLE $table ($schema)";
$this->pdo->exec($query);
}
return $test_to_see_if_table_exists;
}
function add_test_records()
{
$query[]='INSERT INTO dvds (id, title, year, price) VALUES (null, "The Dark Night", 2008, 19.95)';
$query[]='INSERT INTO dvds (id, title, year, price) VALUES (null, "The Wizard of Oz", 1939, 9.95)';
$query[]='INSERT INTO dvds (id, title, year, price) VALUES (null, "Jaws", 1977, 6.95)';
$this->pdo->exec( join(';', $query) );
}
function dump_test_records()
{
$query = "SELECT * FROM dvds";
if ($statement = $this->pdo->prepare($query)) {
$statement->execute();
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
echo "<pre>";
var_dump($rows);
echo "</pre>";
}
}
function main()
{
if ( ! $this->open_table() ) {
$this->add_test_records();
}
$this->dump_test_records();
}
}
$test = new sqlite_test();
$test->main();
This has nothing to do with SQLite; all records will be returned as collections of strings no matter what you use to query a database. It's just the nature of the database adapters/drivers used by PHP.
If you want the values to be of your desired types, you have to cast manually.
PHP 8.1 started returning numbers instead of strings for INTEGER fields (sqlite pdo).