UPDATE:
I get array values from $_POST['changed'].
The array structure looks like this:
Array
(
[0] => Array
(
[recid] => 1
[nachname] => Müller7777
)
[1] => Array
(
[recid] => 3
[vorname] => Maria123
)
)
I get on line #3 this error: Fatal error: Function name must be a string
$uarr=array();
foreach ($_POST['changed'] as $a) {
list($x,$k)=array_keys($a);
list($y,$v)=array_values($a);
$uarr[$y][]="$k='$v'";
}
foreach ($uarr as $k=>$v) {
$sql = "";
$sql .="UPDATE tbl SET ".join(",",$v)." WHERE recid=$k";
// send UPDATE ...
}
file_put_contents('filename2.txt', $sql);
Before I do the final database UPDATE I want to check if the created array does its job. Thats why I want to write the $sql variable first into a txt-file.
------------------------------------------------
SOLUTION:
checking if $_POST['changed'] == null is the final answer for this question.
if ($_POST['changed'] == null) {
} else {
$uarr=array();
$b = $_POST['changed'];
foreach ($b as $a) {
list($x,$k)=array_keys($a);
list($y,$v)=array_values($a);
// $x contains the `recid` key
// $y ... value
$uarr[$y][]="$k='$v'";
}
foreach ($uarr as $k=>$v) {
$sql = "";
$sql .="UPDATE tbl SET ".join(",",$v)." WHERE recid=$k";
// send UPDATE ...
}
file_put_contents('filename2.txt', $sql);
}
Before you run the individual UPDATE statements - yes, for each recid value you should send one statement - you could first collect all the affected values for each recid in an associative array like
$uarr=array();
foreach ($_POST['changed'] as $a) {
list($x,$k)=array_keys($a);
list($y,$v)=array_values($a);
// $x contains the `recid` key
// $y ... value
$uarr[$y][]="$k='$v'";
}
and then do another loop like
foreach ($uarr as $k=>$v) {
$sql="UPDATE tbl SET ".join(",",$v)." WHERE recid=$k";
// send UPDATE ...
}
But, of course, this will only work correctly if the $_POST('changed') array adheres to the described format and order. And, finally, so far there is nothing in this code to protect you from SQL injection.
Try to do it like this:
$BigArray = $_POST['changed'];
$LengthOfArray = sizeof($BigArray);
for ($i = 0; $i < $LengthOfArray ; $i++) {
$SubArray = $BigArray[$i];
// Call the update/insert here
// $SubArray['recid'] is the ID
// $SubArray['vorname'] is the name
}
Related
I'm trying to add an <hr> tag between lines when a new name is encountered.
$conn = new mysqli("localhost", "root", "", "test");
$rs = $conn->query("SELECT * FROM usuarios");
$info = [];
$i = 0;
while($rows = $rs->fetch_array()) {
$info[$i]["pass"] = $rows["pass"];
$info[$i]["name"] = $rows["name_real"];
$i++;
}
// I want to print a line just after the last duplicated value
for($i = 0; $i < count($info) - 1; $i++) {
if($info[$i]["name"] !== $info[$i +1]["name"] && // some duplicate condition) {
$info[$i]["line"] = "<hr>";
};
}
This is the structure of my info array build from the resultset.
Array
(
[0] => Array
(
[pass] => 12
[name] => Martin
)
[1] => Array
(
[pass] => 20
[name] => Martin
)
[2] => Array
(
[pass] => 2
[name] => Martin
)
[3] => Array
(
[pass] => 2
[name] => Alberto
)
)
My desired result would be something like:
<p>Martin<p>
<p>Martin<p>
<p>Martin<p>
<hr>
<p>Alberto<p>
If you don't care what the duplicate names are or how many duplicates exist, and you just want to see whether or not there are any, it looks like it could be simpler code than some of the possible duplicate answers.
Get the names
$names = array_column($array, 'name');
Then check if the full list of names is equal to the unique list.
$has_duplicates = $names != array_unique($names);
Disclaimer: This answer looks odd now. It was provided for Revision 1 of the question. I seem to have misunderstood the question somewhat, and then Revision 2 transformed it to the extent that this answer no longer applies at all. Still, I think it's a useful way to do the thing that it seemed was trying to be done at first.
This solution would be handy:
$result = array();
$names = array_count_values(array_column($source, 'name'));
foreach($names as $key=>$val) {
$result[$key] = ($val == 1 ? false : true);
}
This can be achieved with just one loop. First, use your mysqli query to order the resultset by name_real. (If you are only going to use name_real, you can change the SELECT clause to reflect this. I have shown this in the commented query.) Then write a condition that checks for a new/unique name_real -- if so, echo <hr>.
Code: (Demo)
//$rs = $conn->query("SELECT `name_real` FROM usuarios ORDER BY `name_real`;");
$rs=[
['pass'=>2,'name_real'=>'Alberto'],
['pass'=>12,'name_real'=>'Martin'],
['pass'=>20,'name_real'=>'Martin'],
['pass'=>2,'name_real'=>'Martin']
];
$prev=NULL;
//while($rows = $rs->fetch_array()) {
foreach($rs as $rows){
if($prev && $rows['name_real']!=$prev){ // if not first iteration, and new name_real
echo "<hr>";
}
echo "<p>{$rows['name_real']}</p>";
$prev=$rows['name_real']; // preserve this value for next iteration's check
}
Output:
<p>Alberto</p>
<hr>
<p>Martin</p>
<p>Martin</p>
<p>Martin</p>
I have an "Events" table in MySQL :
EventsDate('id','event','start_date','end_date')
I'd like to check if multiple events have the same start date to show it differently in my HTML template.
My SQL request is :
SELECT * FROM EVENTSDATE where event='$id' and start_date>='$today' order by start_date asc
Now my foreach :
foreach ($upcomingDates as $value) { //$upcoming is the array with my sql request
}
How can I say : "if you find two rows with the same start_date, echo something"
I have a slightly different approach.
// Array to contain all values
$container = array();
// Loop through your existing array
foreach ($upcomingDates as $key => $value) {
// Check if the value is already in the container array
// If this is the case, its a duplicate.
if (array_key_exists($value['start_date'], $container)) {
$container[$value['start_date']]++;
echo $value.' is a duplicate with key '.$key;
}
// Add each value to the array
$container[$value['start_date']] = 1;
}
Another method is to use array_count_values()
foreach(array_count_values($upcomingDates) as $value => $c) {
if ($c > 1) {
echo $value.' is a duplicate';
}
}
Note that the second option won't work if your $upcomingDates is an array of arrays.
You can make an empty array before the for loop, and add each value in as a key. Then, on each iteration you can check that array for the key, like so:
$values = [];
foreach ($upcomingDates as $value) { //$upcoming is the array with my sql request
if(isset($values[$value])) //duplicate value found
//do something here
$values[$value] = 1;
}
Since you're ordering your events by start_date:
for ($i = 0, $length = count($upcomingDates); $i < $length; $i++) {
$date = $upcomingDates[$i];
if (isset($upcomingDates[$i + 1]) &&
$upcomingDates[$i + 1]['start_date'] == $date['state_date']) {
echo 'this and the next date are equal';
}
}
Try out GROUP BY
look here: GROUP BY
if you want to find duplicates, then you can directly get it from database
ex.
SELECT * FROM EVENTSDATE where event='$id' and start_date>='$today' GROUP BY start_date having count(start_date) > 1 order by start_date asc
or you can find duplicates from resulting array
return only duplicated entries from an array
Im using this DOMXpath query to retrieve some columns from another page.
$html = file_get_contents("http://localhost:8888/stockPrices.php");
libxml_use_internal_errors(true);
$doc = new \DOMDocument();
if($doc->loadHTML($html))
{
$result = new \DOMDocument();
$result->formatOutput = true;
$table = $result->appendChild($result->createElement("table"));
$thead = $table->appendChild($result->createElement("thead"));
$tbody = $table->appendChild($result->createElement("tbody"));
$table->setAttribute('class', 'table table-hover');
$xpath = new \DOMXPath($doc);
$newRow = $thead->appendChild($result->createElement("tr"));
foreach($xpath->query("//table[#id='kurstabell']/thead/tr/th[position()=2 or position()=3 or position()=8 or position()=9 or position()=10]") as $header)
{
$newRow->appendChild($result->createElement("th", trim($header->nodeValue)));
}
foreach($xpath->query("//table[#id='kurstabell']/tbody/tr") as $row)
{
$newRow = $tbody->appendChild($result->createElement("tr"));
foreach($xpath->query("./td[position()=2 or position()=3 or position()=8 or position()=9 or position()=10]", $row) as $cell)
{
$newRow->appendChild($result->createElement("td", trim(htmlentities($cell->nodeValue))));
}
}
echo $result->saveXML($result->documentElement);
}
This generates four columns, aktier, senaste, högst, lägst and omsatt. But i dont know how to insert this to a MySQL table. Im thinking to first generate a array of the result, like:
Array
(
[1] => stdClass Object
(
[aktie] => AAK AB
[senaste] => 634,50
[högst] => 638,50
[lägst] => 622,50
[omsatt] => 32 094 048
)
[2] => stdClass Object
(
[aktie] => ABB Ltd
[senaste] => 162,80
[högst] => 163,30
[lägst] => 161,90
[omsatt] => 167 481 268
)
(you get the hang of it..)
)
According to this image:
And then loop the array into the table. Something like this?
$sql = "INSERT INTO stock_list (`aktie`, `senaste`, `högst`, `lägst`, `omsatt`, `timestamp`) VALUES
(:aktie, :senaste, :högst, :lägst, :omsatt)";
$query = $database->prepare($sql);
foreach($data as $stock){
$query->execute(array(':aktie' => $stock->stock,
':senaste' => $stock->prevclose,
':högst' => $stock->high,
':lägst' => $stock->low,
':omsatt' => $stock->volume
));
}
My question:
How do i populate the array with data?
How do i loop the result in a mysql query?
Don't know if this is a work around. But it is currently doing what I'm asking for.
// build query...
$sql = "INSERT INTO stocks";
// columns to insert into...
$sql .="(`name`, `closing`, `high`, `low`, `turn`, `timestamp`)";
// implode values of $array...
// notice array_chunk, this functions splits a big array into multi.
$str = NULL;
foreach (array_chunk($a, 5) as $row) {
$str .= '("'. implode('","',$row).'",NOW()),';
}
// Remove last ',' (comma) from string
// We added commas in the previous step
$str = rtrim($str,',');
$sql .= 'VALUES '. $str ;
// execute query...
$app = new Connection();
$query = $app->getConnection()->prepare($sql);
$query->execute();
if ($query->rowCount() <= 0) {
echo "Something went wrong.";
return false;
}
return true;
My guess is that what you really want is something along the lines of:
$query = 'INSERT INTO stock_list
(`aktie`, `senaste`, `högst`, `lägst`, `omsatt`, `timestamp`)
VALUES
(:aktie, :senaste, :högst, :lägst, :omsatt, NOW())';
$stmt = $app->getConnection()->prepare($query);
foreach ($data as $stock) {
$stmt->execute(
[
':aktie' => $stock->aktie,
':senaste' => $stock->senaste,
':högst' => $stock->{'högst'},
':lägst' => $stock->{'lägst'},
':omsatt' => $stock->omsatt,
]
);
$stmt->closeCursor();//might be required depending on DB driver, not for MySQL, though
}
Note that I call NOW() in the query string, and I don't bind that SQL function call to the parameters I execute the prepared statement with. All in all though, a timestamp field is best set by the DB itself (with a DEFAULT CURRENT_TIMESTAMP in the field definition). Then you can just leave the timestamp field out of your INSERT query, and it'll be set correctly for you.
I've also changed the way you're using the objects stock. From the var_dump I can see the properties aren't called stock, high, low and all that. The problem is, some of these property names (lägst for example) are a bit dodgy. You'll probably have to access those using a string, which can be done, like I did, by writing $objVar->{'property name as string'}.
If I were you, though, I'd look into ways of changing what $data actually looks like, and change the property names if at all possible.
I would like to grab the values of several textarea fields and save them to the database. For now I have four of each with different values and I want to batch save these values, the textarea fields are:
<textarea name="compedia[]"></textarea>
<textarea name="specification[]"></textarea>
and the save function:
function saveCOA(){
$labref=$this->uri->segment(3);
$data= $this->input->post('compedia');
$data1= $this->input->post('specification');
$compedia=array(
'labref'=>$labref, //NDQA201303001
'compedia'=>$data,
'specification'=>$data1
);
foreach ($compedia as $value) {
$this->db->insert('coa_body',$value);
}
}
When I print_r($value) it returns :
NDQA201303001
Array ( [0] => Alphy [1] => poxy [2] => alphy [3] => poxy )
Array ( [0] => poxy [1] => alphy [2] => poxy [3] => alphy )
and when I try to save, it returns:
A Database Error Occurred
Error Number: 1054
Unknown column 'NDQA201303001' in 'field list'
INSERT INTO `coa_body` (`NDQA201303001`) VALUES ('')
Filename: C:\xampp\htdocs\NQCL\system\database\DB_driver.php
Line Number: 330
How should the syntax be so as to loop over all the textarea values and save them to the database at once?
I hope that
count($data) == count($data1); //Always True!
If that's the case the following will work:
for ($i=0;$i<count($data);$i++) {
$insert_data = array(
'labref'=>$labref, //NDQA201303001 - Same for all the rows
'compedia'=>$data[$i],
'specification'=>$data1[$i]
);
$this->db->insert('coa_body',$insert_data);
}
Check this Link: CodePad.org
Update:
Suggested by Rcpayan:
//This will reduce number of context switching,
//even though loping is doubled!
for ($i=0;$i<count($data);$i++) {
$insert_data[$i] = array(
'labref'=>$labref, //NDQA201303001
'compedia'=>$data[$i],
'specification'=>$data1[$i]
);
}
$this->db->insert_batch('coa_body',$insert_data);
You could do something like this, it's a bit longer but can also deal with compedia and specification not being equal. This solutions assumes a few things:
You want the value of labref to be the same for each row inserted
If the number of values for compedia and specification aren't equal, you still want to insert the row, but the 'missing' values will be set to NULL.
$labref = $this->uri->segment(3);
$compedia_data = $this->input->post('compedia');
$specification_data = $this->input->post('specification');
//Calculate which array is larger, so we can loop through all values
$max_array_size = max(count($compedia_data), count($specification_data));
//Iterate through the arrays
for ($i = 0; $i < $max_array_size; $i++)
{
$this->db->set('labref', $labref);
//If we still have a value(s) for compedia, then assign the value, otherwise set to NULL
if array_key_exists($i, $compedia_data)
{
$this->db->set('compedia', $compedia_data[$i]);
}
else
{
$this->db->set('compedia', NULL);
}
//If we still have a value(s) for specification, then assign the value, otherwise set to NULL
if array_key_exists($i, $specification_data)
{
$this->db->set('specification', $specification_data[$i]);
}
else
{
$this->db->set('specification', NULL);
}
//Insert into table: 'coa_body'
$this->db->insert('coa_body');
}
Alternatively, you could change the loop to assign the values to an array, then batch insert these values. This might offer better performance.
//Initial other relevant code is included in the example above (excluded here for brevity)
$insert_array = new array();
//Iterate through the arrays
for ($i = 0; $i < $max_array_size; $i++)
{
$row_array = new array();
$row_array['labref'] = $labref;
//If we still have a value(s) for compedia, then assign the value, otherwise set to NULL
if array_key_exists($i, $compedia_data)
{
$row_array['compedia'] = $compedia_data[$i];
}
else
{
$row_array['compedia'] = NULL;
}
//If we still have a value(s) for specification, then assign the value, otherwise set to NULL
if array_key_exists($i, $specification_data)
{
$row_array['specification'] = $specification_data[$i];
}
else
{
$row_array['specification'] = NULL;
}
//Add current row to the insert array, so it can be added to the database
$insert_array[$i] = $row_array;
}
//Insert into table: 'coa_body'
$this->db->insert_batch('coa_body', $insert_array);
I have a form with over 100 dynamically named fields, that post to a php file, I want to take all the fields that are posted to the php file which is currently:
Array ( [option_page] => plugin_options
[action] => update
[_wpnonce] => a51bfc281a
[_wp_http_referer] =>/wp-admin/options-general.php page=plug.php
[13939069] =>
[2171] =>
[3600645] =>
[2168] =>
[13937024] =>
[submit] => Save Changes
[__qca] => P0-1887521465-1334258158937
[s_vi] => )
From this I want to insert the data into a mysql table in the format:
id | option_name | value
--------------------------------------------
autonum | post data key | post data value
But the issue is I am only intrested in the post data value after: [_wp_http_referer]
but before [submit] so these can be used as reference points.
The part I am stuggling with is:
how would I get only that part of the post data dynamically?
How would I get the required array keys and insert it into the
table dynamically?
Many thanks!
You mat try this
$start = array_search("_wp_http_referer",array_keys($_POST))+1;
$end = array_search("submit",array_keys($_POST))-1;
$newArr=array_slice($_POST, $start, $end);
foreach($newArr as $k=>$v)
{
// $k is the key name and $v is the value of that key
//echo $k."=".$v."<br />";
$val=mysql_real_escape_string($v);
$sql="INSERT INTO table_name VALUES (null, ".$k.", ".$val.")";
mysql_query($sql);
}
$counter = 0;
foreach($_POST as $key=>$value)
{
if($key == "_wp_http_referer")
{
$counter = 1;
}
if($counter == "1")
{
if($key != "submit")
{
mysql_query("INSERT INTO table_name(id, option_name, value) VALUES ('','".mysql_real_escape_string($key)."','".mysql_real_escape_string($value)."')");
}
}
}
The keys you want seem to be all numeric, so you could only store those. Like others before me, I also suggest using PDO for added security and convenience.
$dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
foreach($_POST as $key => $value) {
if(preg_match("/^[0-9]+$/", $key) {
$stmt = $dbh->prepare('INSERT INTO table_name(option_name, value) VALUES (?, ?)');
$stmt->execute(array($key, $value));
}
}
You could do something like this:
$discard_array = array('option_page', 'action', '_wpnonce', '_wp_http_referer', 'submit', '__qca', 's_vi');
$good_array = array();
foreach ($_POST as $key => $val)
{
if (!in_array($key, $discard_array)) $good_array[$key] = $val;
}
// use $good_array to insert your data into db
print_r($good_array);
Or, if all of the "good" values have always numeric keys, here's a simplified variation:
$good_array = array();
foreach ($_POST as $key => $val)
{
if (is_numeric($key)) $good_array[$key] = $val;
}
print_r($good_array);
Hope that helps.