I have some code that essentially does what I want but I always like to make it simpler and more efficient whenever possible so here I am.
Basically, I have a list of pages that each run an SQL query and pull X number of relevant records, appending each one to the former by saving to a text file that's then reopened for further processing, like so:
foreach($pages as $page){
$fp = fopen("$page.txt", 'w');fclose ($fp);
$result = $db->query("SELECT X, Y, Z FROM Table WHERE Pages LIKE '%$page%'");
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$v = $row['X'].'|'.$row['Y'].'|'.$row['Z'].';';
file_put_contents("$page.txt", $v, FILE_APPEND);
}
$data = file_get_contents("$page.txt");
$data = explode(';', $data);
}
Now while that gets the job done I was wondering what would be the better way of doing it, I've tried messing around with mixed results, was hoping this would work but it generates an error:
foreach($pages as $page){
$result = $db->query("SELECT X, Y, Z FROM Table WHERE Pages LIKE '%$page%'");
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$v = $row['X'].'|'.$row['Y'].'|'.$row['Z'].';' . $v;
$r = array("$page"=>"$v");
}
$data = join($r["$page"]);
$data = explode(';', $data);
}
Any ideas? Thanks
Your code's rather inefficient. You open a file and immediately close it, which is to create the file, I presume. You then use file_get_contents() to output to that file in append mode for every iteration of the loop. That means PHP has to re-open the file, jump to the end, write some text, then close it again. It's like going to the grocery store, buying something, driving home, going back to the store, buying another item, driving home, etc... A major waste of time.
Instead, try something like this:
foreach ($pages as $page) {
$result = $db->query(...) or die('db error...');
$data = array();
while($row = $result->fetchArray(...)) {
$data[] = $row; // append the fetched row to the $data array
}
... do something with $data here ...
}
After each while() loop completes, $data will be array that looks something like:
$data = array(
0 => array('X' => 'someval', 'Y' => 'otherval', 'Z' => 'otherotherval'),
1 => array('X' => etc.....),
etc...
)
if you need to write this $data array out to a file for processing elsewhere, you can use serialize() to output it as a string which can be trivially converted back to a native PHP array using unserialize().
You could also do it like:
$data = array();
foreach($pages as $page){
$result = $db->query("SELECT CONCAT(X, '|', Y, '|', Z) as `data` FROM Table WHERE Pages LIKE '%$page%'");
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$data[] = $row['data'];
}
}
Maybe a bit faster.
If I understood what you are trying to do correctly, then yes, there are much easier ways:
$data = array();
foreach($pages as $page){
$result = $db->query("SELECT X, Y, Z FROM Table WHERE Pages LIKE '%$page%'");
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$data[] = $row['X'].'|'.$row['Y'].'|'.$row['Z'];
}
}
And if I misunderstood, then I am sorry.
Edit
Fixed a little bug with the declaration of the $data array
What's you error?
I can see possible problems here
$v = $row['X'].'|'.$row['Y'].'|'.$row['Z'].';' . $v;
$r = array("$page"=>"$v");
remove the quote codes on $v, and define $v as a empty variable before the loop.
Related
I am trying to save the rows (results) from an SQL query to a csv file.
I am using array push in order to put the results in a list. Later I put the data from this list to my csv file.
My code :
while ($row = $query->fetch_assoc())
{
echo sprintf( $row['campaign']);
array_push($list, $row['campaign']);
}
The results are there because sprintf works. The problem is with the syntax of array_push. I even tried :
array_push($list, array(''.$row['campaign']);
I am getting an error:
fputcsv() expects parameter 2 to be array
The full code is here :
$list = array
(
array('old_campaign_name', 'new_campaign_name')
);
// table 1
$sql = ('select distinct(campaign) as campaign from '.$table1.'');
// Run the query
$query = $Db->query($sql);
// Check for SQL errors
if ($Db->error)
{
return ($Db->error);
}
// Put data in the list
while ($row = $query->fetch_assoc())
{
echo sprintf( $row['campaign']);
array_push($list,$row['campaign'],'');
}
$fp = fopen($location, 'w');
foreach ($list as $fields)
{
fputcsv($fp, $fields);
}
fclose($fp);
As the error says, fputcsv expects each row that you put to be an array, so it can write it out with commas separating the elements. $list should be a 2-dimensional array, so you need to push an array onto it when you're building it.
while ($row = $query->fetch_assoc() {
$list[] = array($row['campaign']);
}
BTW, $list[] = x is equivalent to array_push($list, x).
When you initially create the $list array, it is an array containing one array. But when you add more values to it from your query results, you are pushing strings onto the end of it, not arrays. In effect, you will be making something like
$list = array (
array('old_campaign_name', 'new_campaign_name'),
'first campaign',
'second campaign',
'etc.',
...
);
Because of this, when you loop over $list, the first value should work with fputcsv, because it is an array, but any subsequent values will be strings instead of arrays and will cause the error you are seeing.
You should be able to fill the $list like this:
while ($row = $query->fetch_assoc()) {
$list[] = $row;
}
$list[] = $row will not overwrite the values previously in $list. From the PHP documentation for array_push:
Note: If you use array_push() to add one element to the array it's better to use $array[] = because in that way there is no overhead of calling a function.
It works like this :
while ($row = $query->fetch_assoc())
{
// array_push($list,$row['campaign'],'');
array_push($list,array($row['campaign'], ''));
}
I have an array returned from MYSQL query with 2 LEFT JOINs.
Question is: "Is there another way for writing the code below?". I got the code but I want a more clear way of it just to understand what happens inthere.
CODE:
$result = array();
while ($resultArr = mysqli_fetch_assoc($booksAndAuthors)) {
$result[$resultArr['book_id']] ['book_name'] = $resultArr['book_title'];
$result[$resultArr['book_id']] ['author'][] = $resultArr['author_name'];
print_r($result);
}
With the extract() function you can make the data in the result into variables. I have put the example below inside a function, so they will be local variables.
function getBooksAndAuthors($queryResult)
{
while ($data = mysqli_fetch_assoc($queryResult))
{
extract($data);
$BooksAndAuthors[$book_id] = array('book_name' => $book_title,
'author' => $author_name);
}
return $BooksAndAuthors;
}
This makes the code a lot more readable. You will, of course, have to know which columns there are in your database table. I also left out the extra '[]' for the author.
Here's how I recommend writing it, because I don't think you should depend on automatic creation of intermediate arrays.
$result = array();
while ($row = mysqli_fetch_assoc($booksAndAuthors) {
$bookid = $row['book_id'];
if (!isset($result[$bookid])) {
# First time we see this book, create a result for it
$result[$bookid] = array('book_name' => $row['book_title'],
'author' => array());
}
# add this author to the result entry for the book
$result[$bookid]['author'][] = $row['author_name'];
}
It's essentially equivalent, but I think it also makes the logic clearer.
I am basically trying to fetch results from a SQL database and load that into a multidimensional array so i can use them later on in the page.
while($row = mysqli_fetch_array($result))
{
$send = array
(
array($row['Name'],$row['Email'],$row['Mobile'])
);
$count = $count + 1;
}
That is what i am using to get the results which if i print within the while loop it will echo all the results. However when putting it into the array it loads each result into the array as the first result. My initial plan was to use a counting variable to set where in the array the result was set to with this adding by one each time. I am not certain how to specify where to add the result i thought something along the lines of
$send = array[$count]
(
array.....
so i could then refer to the results as 0 to count length but i am not sure how to make this work. Or ,which i presume, if there is a much easier and better way of going about it. I am also not sure if this is necessary as surely the results seem to be in an array when gathered from the SQL database but i am unsure if this array is populated with each while loop or stored and can be accessed at any point
If any one can give me an example of something similar or point me at some documentation much appreciated
Try this:
$count = 0;
while ($row = mysqli_fetch_array($result)) {
$send[$count] = array($row['Name'], $row['Email'], $row['Mobile']);
$count++;
}
I have a better way for you. You could also use the id for your index, if you have one:
while ($row = mysqli_fetch_array($result)) {
$send[$row['id']] = array(
"Name" => $row['Name'],
"Email" => $row['Email'],
"Mobile" => $row['Mobile']
);
}
You can use:
$count = 0;
while($row = mysqli_fetch_array($result))
{
$send[$count] = $row;
$count ++;
}
Also you might want to use the table id as an array index, so you can access the records by ID later. In that case you can do:
while($row = mysqli_fetch_array($result))
{
$send[$row['id']] = $row;
}
You're declaring your array inside your loop. So it will reset it every time.
$send = array();
while($row = mysqli_fetch_array($result))
{
$send[] = array($row['Name'],$row['Email'],$row['Mobile']);
}
tl;dr - Pushing an array (by $array[] or $array[$id] is not working in Kohana 3, it gives a blank white page.
I'm using Kohana (3), it's my first experience with MVC and it's been great so far; however, I'm working with a database and encountered a weird problem that I was hoping someone could shed some light on:
My workflow is like this, to give you an idea of my problems surrounding:
$sql = "SELECT table1.row1, max(table2.row1) as `maxAwesome` FROM table1, table2 WHERE table1.id=table2.table1id GROUP BY table1.id";
$table1Results = DB::query(Database::SELECT, $sql)->execute();
$masterArray = array();
foreach ($table1Results as $result1)
{
$sql = "SELECT * FROM table2 WHERE table2id='" . $result1['id'] . "' AND column > 21";
$table2Results = DB::query(Database::SELECT, $sql)->execute();
$subArray = array();
foreach ($table2Results as $result2)
{
$subArray[$result1['id']] = $result2;
// Even had just $subArray[] = array("whatever");
}
$masterArray[] = array("table1Data" => array(), "table2Data"=> $subArray);
}
I do a query where I run a couple max/min functions then do a query within the foreach doing another select to build a master array of data formatted the way I want it and all the SQL etc works fine and dandy; however, the problem arises when I'm pushing the array.
It seems whenever I push the array by doing either $array[] = array("data"); or by specifying the key $array[$id] = array("data"); Kohana gives me a straight blank page, no error, no output etc.
Sometimes I get a Kohana error indicating the key does not exist (duh, I'm creating it) but for the most part the output is straight white.
Why is this happening? Am I going about it wrong?
Thanks in advance.
Clarity edit:
My SQL blunders aside, the issue lies in the building of the secondary array, for example:
$queryStores = "SELECT stores.store_id, stores.title, max(product.discount) as `max_discount`, min(product.discount) as `min_discount`
FROM stores, products
WHERE products.store=stores.store_id
GROUP BY products.store";
$stores = DB::Query(Database::SELECT, $queryStores)->execute();
$formattedStores = array();
if (count($stores))
{
foreach ($stores as $store)
{
$formattedStores[$store['store_id']] = array(
"title" => $store['title'],
);
// Same result if just doing $formattedStores[] = array();
// Problem goes away should I do:
// $formattedStores = array("This works");
//
}
}
echo "<pre>";
print_r($formattedStores);
echo "</pre>";
That does not print an array, it simply gives a blank page; however, if i change it to just re-set the $formattedStores array to something I get an output. What is it about pushing the array that's causing a problem, perhaps a Kohana bug?
Thanks
Your code should be like:-
$sql = "SELECT table1.id, table1.row1, max(table2.row1) as `maxAwesome`
FROM table1, table2
WHERE table1.id = table2.table1id
GROUP BY table1.id";
$table1Results = DB::query(Database::SELECT, $sql)->execute();
$masterArray = array();
if (count($table1Results))
{
foreach ($table1Results as $result1)
{
$sqlInner = "SELECT * FROM table2
WHERE table2id = '" . $result1['id'] . "'
AND column > 21";
$table2Results = DB::query(Database::SELECT, $sqlInner)->execute();
$subArray = array();
if (count($table2Results))
{
foreach ($table2Results as $result2)
{
$subArray[$result1['id']] = $result2;
// Even had just $subArray[] = array("whatever");
}
}
$masterArray[] = array("table1Data" => array(), "table2Data"=> $subArray);
}
}
Some valuable coding standards & miss-ups:-
You have got the "id" field (w.r.t. the "table1" DB table) missing from the first SQL.
The second SQL should be better written using another variable naming, so as to keep it separate from the first one. Hence the second variable is named as "$sqlInner".
It's always better to check for any existence of array elements in an array variable, so I have used the simple checks using the "if" statement.
Hope it helps.
I've determined this to be memory related.
I have a query returning data that looks like this:
Status Total
Success 234
Failed 20
Missing 12
I want to add this to an array which can then be used to populate a google pie chart.
the array would look like this:
array backup = array("Success" => 234),
("Failed" => 20),
("Missing" => 12);
How would I add these item dynamically at each row in a query?
$result = mysql_query(...);
$backup = array();
while ($r = mysql_fetch_assoc($result)) {
$backup[$r['Status']] = $r['Total'];
}
Here's how you can make the Google Charts API call:
$values = implode(',', array_values($backup));
$labels = implode('|', array_keys($backup));
$img = "http://chart.apis.google.com/chart?cht=p3&chd=t:{$values}&chl={$labels}&chs=250x100";
echo "<img src='{$img}' alt='Chart'>";
Assuming this is your query:
SELECT status, total FROM table
Then you can do:
$data = array();
while(($row = mysql_fetch_assoc($result))) {
$data[$row['status']] = $row['total'];
}
If this is not what you mean, please clarify your question and/or provide the code you already have.
I think we need a bunch more information, but in the mean time look at array_merge()
http://www.php.net/manual/en/function.array-merge.php