Appending to array replaces all elements in the array - php

I'm building an array of rows from a DB using the code below.
$site = new stdClass();
$dbh = _vic_commander_db();
$sth = $dbh->prepare('SELECT name, title, url FROM site ORDER BY siteid');
$sth->bindColumn(1, $site->name);
$sth->bindColumn(2, $site->title);
$sth->bindColumn(4, $site->url);
$sth->execute();
$ret = array();
while ($sth->fetch(PDO::FETCH_BOUND))
{
$ret[] = $site;
}
The array ($ret[]) does get added to each iteration of the loop; however in addition to APPENDING each of the rows of the table, all elements get REPLACED by the last result appended. So I have an array with the same number of elements as rows in the table but the elements are all the same.
Any ideas would be much appreciated.
Example out:
array(3) (
[0] => stdClass object {
name => (string) Same Site Name
title => (string) Same Site Title
url => (string) samepurl.com
}
[1] => stdClass object {
name => (string) Same Site Name
title => (string) Same Site Title
url => (string) samepurl.com
}
[2] => stdClass object {
name => (string) Same Site Name
title => (string) Same Site Title
url => (string) samepurl.com
}
)

All the array indexes point to the same object $site.
You have to copy by value instead of by reference:
$ret[] = clone $site;
see http://php.net/manual/en/language.oop5.cloning.php
Also I wonder why you really need to store an object here.

The other answer has a decent explanation, but why not just fetch into an array of objects?
$sth = $dbh->prepare('SELECT name, title, url FROM site ORDER BY siteid');
$ret = $sth->fetchAll(PDO::FETCH_OBJ);

try this way, according to documentation ( execute() before bindColumn() ):
$site = new stdClass();
$dbh = _vic_commander_db();
$sth = $dbh->prepare('SELECT name, title, url FROM site ORDER BY siteid');
$sth->execute();
$sth->bindColumn(1, $site->name);
$sth->bindColumn(2, $site->title);
$sth->bindColumn(4, $site->url); //could you explain why 4?? not 3 ???
$ret = array();
while ($sth->fetch(PDO::FETCH_BOUND))
{
$ret[] = $site;
}

Related

How to add <hr> tags between unique rows from query resultset?

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>

PHP - Merge arrays | Numbers of arrays not known because arrays coming by loop

Apologies if posted already.
Struggling with array_merge function.
It works fine when we use it like this.
array_merge($array1,$array2);
In my case both arrays are from MySQL result.
See the following code for understanding it better.
$getfilelist = 'select * from fileartist fid IN (210,209)'; // fetching two rows
$FILE = $db->query($getfilelist);
$file_tot = count($FILE);
for($i=0;$i<$file_tot;$i++)
{
$artist = explode(',', $FILE[$i]['artist']); // Because Artist names saved like this `A,B` in first row and `A,C,D` in second.
}
print_r($artist);
This prints something like this.
Array // artist in first row
(
array[0] => A
array[1] => B
)
Array // artist in second row
(
array[0] => A
array[1] => C
array[2] => D
)
I want array should -
Array
(
array[0] => A
array[1] => B
array[2] => C
array[3] => D
)
I tried following code.
$getfilelist = 'select * from fileartist fid IN (210,209)'; // fetching two rows
$FILE = $db->query($getfilelist);
$file_tot = count($FILE);
for($i=0;$i<$file_tot;$i++)
{
$artist = explode(',', $FILE[$i]['artist']); // Because Artist names saved like this `A,B` in first row and `A,B,C` in second.
$merged = array_merge($artist);
$unique = array_unique($merged);
}
print_r($unique);
Results is
Array
(
array[0] => A
array[1] => B
)
Array
(
array[0] => A
array[1] => C
array[2] => D
)
This is not expected result.
In above code, I need something like this -> array_merge($FILE[0], $FILE[1]); for get expected result. Can't figure out how to code it.
I know array_merge function require two or more array but can't figure out how give both array to array_merge function.
Suggest me how to print only A,B,C,D in above case. Is I'm missing something? Or this is bad coded script?
Also, can this post may have more better title for future users.
try this
$getfilelist = 'select * from fileartist fid IN (210,209)'; // fetching two rows
$FILE = $db->query($getfilelist);
$file_tot = count($FILE);
$artist=[];
for($i=0;$i<$file_tot;$i++)
{
$artist = array_merge($artist,explode(',', $FILE[$i]['artist'])); // Because Artist names saved like this `A,B` in first row and `A,C,D` in second.
}
print_r(array_unique($artist));
or
$getfilelist = 'select * from fileartist fid IN (210,209)'; // fetching two rows
if($result = $mysqli->query($getfilelist)){
$artist=[];
while($FILE = $result->fetch_assoc()){
array_merge($artist,explode(',', $FILE['artist']));
}
}
print_r(array_unique($artist));
This will works for an Album's full info.
I posted it here for future user.
$getfilelist = 'select * from fileartist fid IN (210,209)'; // fetching two rows
$FILE = $db->query($getfilelist);
$file_tot = count($FILE);
$artist=[];
$music=[];
$label=[];
$lyrics=[];
for($i=0;$i<$file_tot;$i++) {
$artist = array_merge($artist,explode(',', $FILE[$i]['artist'])); // Because Artist names saved like this `A,B` in first row and `A,C,D` in second.
$music = array_merge($music,explode(',', $FILE[$i]['music']));
$label = array_merge($label,explode(',', $FILE[$i]['label']));
$lyrics = array_merge($lyrics,explode(',', $FILE[$i]['lyrics']));
}
print_r(array_unique($artist));
print_r(array_unique($music));
print_r(array_unique($label));
print_r(array_unique($lyrics));

