I can't use a nested loop as foreach - php

The problem is easy. The answer is not
I have an array with multiple (2) dimensions.
The code is easy (line 28-32):
<?php
foreach($select_all_data as $key => $value) {
foreach ($value as $v => $k) {
$all_values = $v.",";
}
}
?>
But when I excecute it, it shows me
Warning: Invalid argument supplied for foreach() in D:\xampp\htdocs\qlb\test.php on line 29
(I also tested $value al array with is_array, that gave me true)
An example output of $value in the loop is:
array(12) {
["id"]=>
string(3) "101"
["aangever_voornaam"]=>
string(8) "censored"
["aangever_achternaam"]=>
string(6) "censored"
["aangever_geslacht"]=>
string(3) "Male"
["pleegplaats"]=>
string(6) "censored"
["pleegdatum"]=>
string(10) "dd-mm-yyyy"
["pleegtijd"]=>
string(5) "hh:mm"
["verbalisant"]=>
string(12) "censored"
["verklaring"]=>
string(229) "censored"
["opnamedatum"]=>
string(19) "yyyy-mm-dd hh:mm:ss"
["status"]=>
string(4) "open"
["behandelaar"]=>
string(12) "censored"
}
As you can see, its a nice array that I want to put in the loop. But it gives me the invalid argument error.
What did I do wrong?
For the record: I tried to create a script to export a whole database with this script
<?php
$DB_HOST = "";
$DB_USER = "";
$DB_PASS = "";
$DB_NAME = "";
$con = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
if($con->connect_errno > 0) {
die('Connection failed [' . $con->connect_error . ']');
}
$select_all_tables = array();
$select_all_data = array();
$show_tables_from = $con->query("SHOW TABLES FROM `$DB_NAME`");
while ($row = $show_tables_from->fetch_assoc()) {
$select_all_tables[] = $row['Tables_in_'.$DB_NAME.''];
}
foreach ($select_all_tables as $a) {
$q = $con->query("SHOW CREATE TABLE `$a`");
$show_create_table[] = $q->fetch_assoc()['Create Table'];
$q = $con->query("SELECT * FROM `$a`");
$select_all_data[] = $q->fetch_assoc();
}
echo "<pre>";
//var_dump($a);
//var_dump($show_create_table);
//var_dump($select_all_data);
foreach($select_all_data as $key => $value) {
var_dump($value);
}
?>

Acording to fetch_assoc docs
Returns an associative array that corresponds to the fetched row or
NULL if there are no more rows.
So for those $value elements inside the loop that end up being null you will have that error thrown..
So just wrap it in if statement like:
if (!is_null($value)) {
foreach ($value as $v => $k) {
$all_values = $v.",";
}
}
or maybe even is_array($value) to make sure you able to iterate thru...

The arrays had a diffrent number of keys. I think because I forgot to loop the query in the first foreach (after the while)
So I changed that to
foreach ($select_all_tables as $a) {
$q = $con->query("SHOW CREATE TABLE `$a`");
$show_create_table[] = $q->fetch_assoc()['Create Table'];
$q = $con->query("SELECT * FROM `$a`");
while ($row = $q->fetch_assoc()) {
$select_all_data[] = $row;
}
}
And that was the solution!

Related

Adding rows spanning multiple rows in Symfony Console

I am currently developing a CLI using Symfony Console and I have run into a problem regarding adding a row spanning multiple rows.
My code is
$table = new Table($output);
$table->setHeaders(['Elements','Properties']);
foreach($elements as $key => $element) {
if ($key != 'templates') {
//process element
$rowcount = 0;
foreach($element as $name => $component){
if(is_string($component)){
$strings[] = $name.' = '.($component == '' ? 'empty' : $component);
$rowcount++;
}
}
//creating row
$count = 0;
foreach ($strings as $string) {
if ($count == 0) {
$frow[] = new TableCell($key, ['rowspan' => $rowcount]);
$frow[] = $string;
} else {
$row[] = $string;
}
$count++;
}
$rows = [$frow,$row];
var_dump($rows);
$table->addRows($rows);
unset($frow,$row,$strings);
}
}
$table->setStyle('borderless');
$table->render();
The var_dump at this point creates this result
array(2) {
[0]=>
array(2) {
[0]=>
object(Symfony\Component\Console\Helper\TableCell)#63 (2) {
["value":"Symfony\Component\Console\Helper\TableCell":private]=>
string(5) "forms"
["options":"Symfony\Component\Console\Helper\TableCell":private]=>
array(2) {
["rowspan"]=>
int(4)
["colspan"]=>
int(1)
}
}
[1]=>
string(12) "name = forms"
}
[1]=>
array(3) {
[0]=>
string(18) "path = admin/forms"
[1]=>
string(14) "scope = system"
[2]=>
string(16) "attachto = empty"
}
}
The CLI should appear like this
============= ===================
Elements Properties
============= ===================
forms name = forms
path = admin/forms
scope = system
attachto = empty
I don't know if this is too much but the problem is the alignment of the second column is completely disjointed.The scope=system section moves to a 3rd column.

