php array_map is not mapping arrays correctly - php

I am fetching data from db.I am looping over the sql query and array_map() to get proper value.
$CompleteData = array();
foreach ( $Details as $d ) {
$q = "SELECT "
. "`log`.`id` AS 'id', "
. "DATE_FORMAT( `log`.`timestamp`, '%d %b %Y %h:%i:%s %p' ) AS 'timestamp', "
. "`log`.`Author` AS 'Author', "
. "`log`.`message` AS 'message', "
. "`log`.`bookname` AS 'bookname' "
. "FROM `log` "
. "WHERE `log`.`detailId` = '" . $d . "' "
. "ORDER BY `log`.`timestamp` DESC, `log`.`id` DESC";
$qr = mysql_query($q, $sql);
for ($i = 0; $i < mysql_num_rows($qr); ++$i) {
$LogId[$i] = mysql_result($qr, $i, 'id');
$LogTimestamp[$i] = mysql_result($qr, $i, 'timestamp');
$LogAuthor[$i] = mysql_result($qr, $i, 'Author');
$LogMessage[$i] = mysql_result($qr, $i, 'shortmessage');
$Logbookname[$i] = mysql_result($qr, $i, 'bookname');
}
$CompleteData[$d] = array_map(null, $LogId, $LogTimestamp, $LogAuthor, $LogMessage, $Logbookname);
}
Here array_map is not mapping data as desired and the output is collapsed.
Log table in DB:
Desired Output:
But with array_map(null,array1,arrar3..) the output is like below
It is combining 1st array with 2nd array and so on.
Can you pls tell am I doing wrong with array map?

I think you are doing it really wrong.
First I would like to inform you that mysql_ functions are deprecated and it's better starting looking for PDO, mysqli_ functions or MySQLi class and, of course, prepared statements.
What you are trying to do can be simplified as follows:
$query = "SELECT "
. "`log`.`id` AS 'id', "
. "DATE_FORMAT( `log`.`timestamp`, '%d %b %Y %h:%i:%s %p' ) AS 'timestamp', "
. "`log`.`Author` AS 'Author', "
. "`log`.`message` AS 'message', "
. "`log`.`bookname` AS 'bookname' "
. "FROM `log` "
. "WHERE `log`.`detailId` IN ('" . implode("', '", $Details) . "') "
. "ORDER BY `log`.`timestamp` DESC, `log`.`id` DESC";
$stmt = mysql_query($query);
$CompleteData = array();
while ($row = mysql_fetch_array($stmt)) {
if (!isset($CompleteData[$row['detailedId']])) {
$CompleteData[$row['detailedId']] = array($row);
} else {
$CompleteData[$row['detailedId']][] = $row;
}
}
Why is better this way?
You are executing a single query to get the info for all the logs
The complexity of the code is smaller so the execution will be faster
The code is more readable and easy to understand
Later edit:
If your $Details variable is an array of objects you can use array_map to get only the info you need to use in the query:
$detailsIds = array_map(function ($item) {
return $item->detailsId;
}, $Details);
having the details ids you can use the array to create the where statement:
"WHERE `log`.`detailId` IN ('" . implode("', '", $detailsIds) . "')

I think an associative array will format your response with the columns without the need to use array map.
Associative array

Related

PHP: How to pass multiple values to SELECT query

I am new to PHP and hope someone can help me with this.
I currently use the below lines to retrieve a value from a db and to output it as an array with the item's ID and value which works as intended.
Now I would need to do the same for multiple items so my input ($tID) would be an array containing several IDs instead of just a single ID and I would need the query to do an OR search for each of these IDs.
I was thinking of using a foreach loop for this to append " OR " to each of the IDs but am not sure if this is the right way to go - I know the below is not working, just wanted to show my thoughts here.
Can someone help me with this and tell me how to best approach this ?
My current PHP:
$content = "";
$languageFrm = $_POST["languageFrm"];
$tID = $_POST["tID"];
$stmt = $conn->prepare("SELECT tID, " . $languageFrm . " FROM TranslationsMain WHERE tID = ? ORDER BY sortOrder, " . $languageFrm);
$stmt->bind_param("s", $tID);
$stmt->execute();
$result = $stmt->get_result();
while($arr = $result->fetch_assoc()){
$content[] = array("ID" => $arr["tID"], "translation" => $arr[$languageFrm]);
}
My thought:
foreach($tID as $ID){
$ID . " OR ";
}
Many thanks for any help,
Mike
There are two approaches, assuming $tID is an array of IDs
Using MySQL IN() clause
This will work also when $tID is not an array, but a single scalar value.
$tID = array_map('intval', (array)$tID); // prevent SQLInjection
if(!empty($tID)) {
$query .= ' WHERE tID IN(' . implode(',', $tId) . ')';
} else {
$query .= ' WHERE 0 = 1';
}
Using OR clause, as you suggested
A bit more complicated scenario.
$conds = array();
foreach($tID as $ID) {
$conds[] = 'tID = ' . intval($ID);
}
if(!empty($conds)) {
$query .= ' WHERE (' . implode(' OR ', $conds) . ')';
} else {
$query .= ' WHERE 0 = 1';
}
As per above conditions you can try with implode();
implode($tID,' OR ');
You can also use IN condition instead of OR something like this.
implode($tID,' , ');