Insert result from DOMXpath into MySQL

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.

make an object out of an array PHP

I am trying to search one word in my whole table.
So if you search Eminem, you have to get everything with the word Eminem.
I search
<?php
$sql="SELECT * FROM album WHERE albumartiest like '$zoek'";
$resultaatcolumn = Yii::app()->db->CreateCommand($sql)->queryAll();
if($resultaatcolumn != null){
$zoekresultaat[] = $resultaatcolumn;}
$sql="select * from album where albumnaam like '%$zoek%'";
$resultaatcolumn = Yii::app()->db->CreateCommand($sql)->queryAll();
if($resultaatcolumn != null){
$zoekresultaat[] = $resultaatcolumn;}
$sql="select * from album where albumartiest like '%$zoek%'";
$resultaatcolumn = Yii::app()->db->CreateCommand($sql)->queryAll();
if($resultaatcolumn != null){
$zoekresultaat[] = $resultaatcolumn;}
$sql="select * from album where albumgenre like '%$zoek%'";
$resultaatcolumn = Yii::app()->db->CreateCommand($sql)->queryAll();
if($resultaatcolumn != null){
$zoekresultaat[] = $resultaatcolumn;}
$sql="select * from album where albumafspeelijst like '%$zoek%'";
$resultaatcolumn = Yii::app()->db->CreateCommand($sql)->queryAll();
if($resultaatcolumn != null){
$zoekresultaat[] = $resultaatcolumn;}
It works, but not exactly how I want it.
The result is this:
Array ( [0] => Array ( [0] => Array ( [albumcode] => 45 [albumnaam] => recovery [albumafspeelijst] => ["Cold Wind Blows","Talkin' 2 Myself","On Fire","Won't Back Down","W.T.P.","Going Through Changes","Not Afraid","Seduction","No Love","Space Bound","Cinderella Man","To Life","So Bad","Almost Famous","Love The Way You Lie","You're Never Over",""] [albumartiest] => Eminem [albumgenre] => hip-hop [albumimage] => images\eminemrecovery.png [albumprijs] => 20 ) ) [1] => Array ( [0] => Array ( [albumcode] => 45 [albumnaam] => recovery [albumafspeelijst] => ["Cold Wind Blows","Talkin' 2 Myself","On Fire","Won't Back Down","W.T.P.","Going Through Changes","Not Afraid","Seduction","No Love","Space Bound","Cinderella Man","To Life","So Bad","Almost Famous","Love The Way You Lie","You're Never Over",""] [albumartiest] => Eminem [albumgenre] => hip-hop [albumimage] => images\eminemrecovery.png [albumprijs] => 20 ) ) )
that's okay, but what I want is take out variable's and use it.
is there a way that I can get variable's out of the array and use it?
If you guys want more information about my code please ask!
Try using this
Yii::app()->db->CreateCommand($sql)->setFetchMode(PDO::FETCH_OBJ)->queryAll()
This will give you an array of objects with column name as the properties.
Eg:-
foreach($result as $row)
{
echo $row->albumcode;
}
If you want to access the result set like an object you can use the native PHP class ArrayObject and provide the flag to indicate that.
$album = new ArrayObject($result, ArrayObject::ARRAY_AS_PROPS);
You can now access the results like the following:
$code = $album->albumcode;
$name = $album->albumnaam;
Hope this can guide you, happy coding!
uhhh just do
foreach($zoekresultaat as $key => $value) {
//do what I want with each seperate returened result. The array key is in $key and the result array is in $value
echo $value['albumcode'] . ' = '. $value['albumnaam'];
}
aka, basic php
And please for the security of your app, learn how to do prepared statements in yii
The way your query is now I could wipe your entire database