PHP/SQL array access error

I'm trying to make a new column with results from an SQL query in PHP:
$someArray= array(array('match'=>'123'), array('match'=>'456'), array('match'=>'789')); //arbitrary number of elements
foreach($someArray as $key=>$item){
$someArraysDouble[]=$item;
}
$someQuery="select count(*) as somecount from sometable";
$probe1=array();
$probe2="0";
$probe3="0";
$probe4="0";
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";//myDB uses MySQL
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
foreach($someArray as $key=>$item) {
$someQuery.=" where somecolumn like "%$item['match']%";
$blahblah=$conn->query($someQuery);
if ($blahblah->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$row['match']=$item['match'];
$probe1[]=$row;
}
}
$conn->close();
}
foreach($someArraysDouble as $key1=>$item1) {
foreach($probe1 as $key2=>$item2) {
if($item2['match']==$item1['match']) {
$probe2=$item1['somecount'];
$probe3=$item2['somecount'];
$item1['somecount']=$item2['somecount'];
$probe4=$item1['somecount'];
}
}
}
The output HTML looks like this:
<html>
<head></head>
<body>
{$probe2}<br>{$probe3}<br>{$probe4}<br><br>
{loop $probe1 $key1 $item1}
{$item1['somecount']}<br><br>
{/loop}
<br><br>
{loop $someArraysDouble $key2 $item2}
{$item2['somecount']}<br><br>
{/loop}
</body>
</html>
Result is... something I don't understand:
- $probe2 is null, which is expected.
- $probe3 is the count value for last element, which is expected.
- $probe4 is the count value for last element, which is expected.
- The first loop with $probe1 produces the count value for each element, which is expected.
- The second loop with $someArraysDouble produces nothing, which is NOT expected. HOW can this happen?
For some reason that I'm not sharing in order to keep this question concise, I need to have the count value for each element outputted via $someArraysDouble.
I suspect that this line is not performing as you expect because you have not created $someArraysDouble before entering the loop:
$someArraysDouble[]=$item;
Try creating an empty array first, like this:
$someArraysDouble = array(); // <== Initialize the array first
$someArray = array(array('match'=>'123'), array('match'=>'456'),
array('match'=>'789')); //arbitrary number of elements
foreach($someArray as $key=>$item){
$someArraysDouble[] = $item;
}
See the PHP Array docs for more info, specifically the section "Creating/modifying with square bracket syntax".
Turns out it was me not understanding how foreach in PHP works.
function array_generate(){
return array(array('match'=>'123'), array('match'=>'456'), array('match'=>'789')); //arbitrary number of elements
}
$someArray=array_generate();
var_dump($someArray);
foreach($someArray as $heavy=>$load)
{
$load['addedvalue']="newvalue";
$test1[$heavy]="newvalue";
$test2[$heavy]=$load['addedvalue'];
var_dump($someArray);
}
var_dump($someArray);
var_dump($test2);
The n+2 var_dump($someArray)s (where n==count($someArray)) all show the same.
array(3) { [0]=> array(1) { ["match"]=> string(3) "123" } [1]=> array(1) { ["match"]=> string(3) "456" } [2]=> array(1) { ["match"]=> string(3) "789" } }
But var_dump($test2) shows:
array(3) { [0]=> string(8) "newvalue" [1]=> string(8) "newvalue" [2]=> string(8) "newvalue" }
This means the addedvalue of each element of $someArray does not persist once $key changes. So my solution is to use a new array, which is synced with the original array, length-wise.

php multidimensional array to single dimensional array [duplicate]