PHP MySQL large quantity of queries being passed,

I have a PHP script that is passing large quantities of queries to a DB very quickly. Does a MySQL DB queue the queries as they come in if it can't process them at the same speed they are being passed, or do they get lost?
My program has written and passed syntactically correct queries to the DB, but the DB is very far behind in terms of information contained in tables and number of tables.
Some example code (I am slightly new to PHP, so my code/coding style may be horrifying):
//If table has one primary key
$val = $tblColPkArray[0];
$pkInsert = ", PRIMARY KEY (". $val['COLUMN_NAME'] .")";
$pkColName = $val['COLUMN_NAME'];
$string = ltrim($string, ",");
$oneCreateTableQuery = $beginning . $string . $pkInsert . $end;
echo $oneCreateTableQuery . "\n";
$newLink->query($oneCreateTableQuery);
$pkValuesInOld = "SELECT " . $pkColName . " FROM " . $tables . ";";
$pkValsResult = $link->query($pkValuesInOld);
while($pkValues = $pkValsResult->fetch(PDO::FETCH_ASSOC))
{
$pkRowValuesQuery = "SELECT * FROM " . $tables . " WHERE " . $pkColName . " = '" . $pkValues[$pkColName] . "';";
echo $pkRowValuesQuery . "\n";
$valsOfPkInOldTable = $link->query($pkRowValuesQuery);
while($pkVals = $valsOfPkInOldTable->fetch(PDO::FETCH_ASSOC))
{
//var_dump($ckVals);
$insertBeginning = "INSERT INTO " . $tables . "(";
$insertValuesSection = ") VALUES (";
$insertEnd = ");";
$keys = "";
$rowValues = "";
foreach($pkVals as $key => $value)
{
$keys = $keys . ", " . $key;
$rowValues = $rowValues . ", '" . $value . "'";
}
$insertStatement = $insertBeginning . ltrim($keys, ",") . $insertValuesSection . ltrim($rowValues, ",") . $insertEnd;
echo $insertStatement . "\n";
$newLink->query($insertStatement);
}//While loop: Inserting values of old table into new table via INSERT INTO statement
//unset();
} //While loop: Selecting all values from old table based on PK values per table, pass result of that query to next while loop
You can do this in a single query, instead of calling multiple insert statements.
For instance, instead of running these 3 queries,
INSERT INTO table VALUES(1, 2);
INSERT INTO table VALUES(3, 4);
INSERT INTO table VALUES(5, 6);
...
You could run this query:
INSERT INTO table VALUES(1, 2), (3, 4), (5, 6), ...;
Looks like you could do even combine the INSERT and SELECT:
INSERT INTO table (...)
SELECT ... FROM ...;
Furthermore, your nested loops look like this might work:
INSERT INTO table (...)
SELECT ... FROM ...
JOIN ...;
That would get it down to one call to ->query() and eliminate most of your code.

Displaying Expenses under each expense type using MySQL PDO

I have two tables that I am creating a list that shows all the expenses under each expense type. I have been able to get it to work except when I add the
AND WHERE expenses.pid = " . $pid
it cases a Syntax error and I can't figure out way.
The biggest thing is I need to limet the Expense Type to only show the ones that have some data to go below them
EXPENSETYPE
typeid
pid
exptype
EXPENSES
expid
pid
expdate
checktype
payee
typeid
details
amount
<?php
$pid = 6;
$sql = "SELECT expensetype.typeid, expensetype.exptype
FROM `expensetype` WHERE expensetype.pid = $pid
ORDER BY expensetype.typeid DESC";
$expensetype = $db->query($sql);
foreach($expensetype as $type) {
echo '<li>' . $type['exptype'] . '<ul>';
$sql2 = "SELECT expenses.expid, expenses.expdate, expenses.checktype, expenses.payee, expenses.details, expenses.amount
FROM `expenses` WHERE `expenses`.typeid = " . $type['typeid'] . "AND WHERE expenses.pid = " . $pid ;
$expenses = $db->query($sql2);
foreach($expenses as $exp) {
echo '<li>' . $exp['expdate'] . ' ' . $exp['checktype'] . ' ' . $exp['expdate'] . ' ' . $exp['payee'] . ' ' . $exp['details'] .' ' . $exp['amount'] .'</li>';
}
echo '</ul></li>';
}
?>
Try this SQL statement instead of making two of them :
SELECT `expensetype`.`typeid`, `expensetype.exptype`, `expenses`.`expid`,
`expenses`.`expdate`, `expenses`.`checktype`, `expenses`.`payee`,
`expenses`.`details`, `expenses`.`amount`
FROM `expensetype` INNER JOIN `expenses` ON
`expensetype`.`typeid` = `expense`.`typeid`
WHERE (...)
Also, you cannot use two WHERE in a SQL statement, only use AND.

How can I get the number of rows in a MySQL table with PHP?