Looping through post data and updating corresponding database records

I am trying to loop through some data I post through jQuery. Here is my PHP script:
<?php
include '../dbconnect.php';
$map = $_POST['map'];
$position = 0;
foreach ($map as $ID)
{
if ($_POST['type'] == "sub") {
$query = "UPDATE Subcategories SET `Position` = '$position' WHERE CategoryID = '$ID';";
} else {
$query = "UPDATE Categories SET `Position` = '$position' WHERE CategoryID = '$ID';";
}
$result = mysql_query($query) or die(mysql_error());
$position ++;
}
?>
and the data it is recieving as $map is sent in this format:
ID[]=27&ID[]=28&ID[]=33&ID[]=19
Obviously my foreach is wrong, but how would I go about getting it so that I retain $maps order and each numerical value becomes the variable $ID?
Ok, Since your $map contains, ID[]=27&ID[]=28&ID[]=33&ID[]=19 string value. Do something like this
$str = str_replace($map, "ID[]=","");
$mArr = explode("&", $str);
foreach($mArr as $key) {
//now your $key will have 27, 28, 33, 19 as the loop progresses
}
P.S. Based on the OP's comment of $map having a string output of that
Can you show us what print_r($map); displays.
If it's just a string in the format you've described, I'd suggest changing the format of map to something easier to loop through like json. For example
{"map":[27,28,33,19]}
Then you can use
<?php
$mapObject = json_decode($_POST['map']);
$mapArray = $mapObject->map;
foreach($mapArray as $id)
{
echo $id;
}
?>
You can POST it without the map, just
$.ajax({ type: 'POST', url: 'updatecategoryposition.php', data: map + "&type=sub" });
I'm assuming that map contains 'ID[]=27&ID[]=28&ID[]=33&ID[]=19'
As an alternative you can save the map in a different format so you end up with map being just a list of IDs ($map="27,28,33,19"), use the original jquery post and finally use
$map = explode(',' $_POST['map']);
I'm not entirely sure, but is this what you meant? It works, if I understand your problem correctly.
<?php
include '../dbconnect.php';
$position = 0;
$pattern = '/ID\\[\\]=(\d+)&*/';
$subject = $_POST['map'];
preg_match_all($pattern, $subject, $matches);
foreach ($matches as $k => $ID) {
// etc
Test Case
Try this test, in a separate script. The output from $matches[1] are what you would feed to the foreach loop if you used this script. Does this retrieve what you want?
<?php
$pattern = '/ID\\[\\]=(\d+)&*/';
$subject = 'ID[]=27&ID[]=28&ID[]=33&ID[]=19';
preg_match_all($pattern, $subject, $matches);
echo '<pre>'.print_r($matches,1).'</pre>';
?>
Outputs:
Array
(
[0] => Array
(
[0] => ID[]=27&
[1] => ID[]=28&
[2] => ID[]=33&
[3] => ID[]=19
)
[1] => Array
(
[0] => 27
[1] => 28
[2] => 33
[3] => 19
)
)
Thanks for trying guys, but in the end I couldn't get any suggestions to work but I did find a solution:
Update category position:
<?php
include '../dbconnect.php';
foreach ($_POST['ID'] as $position => $ID){
$query = "UPDATE Subcategories SET `Position` = '$position' WHERE CategoryID = '$ID';";
$result = mysql_query($query) or die(mysql_error());
}
?>
and the new Jquery post request courtesy of Starx (telling me to remove variable name), as a result I can access the query string as above:
$.ajax({
type: 'POST',
url: 'updatecategoryposition.php',
data: map
});

Categories