This question already has answers here:
Is there a function to extract a 'column' from an array in PHP?
(15 answers)
Closed 6 months ago.
I have an array
array(5) {
[0]=>
array(1) {
["id"]=>
string(1) "5"
}
[1]=>
array(1) {
["id"]=>
string(1) "6"
}
[2]=>
array(1) {
["id"]=>
string(1) "7"
}
[3]=>
array(1) {
["id"]=>
string(1) "8"
}
[4]=>
array(1) {
["id"]=>
string(1) "9"
}
}
I wan to make my array like:
$registrationIDs = array( "5","6","7","8","9");
I am trying this code but not working
$results = array();
foreach($result as $inner) {
$results[key($inner)] = current($inner);
}
How do I effeciently transform arrays like this
Try with array_map.
$results = array_map (function ($e) { return $e['id']; }, $inner);
http://php.net/manual/en/function.array-map.php
By the way, if you still want to do it your way, try this form of foreach :
$results = array ();
foreach ($inner as $key => $value)
$results[$key] = $value['id'];
$array = [['id'=>1],['id'=>2],['id'=>3],['id'=>4],['id'=>5],];
$result = call_user_func_array('array_merge_recursive', $array);
var_dump($result['id']);
//array(5) {
// [0] =>
// int(1)
// [1] =>
// int(2)
// [2] =>
// int(3)
// [3] =>
// int(4)
// [4] =>
// int(5)
//}
Ok, I saw a lot of answers, so I wondered what to better answer was.
<?php
$data = array ();
for ($i = 0; $i < 1000000; $i++)
$data[$i] = array ('id' => rand ());
$time0 = microtime (true);
// Niols (1)
$results = array_map (function ($e) { return $e['id']; }, $data);
$time1 = microtime (true);
// Niols (2)
$results = array ();
foreach ($data as $key => $value)
$results[$key] = $value['id'];
$time2 = microtime (true);
// User (1)
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
$results = iterator_to_array($it, false);
$time3 = microtime (true);
// User (2)
$results = array();
foreach ($data as $datum)
$results = array_merge($results, $datum);
$time4 = microtime (true);
// sectus
$results = call_user_func_array('array_merge_recursive', $data);
$time5 = microtime (true);
// Pankaj katiyar and Ghost
$results = array_column($data, 'id');
$time6 = microtime (true);
var_dump ($time1-$time0);
var_dump ($time2-$time1);
var_dump ($time3-$time2);
var_dump ($time4-$time3);
var_dump ($time5-$time4);
var_dump ($time6-$time5);
On my computer, this outputs :
float(0.62708687782288)
float(0.35285401344299)
float(1.5429890155792)
float(0.7408618927002)
float(0.70525908470154)
float(0.15015292167664)
Conclusion :
array_column is ultra-efficient (but PHP 5.5+). Writing a simple foreach seems quite efficient too.
You can try with below code.
I think this is working fine.
Process 1:-
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($data));
$l = iterator_to_array($it, false);
var_dump($l); // one Dimensional
Process 2:-
Try with:
$input = array(/* your array*/);
$output = array();
foreach ( $input as $data ) {
$output = array_merge($output, $data);
}
Try this:
$array = array(/*your array*/);
$results = array();
foreach ($array as $value)
{
foreach($value as $innerValue)
{
$results[] = $innervalue;
}
}

query should return integer and string CI

I have got the following query which returns Dates (string value) and Numbers (integer value)
public function getGraphDataPositives() {
$query = 'SELECT
DATE(stamp) AS x, SUM(positive) AS y
FROM data
WHERE companyId = 3
GROUP BY DATE(stamp)';
$currentDate = date("%Y-m-d%");
$query = $this->db->query($query);
return $query->result();
}
But when I'm dumping my result in my controller I get an array with only strings. The values should be integer in order to use them for a graph.
Just the first piece of array:
array(25) {
[0]=>
object(stdClass)#169 (2) {
["x"]=>
string(10) "2013-10-16"
["y"]=>
string(7) "3283581"
}
[1]=>
object(stdClass)#160 (2) {
["x"]=>
string(10) "2013-10-17"
["y"]=>
string(7) "1512116"
}
I'm handling this array to create a Json object:
$_rows = array();
foreach ($rows as $i => $row) {
foreach ($row as $column => $value) {
$_rows[$i][$column] = $value;
}
}
$rows = $_rows;
echo json_encode(array("className" => ".main.l1","data" => $rows));
But the JSON object contains the values as a string, not like an integer like desired. What should I change?
Sample of JSON output:
{"className":".main.l1","data":[{"x":"2013-10-16","y":"3283581"},{"x":"2013-10-17","y":"1512116"},{"x":"2013-10-18","y":"3967"},{"x":"2013-10-19","y":"1094"},{"x":"2013-10-20","y":"853"},{"x":"2013-10-21","y":"1205"},{"x":"2013-10-22","y":"2618700"},{"x":"2013-10-23","y":"3928291"},{"x":"2013-10-24","y":"3670318"},{"x":"2013-10-25","y":"3347369"},{"x":"2013-10-26","y":"2525573"},{"x":"2013-10-27","y":"3224612"},{"x":"2013-10-28","y":"3992964"},{"x":"2013-10-29","y":"3949904"},{"x":"2013-10-30","y":"3568618"},{"x":"2013-10-31","y":"3104696"},{"x":"2013-11-01","y":"3246932"},{"x":"2013-11-02","y":"2817758"},{"x":"2013-11-03","y":"3198856"},{"x":"2013-11-04","y":"3952957"},{"x":"2013-11-05","y":"3934173"},{"x":"2013-11-06","y":"3878718"},{"x":"2013-11-07","y":"3642822"},{"x":"2013-11-08","y":"3388646"},{"x":"2013-11-09","y":"376763"}]}
Can anyone help me out on this one?
try something like this
try to check if value is Integer.If it is integer than parse it to string
foreach ($rows as $i => $row) {
foreach ($row as $column => $value) {
if(is_numeric($value)){
$_rows[$i][$column] = intval($value);
}else{
$_rows[$i][$column] = $value;
}
}
}

