Working with arrays in Kohana, Blank page? - php

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.

Related

How to stop second foreach from looping more than once

I have an query which select all ids from a table. Once I have all id's, they are stored in an array which I foreach over.
Then there is an second array which pull data from url (around 5k rows) and should update DB based on the id's.
The problem - second foreach is looping once for each ID, which is not what I want. What I want is to loop once for all id's.
Here is the code I have so far
$query = " SELECT id, code FROM `countries` WHERE type = 1";
$result = $DB->query($query);
$url = "https://api.gov/v2/data?api_key=xxxxx";
$api_responce = file_get_contents($url);
$api_responce = json_decode($api_responce);
$data_array = $api_responce->data;
$rows = Array();
while($row = $DB->fetch_object($result)) $rows[] = $row;
foreach ($rows as $row) {
foreach ($data_array as $key => $dataArr) {
$query = "UPDATE table SET data_field = $dataArr->value WHERE country_id = $row->id LIMIT 1";
}
}
The query returns 200 id's and because of than the second foreach (foreach ($data_array as $key => $dataArr) { ... }) execute everything 200 times.
It must execute once for all 200 id's not 200 * 5000 times.
Since the question is aboot using a loop, we will talk about the loop, instead of trying to find another way. Actually, I see no reason to find another way.
->Loops and recursions are great, powerful tools. As usually, with great tools, you need to also find ways of controlling them.
See cars for example, they have breaks.
The solution is not to be slow and sit to horses era, but to have good brakes.
->In the same spirit, all you need to master the power called recursions and loops is to stop them properly. You can use if cases and "break" command in PHP.
For example, here we have a case of arrays containing arrays, each first child of the array having the last of the other (1,2,3), (3,4,5) and we want to controll the loop in a way of showing data in a proper way (1,2,3,4,5).
We will use an if case and a counter :
<?php
$array = array( array(-1,0,1), array(1,2,3,4,5), array(5,6,7,8,9,10), array(10,11,12,13,14,15) );
static $key_counter;
foreach( $array as $key ){
$key_counter = 0;
foreach( $key as $key2 ){
if ( $key_counter != 0 ) {
echo $key2 . ', ';
}
$key_counter = $key_counter + 1;
}
}
Since I dont have access to your DB is actually hard for me to run and debbug the code, so the best I can say is that you need to use an if case which checks if the ID of the object is the ID we want to proccess, then proceed to proccessing.
P.S. Static variables are usefull for loops and specially for recurrsions, since they dont get deleted from the memory once the functions execution ends.
The static keyword is also used to declare variables in a function
which keep their value after the function has ended.

'Grouping' PHP results from an MySQL query

I'm having difficulty achieving this one, so thought I'd ask..
I have a table which contains some field names. Each field entry in the table has a type, a name and an ID as per the norm.
I'd like to be able to group my SQL results so that I can 'print' each type (and the type's associated members) into a table. I tried the following:
$query = "SELECT id,type,opt_name FROM fields ORDER BY type";
$resource = $pdo->query($query);
$results = array();
while ( $row = $resource->fetch() ) {
$type[$row['type']] = $row['opt_name'];
$o_id = clean($row['id'], 'text');
$o_name = clean($row['opt_name'], 'text');
}
foreach ($type AS $o_type => $o_name) {
echo $o_type;
echo "<br>";
foreach (($type) AS $opt_name) {
echo $opt_name;
echo "<br>";
}
}
Please try not to worry too much about the HTML output, it's just for this example to show context.
When the code is executed, it will only print one row. As a result, I have 'print_r' tested both:
$type[$row['type']] = $row['opt_name'];
Which does indeed show only one row in the array. Creating:
$results = $row;
Shows all the data, but too much of it and not in the way I think will work with the 'foreach'.
I'm probably making a rookie mistake here, but can't see it.
Help!
You're going to be overwriting the value of $type['type'] instead of pushing more values onto it with:
$type[$row['type']] = $row['opt_name'];
You most likely want
$type[$row['type']][] = $row['opt_name'];
Then you'll need to fix your loop so you loop through the options, not the types twice.
foreach ($type AS $o_type => $options) {
echo $o_type;
echo "<br>";
foreach ($options AS $opt_name) {
echo $opt_name;
echo "<br>";
}
}

MySQLi Array in PHP sometimes coming up empty