Why is my code returning a 500 Internal Server error on the line $result = mysql_query("SELECT * FROM institutions"); Am I doing something horrifically wrong? All I am trying to do is count the number of rows in a MySQL table (called 'institutions') after I have just added a row to that table.
$institution_sql = "
INSERT INTO `institutions`
(`InstitutionName`, `HeaderPictureID`, `Description`, `DevicesInfo`, `DoingInfo`, `FacebookPage`, `Location`, `TwitterHandle`, `Website`, `CreatedAt`)
VALUES
(" . nz($_POST['TempInstitutionName']) . ", 74, 'N/A', 'N/A', 'N/A', 'N/A', 'On the Internet', 'N/A', 'N/A', NOW())
";
$mysqli->query($institution_sql);
if ($mysqli->errno) {
$dbreturn['status'] = "PASSWORD_FAILURE";
} else {
$dbreturn['status'] = "EXEC_SUCCESS";
$result = mysql_query("SELECT * FROM institutions");
$rows = mysql_num_rows($result);
echo "There are " . $rows . " rows in my table.";
$insert_sql = "
INSERT INTO `users`
(`Handle`, `Email`, `FirstName`, `LastName`, `InstitutionID`, `TempInstitutionName`, `TwitterHandle`, `ProfilePictureID`, `HeaderPictureID`, `AccountType`, `CreatedAt`)
VALUES
(" . nz($_POST['Handle']) . ", " . nz($_POST['Email']) . ", " . nz($_POST['FirstName']) . ", " . nz($_POST['LastName']) . ", $num_rows, " . nz($_POST['TempInstitutionName']) . ", " . nz($_POST['TwitterHandle']) . ", " . nz('75') . ", " . nz('74') . ", " . nz($_POST['AccountType']) . ",NOW())
";
$mysqli->query($insert_sql);
if ($mysqli->errno) {
$dbreturn['status'] = "EXEC_FAILURE";
} else {
$dbreturn['status'] = "EXEC_SUCCESS";
$insertid = $mysqli->insert_id;
$password_sql = "
INSERT INTO `passwords`
(`UserID`)
VALUES
('$insertid')
";
$mysqli->query($password_sql);
if ($mysqli->errno) {
$dbreturn['status'] = "PASSWORD_FAILURE";
} else {
$dbreturn['status'] = "EXEC_SUCCESS";
}
} //todo: use a transaction here
}
your problem is that you mixing MYSQLI with MYSQL
rewrite your code using mysqli
$result = $mysqli->query("SELECT * FROM institutions");
$rows = $result->num_rows ;
// and so on ...
you are connecting via mysqli and then you use mysql in your code.
$result = mysql_query("SELECT count(*) FROM institutions");
This will directly return the number of rows.
This link can detail you
http://dev.mysql.com/doc/refman/5.1/en/counting-rows.html
Use
$result = $mysqli->query($institution_sql);
$result->num_rows;
Or for plain old mysql
$result = mysql_query($institution_sql);
mysql_num_rows($result);
Try this:
$result = mysql_query("SELECT count(*) FROM institutions");
MySQL documentation: http://dev.mysql.com/doc/refman/5.0/en/select.html
Also this: http://www.w3schools.com/sql/sql_func_count.asp
SQL COUNT(*) Syntax
The COUNT(*) function returns the number of records in a table:
...also, that should be:
VALUES
('" . nz($_POST['TempInstitutionName']) . "', 74
Note the single quotes [unless the 'nz' function takes care of that].

Pass set of array into MySQL query as parameters

what am trying to do here is get data from mysql generated checkboxes. The check boxes data are in array . So for all the check boxes selected I want to use each as a parameter in a query to get more info from another databastablee.
Sample Code Below
if (isset($_POST['submitCourseCode'])) {
//GET ARRAY FROM DATABASE GENERATED CHECKBOXES
$aElective = $_POST['electiveModules'];
foreach($aElective as $snode) {
echo "$snode <br />";
}
//PASSING EACH DATA FROM ARRAY INTO QUERY
$Query = "SELECT ID,title,credits
FROM module
WHERE ID IN('" . implode("', '", $aElective) ."')";
$Result = mysql_query($Query)
or die ("Query failed: " . mysql_error() . " Actual query: " . $Query);
while ($Row = mysql_fetch_array($Result)) {
$id = htmlentities($Row['ID']);
$title = htmlentities($Row['title']);
$credits = $Row['credits'];
echo "<ul>" . $id . " " . $title . " " . $credits . "</ul>";
}
}
var_dump($Query);
var_dump($Result);
var_dump($Row);
Screenshot of my result
Am guessing something is happening with my query probably because of the implode function but everything seems fine in my query.Any suggestions on what am doing wrong?
You need to trim array elements using array_map('trim', $aElective) as:
$Query = "SELECT ID,title,credits
FROM module
WHERE ID IN('" . implode("','", array_map('trim', $aElective)) ."')";
There is a problem with white spaces before your IDs in IN clause.
Try to add a str_replace() call
$Query = "SELECT ID,title,credits
FROM module
WHERE ID IN('" . str_replace(" ", "", implode("', '", $aElective)) ."')";

Categories