add keys to php array

I'm trying to build an array for feeding my Graph. I use the code below:
$rows = $this->Website_model->getGraphDataPositives();
$_rows = array();
$i = 0;
foreach ($rows as $key => $row) {
foreach ($row as $column => $value) {
$_rows[$i]['x'] = $value;
$_rows[$i]['y'] = $value;
$i++;
}
}
This results in the following response:
array(48) {
[0]=>
array(2) {
["x"]=>
string(7) "3283581"
["y"]=>
string(7) "3283581"
}
[1]=>
array(2) {
["x"]=>
string(10) "2013-10-16"
["y"]=>
string(10) "2013-10-16"
}
So it isn't okay yet.. it should say:
array(48) {
[0]=>
array(2) {
["x"]=>
string(7) "3283581"
["y"]=>
string(7) "2013-10-16"
}
[1]=>
array(2) {
["x"]=>
string(10) "1512116"
["y"]=>
string(10) "2013-10-17"
}
Can anyone tell me what I need to adjust in order to get the right output?
/////////////////////////////////
this is what's in $rows (a part of the output)
array(24) {
[0]=>
object(stdClass)#169 (2) {
["SUM(positive)"]=>
string(7) "3283581"
["DATE(stamp)"]=>
string(10) "2013-10-16"
}
[1]=>
object(stdClass)#160 (2) {
["SUM(positive)"]=>
string(7) "1512116"
["DATE(stamp)"]=>
string(10) "2013-10-17"
}
I think the first step here is to fix your output array from the Codeigniter model. Did you create:
$rows = $this->Website_model->getGraphDataPositives();
If so, you should be able to easily go into the function and change the output of the select statement.
Where you find "SUM(positive)" and "DATE(stamp)" in the function getGraphDataPositives(), change it to this (rough example, I don't know what the function looks like):
SUM(positive) AS x
DATE(stamp) AS y
Now you can just run it this way instead:
$rows = $this->Website_model->getGraphDataPositives();
$_rows = array();
foreach ($rows as $i => $row) {
foreach ($row as $column => $value) {
$_rows[$i][$column] = $value;
}
}
Also notice that I removed the $i = 0 and $i++ and replaced $key wit $i. Much easier that way.
Let me know if this helps.
EDIT: I accidentally kept the second $_rows[$i][$column] = $value; in there; that's not needed anymore. You only need one, and the way you have it set up its setting the same value to both entries.
EDIT 2: Just wanted to note that the above example may not be the best option, the best option would be to give more description aliases.
SUM(positive) AS positive
DATE(stamp) AS timestamp
Then set the values like this:
foreach ($rows as $i => $row) {
$_rows[$i]['x'] = $row->positive;
$_rows[$i]['y'] = $row->timestamp;
}
Either option will work, the first is just a little easier.
It would be easier if i knew the column names from SQL but here goes:
$rows = $this->Website_model->getGraphDataPositives();
$_rows = array();
foreach ($rows as $row) {
$_rows[] = array(
'x'=>$row['x-column-name-here'],
'y'=>$row['y-column-name-here']
);
}
foreach ($rows as $key => $row) {
// here $key is index, $row is the object
foreach ($row as $column => $value) {
// here $column will be "SUM(positive)" and the value will be 3283581
// for the first iteration. Since both are assigned $value
// $_rows[$i]['x'] and $_rows[$i]['y'] will be identical
$_rows[$i]['x'] = $value;
$_rows[$i]['y'] = $value;
$i++;
}
}
If you just use the object columns as you defined you should be ok:
foreach ($rows as $row) {
$_rows[$i]['x'] = $row->{'SUM(positive)'};
$_rows[$i]['y'] = $row->{'DATE(stamp)'};
}
You're also not using $key so might as well get rid of that as well.
Your example is kind of basic but I think this should solve its issues:
foreach ($rows as $key => $row) {
foreach ($row as $column => $value) {
$_rows[$key][$column%2==0?'x':'y'] = $value;
}
}
Provided you're using PDO::FETCH_NUM, ie your $rows are numerically indexed.

Categories