Okay, so I'm pretty much at the end of my rope trying to discover the issue here, because sometimes this code works perfectly, and then sometimes not, so here it is:
$allItems = array();
$allItemsQuery = mysqli_query($conn,"SELECT * FROM cart_items WHERE crt_id='".$row['crt_id']."' AND quantity>0");
while($itemsArray = mysqli_fetch_assoc($allItemsQuery)){
array_push($allItems,$itemsArray['item_id']);
}
$allItemsNames = array();
foreach($allItems as $key => $value){
$itemNames = mysqli_fetch_assoc(mysqli_query($conn,"SELECT * FROM items WHERE id='$value'"));
array_push($allItemsNames, $itemNames['item_name']);
}
$allItemsFinal = array_combine($allItems,$allItemsNames);
$itemsList = 'Items:<br>';
foreach($allItemsFinal as $key => $value){
$itemsList .=''.$value.'<br><br>';
}
The idea is it's supposed to get all of the item ID's the user has in their cart from the DB and put it into an array, which I've established exists, grab all of the item names based on their ID, and put that into an array, and then combine the two arrays as a key and value. Then I output the data from the arrays into a string.
This code works perfectly sometimes, and then suddenly not. Can somebody give me any idea why? I'd be indebted forever.
I think you should throw this code away and use something like this:
$items = array();
$itemsQuery = "SELECT i.item_name, i.item_id
FROM items i WHERE i.item_id
IN (SELECT ci.item_id
FROM cart_items
WHERE crt_id='".$row['crt_id']."'
AND quantity>0
)");
$allItemsQuery = mysqli_query($conn, $itemsQuery);
while ($row = mysqli_fetch_assoc($allItemsQuery))
$items[$row['item_id']] = $items[$row['item_name']];

Reorder array from mysql query

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.

How do I insert values into an multidimensional-array, then show them?

I'm fairly new to php, and I don't know how to work with arrays very well. Here's the deal, I want to add into a multidimensional array three or more values I obtain from my database, then I want to sort them based on the timestamp (one of the values). After that, I want to show all of the sorted values. I can't seem to do this, here's the code
$queryWaitingPatients = 'SELECT ArrivalTime, TargetTime, Order, Classification FROM exams WHERE (CurrentState = "Pending")';
$results = mysql_query($queryWaitingPatients) or die(mysql_error());
if (mysql_num_rows($results) == 0) {
echo '<p>There\'s currently no patient on the waiting list.</p>';
return;
}
while ($rows = mysql_fetch_array($results)) {
extract($rows);
//now is the part that I don't know, putting the values into an array
}
// I'm also not sure how to sort this according to my $TargetTime
asort($sortedTimes);
//the other part I don't know, showing the values,
Thanks for the help!
Well, let's look at your code. First, you have a query that's returning a result set. I don't recommend using mysql_fetch_array because it's not only deprecated (use mysqli functions instead) but it tends to lend itself to bad code. It's hard to figure out what you're referencing when all your keys are numbers. So I recommend mysqli_fetch_assoc (be sure you're fully switched to the mysqli functions first, like mysql_connect and mysqli_query)
Second, I really dislike using extract. We need to work with the array directly. Here's how we do this
$myarray = array();
while ($rows = mysqlI_fetch_assoc($results)) {
$myarray[] = $rows;
}
echo $myarray[0]['ArrivalTime'];
So let's go over this. First, we're building an array of arrays. So we initialize our overall array. Then we want to push the rows onto this array. That's what $myarray[] does. Finally, the array we're pushing is associative, meaning all the keys of the row match up with the field names of your query.
Now, the sorting really needs to be done in your query. So let's tweak your query
$queryWaitingPatients = 'SELECT ArrivalTime, TargetTime, `Order`, Classification
FROM exams
WHERE CurrentState = "Pending"
ORDER BY TargetTime';
This way, when your PHP runs, your database now churns them out in the correct order for your array. No sorting code needed.
$arr = array();
while ($rows = mysql_fetch_array($results)) {
array_push ($arr, $row);
}
print_r($arr);
<?php
$queryWaitingPatients = ' SELECT ArrivalTime, TargetTime, Order, Classification, CurrentState
FROM exams
WHERE CurrentState = "Pending"
ORDER BY TargetTime ';
$results = mysql_query($queryWaitingPatients) or die(mysql_error());
if ($results -> num_rows < 1)
{
echo '<p>There\'s currently no patient on the waiting list.</p>';
}
else
{
while ($rows = mysqli_fetch_array($results))
{
$arrivaltime = $row['ArrivalTime'];
$targettime = $row['targettime'];
$order = $row['Order'];
$classification = $row['Classification'];
echo "Arrival: ".$arrivaltime."--Target time: ".$targettime."--Order: ".$order."--Classification: ".$classification;
}
}
echo "Done!";
//or you could put it in a json array and pass it to client side.
?>

Categories