OOP Issue Stopping PHP Functioning & MySQL Data Array Retrieval Issue - php

Now a very kind StackOverflow use has helped me out with a lot of my issues however there's two remaining probelms with my code before it's ready to go, any ideas would be great as i'm currently screaming at it:
First of all i'm using the following to try and pull data from a MySQL Database, return it as a Numeric Array and Order It By ID. There's 2 items in there and no matter what I do I can only get 1 to display (I need it to display ALL data when the table fills up more):
$query = "SELECT * FROM batch ORDER by ID";
$result = $mysqli->query($query);
/* numeric array */
$row = $result->fetch_array(MYSQLI_NUM);
printf ("%s (%s)\n", $row[0], $row[1]);
?>
Secondly, slightly off topic but this code below was given by a StackOverflow user however I can't get it to work, they've geared it to OOP which is not an area i'm familiar with and no matter what I do to correct the $this-> or public / private it still refuses to work (the aim of the code is to have a number in $userinput which gets checked against the $widgetBatches array for the closest match (i.e. input is 1100 and closest is 1000) this then gets deducted from the input (to leave 100) and the process loops again to check and this time returns 100 as the closest, this process continues until the $userinput reaches 0 or a negative number:
<?php
$userinput = 10000; // Our magic variable - user input
$iterations = 0;
function Widget($userinput)
{
$this->iterations++;
$widgetRequested = $userinput;
$widgetBatches = array("250", "500", "1000", "2000");
echo "Iteration " . $iterations;
echo "<br/>";
echo "Widget requested: " . $widgetRequested;
echo "<br/>";
$closest = GetClosest($widgetBatches, $widgetRequested);
echo "Closest: " . $closest;
echo "<br/>";
$widgetRemaining = $widgetRequested - $closest;
echo "Remainder: " . $widgetRemaining;
echo "<hr/>";
if($widgetRemaining > 0)
{
Widget($widgetRemaining);
}
else
{
echo "The value is now below or equaling zero: " . $widgetRemaining . "!";
}
}
function GetClosest($array, $value)
{
$lowest = null;
foreach($array as $val)
{
if($lowest == null || abs($value - $lowest) > abs($val - $value))
{
$lowest = $val;
}
}
return $lowest;
}
?>

This:
<?php
function Widget($input) {
$currentValue = $input; // Set internal variable from input (Think of this as an initial "remainder")
$i = 0;
$widgetBatches = [250, 500, 1000, 2000]; // Setup batch array
while ($currentValue > 0) { // While the remainder is more than 0
$i++;
echo "Iteration " . $i . "<br/>";
echo "Widget requested: " . $currentValue . "<br/>";
$closest = GetClosest($widgetBatches, $currentValue); // Find the closest value from batch array
echo "Closest: " . $closest . "<br/>";
$currentValue = $currentValue - $closest; // Work out new remainder
echo "Remainder: " . $currentValue . "<hr/>";
}
// Loop will exit when remainder is less than 0
echo "The value is now below or equaling zero: " . $currentValue . "!";
}
function GetClosest($array, $value) {
$result = null; // Innitialise the returned variable in case of failure
foreach($array as $val) { // For every array value, unless stopped
$result = $val; // Set result to current array value
if($value <= $result) break; // Stop foreach loop if value is less than or equal to result
}
return $result; // Return last result from Foreach loop
}
Widget(9000);
?>
Hopefully the comments are useful... I put more detail in than I would usually...

Did you try fetchAll(), I use PDO so not sure, but would suggest you use a while loop, like:
while ($result = $mysqli->query($query));
Or:
foreach($result as $r) then $r['data'];
I'm %100 sure the loop will iterate and pull out every data, which you can send to a table or a list.

Related

Getting the MAX/MIN from a PHP array that has objects

I have a PHP array that is filled like so:
[
{"soldPrice":"228.96","dateSold":"05\/22\/2020"},
{"soldPrice":"204.99","dateSold":"06\/22\/2020"},
{"soldPrice":"399.99","dateSold":"08\/12\/2020"},
{"soldPrice":"350.00","dateSold":"08\/23\/2020"}
]
I was able to find the max by doing max($arr);, but now I added the dateSold. How can I find the min/max of this array, but also get the date that it sold?
It would echo 06/22/2020: 204.99 for min.
It would echo 08/22/2020: 399.99 for max.
I tried to add a function like this just to get the max.
function max_attribute_in_array($data_points, $value='soldPrice'){
$max=0;
foreach($data_points as $point){
if($max < (float)$point->{$value}){
$max = $point->{$value};
}
}
return $max;
}
$max = max_attribute_in_array($mainResponse);
var_dump($max);
but this was a no go.
This just returned int(0)
This gives you the complete entry of the array that has the maximum value:
function max_attribute_in_array($data_points, $value='soldPrice') {
$col = array_column($data_points, $value);
return $data_points[array_search(max($col), $col)];
}
From your example (which possibly has a typo since there's no 08/22/2020 date), it looks like you want the max of a key from the arrays which are within the overall array (in JS you'd say an array of objects).. which you've almost solved:
<?php
$data=[
["soldPrice"=>228.96,"dateSold"=>"05/22/2020"],
["soldPrice"=>204.99,"dateSold"=>"06/22/2020"],
["soldPrice"=>399.99,"dateSold"=>"08/12/2020"],
["soldPrice"=>350.00,"dateSold"=>"08/23/2020"]];
function max_attribute_in_array($arr, $key) {
$max=null;
foreach ($arr as $row) {
if ($row[$key]>$max) {
$max=$row[$key];
}
}
return $max;
}
function min_attribute_in_array($arr, $key) {
$min=count($arr)>0 ? $arr[0][$key] : null;
foreach ($arr as $row) {
if ($row[$key]<$min) {
$min=$row[$key];
}
}
return $min;
}
$maxSoldPrice=max_attribute_in_array($data, 'soldPrice');
$maxDateSold=max_attribute_in_array($data, 'dateSold');
echo $maxSoldPrice.", ".$maxDateSold."\n";
$keys=['soldPrice','dateSold'];
$mins=[];
foreach ($keys as $key)
$mins[$key]=min_attribute_in_array($data,$key);
print_r($mins);
Which should output
399.99, 08/23/2020
Array
(
[soldPrice] => 204.99
[dateSold] => 05/22/2020
)
I've switched the data to PHP arrays, what you've specified as the source looks like JSON, but you can convert JSON to PHP arrays using json_decode($json,true);. Note you could also iterate over the keys of each $row and build the max of each key that way (it would require some structural changes to max_attribute_in_array) - instead of having to specify each key. I've used an iteration approach for the min version just to demonstrate - you could use either (but probably best to be consistent)
Iterate with foreach over it and get min/max and remember the corresponding dates.
<?php
$data=[
["soldPrice"=>228.96,"dateSold"=>"05\/22\/2020"],
["soldPrice"=>204.99,"dateSold"=>"06\/22\/2020"],
["soldPrice"=>399.99,"dateSold"=>"08\/12\/2020"],
["soldPrice"=>350.00,"dateSold"=>"08\/23\/2020"]];
$min = INF;
$max = -INF;
foreach ($data as $elem) {
if ($elem['soldPrice'] > $max) {
$max = $elem['soldPrice'];
$maxDate = $elem['dateSold'];
} elseif ($elem['soldPrice'] < $min) {
$min = $elem['soldPrice'];
$minDate = $elem['dateSold'];
}
}
echo 'Max: ' . $max . ' => ' . $maxDate . '<br>';
echo 'Min: ' . $min . ' => ' . $minDate . '<br>';
This delivers:
Max: 399.99 => 08\/12\/2020
Min: 204.99 => 06\/22\/2020

Sum string length of all array values

<?php
setcookie("Auction_Item", "Luxury Car", time()+2*24*60*60);
if(isset($_COOKIE["Auction_Item"])){
echo "Auction Item is a " . $_COOKIE["Auction_Item"];
} else{
echo "No items for auction.";
}
?>
Okay so this php code simply sets a cookie and gives the value, I need to write a function that after accepting a boolean parameter as TRUE returns the sum of length of all cookies presented into the request.
if ($val = true){
$cookies = $_COOKIE
$strVal = "";
$countVal = count($cookies);
for ($x = 0; $x < $countVal; $x++) {
$strVal = $strVal . $cookies[$x].$val
}
echo 'Sum of length of all cookie values' . strlen($strVal)
I've tried this, but it doesn't seem to work.
The answer from MaryNfs is correct but missing one important thing from your original code. Try the following:
setcookie("Auction_Item", "Luxury Car", time()+2*24*60*60);
if(isset($_COOKIE["Auction_Item"])){
echo "Auction Item is a " . $_COOKIE["Auction_Item"];
} else {
echo "No items for auction.";
}
$val = true; //Set the variable $val
//You had $val = true, setting $val to true.
//You need to evaluate it as true or false so use === to compare
//Using = sets the variable's value
if($val===true) {
$joinedCookies = "";
foreach ($_COOKIE as $key=>$value) {
$joinedCookies = $joinedCookies . $value;
}
$joinedCookiesLength = strlen($joinedCookies);
echo 'Sum of length of all cookie values ' . $joinedCookiesLength;
}
Once the $_COOKIE is set, the above should return:
Auction Item is a Luxury Car
Sum of length of all cookie values 36
Your code was missing ; after three lines which would break things so keep an eye out for that as well.
if I got it right, you can get the length of all cookie values like this:
$joinedCookies = "";
foreach ($_COOKIE as $key=>$value){
$joinedCookies = $joinedCookies.$value;
}
echo 'Sum of length of all cookie values: '.strlen($joinedCookies);
To get the total string length of a flat array, implode() the elements using no glue, then call strlen().
No manual looping, no manual concatenation, and no temporary variables.
echo strlen(implode($_COOKIE));

Breaking out of loop in PHP and resetting the counters

There is some logic error in my code and I am not sure what I am doing wrong here.
Setting up things first, I have a .json file that I am reading which is in this layout:
So the polygon element is at every 1, 3, 5, .. and the school name is one prior to that.
Now I have another .csv file from where I am taking different lat and long values. Basically I have to see if that lat long from the csv file is inside any of these polygons as described in the json file.
Here is my part of the PHP code that takes in the json file and csv file. My logic is that, I take one lat and long value from the CSV and then want to go over each polygon in the json file.
If you follow the code below, I take in the values and when I meet the condition that it is outside a polygon, it just breaks out of the second while loop, takes another set of lat and longs.
$string = file_get_contents("Schools.json", 0, null, null);
$json_a = json_decode($string, true);
$start_row = 4;
$rowID = 1;
$polygonIndex = 1;
$insideCheck = 0;
$file = fopen("ActiveProperty.csv", "r");
while (($row = fgetcsv($file)) !== FALSE){
if($rowID >= $start_row){
$points = array($row[52] . ' ' . $row[49]);
$polygonIndex = 1;
while ($polygonIndex < 454){
$polygon = $json_a[$polygonIndex]['Polygons'];
foreach($points as $key => $point) {
if ($pointLocation->pointInPolygon($point, $polygon) == "outside"){
echo "point " . ($key+1) . " ($point): " . $pointLocation->pointInPolygon($point, $polygon);
echo "<br>";
$polygonIndex = $polygonIndex + 2;
echo $polygonIndex;
$insideCheck = 0;
break;
}
else {
echo $json_a[$polygonIndex - 1];
echo "<br>";
echo "point " . ($key+1) . " ($point): " . $pointLocation->pointInPolygon($point, $polygon);
echo "<br>";
$insideCheck = 1;
break;
}
}
if ($insideCheck = 0) {
echo "out of foreach 0";
continue;
}
else {
echo "out of foreach";
$insideCheck = 0;
break;
}
}
}
$rowID++;
}
Here is a sample output that I have:
Lat and longs in this image is from the csv file.
The expected output should be that with that lat and long, it should go over the polygons in the json and if its inside, return the first element which is the school. Here $polygonIndex just stays 3 which I am guessing is the issue.
If this is still unclear what I am trying to do, please let me know. Thanks.

PHP generator yield the first value, then iterate over the rest

I have this code:
<?php
function generator() {
yield 'First value';
for ($i = 1; $i <= 3; $i++) {
yield $i;
}
}
$gen = generator();
$first = $gen->current();
echo $first . '<br/>';
//$gen->next();
foreach ($gen as $value) {
echo $value . '<br/>';
}
This outputs:
First value
First value
1
2
3
I need the 'First value' to yielding only once. If i uncomment $gen->next() line, fatal error occured:
Fatal error: Uncaught exception 'Exception' with message 'Cannot rewind a generator that was already run'
How can I solve this?
The problem is that the foreach try to reset (rewind) the Generator. But rewind() throws an exception if the generator is currently after the first yield.
So you should avoid the foreach and use a while instead
$gen = generator();
$first = $gen->current();
echo $first . '<br/>';
$gen->next();
while ($gen->valid()) {
echo $gen->current() . '<br/>';
$gen->next();
}
chumkiu's answer is correct. Some additional ideas.
Proposal 0: remaining() decorator.
(This is the latest version I am adding here, but possibly the best)
PHP 7+:
function remaining(\Generator $generator) {
yield from $generator;
}
PHP 5.5+ < 7:
function remaining(\Generator $generator) {
for (; $generator->valid(); $generator->next()) {
yield $generator->current();
}
}
Usage (all PHP versions):
function foo() {
for ($i = 0; $i < 5; ++$i) {
yield $i;
}
}
$gen = foo();
if (!$gen->valid()) {
// Not even the first item exists.
return;
}
$first = $gen->current();
$gen->next();
$values = [];
foreach (remaining($gen) as $value) {
$values[] = $value;
}
There might be some indirection overhead. But semantically this is quite elegant I think.
Proposal 1: for() instead of while().
As a nice syntactic alternative, I propose using for() instead of while() to reduce clutter from the ->next() call and the initialization.
Simple version, without your initial value:
for ($gen = generator(); $gen->valid(); $gen->next()) {
echo $gen->current();
}
With the initial value:
$gen = generator();
if (!$gen->valid()) {
echo "Not even the first value exists.<br/>";
return;
}
$first = $gen->current();
echo $first . '<br/>';
$gen->next();
for (; $gen->valid(); $gen->next()) {
echo $gen->current() . '<br/>';
}
You could put the first $gen->next() into the for() statement, but I don't think this would add much readability.
A little benchmark I did locally (with PHP 5.6) showed that this version with for() or while() with explicit calls to ->next(), current() etc are slower than the implicit version with foreach(generator() as $value).
Proposal 2: Offset parameter in the generator() function
This only works if you have control over the generator function.
function generator($offset = 0) {
if ($offset <= 0) {
yield 'First value';
$offset = 1;
}
for ($i = $offset; $i <= 3; $i++) {
yield $i;
}
}
foreach (generator() as $firstValue) {
print "First: " . $firstValue . "\n";
break;
}
foreach (generator(1) as value) {
print $value . "\n";
}
This would mean that any initialization would run twice. Maybe not desirable.
Also it allows calls like generator(9999) with really high skip numbers. E.g. someone could use this to process the generator sequence in chunks. But starting from 0 each time and then skipping a huge number of items seems really a bad idea performance-wise. E.g. if the data is coming from a file, and skipping means to read + ignore the first 9999 lines of the file.
solutions provided here does not work if you need to iterate more than once.
so I used iterator_to_array function to convert it to array;
$items = iterator_to_array($items);

Checking a value in a basic multidimensional array

This will be a quick one for most of you I'm sure, but I'm banging my head against the wall trying to teach myself multidimensional arrays.
I simply wish to check whether or not $_FILES["Photo"]["name"] contains empty strings, and such the code below my if statement is executed.
Currently this works, as does my else statment (not shown), however there has to be a cleaner way of writing this??
Many thanks.
if (empty($_FILES["Photo"]["name"][0]) && empty($_FILES["Photo"]["name"][1]) && empty($_FILES["Photo"]["name"][2])) {
$query = "INSERT INTO lot (lotnumber, lottitle, lotdescription, datecreated, lastmodified) VALUES" .
"('$lotnumber', '$lottitle', '$lotdescription', NULL, NULL)";
if (!$mysqli->query($query)) {
echo '<p class="warning">Error executing INSERT query: (' . $mysqli->errno . ') ' . $mysqli->error . "</p>";
}
else
{
echo '<p class="success">The lot has been added to the directory.' . "</p>" . HTML_LINEBREAK;
}
}
You could use an array_filter(), but I don't really see the problem with what you are doing:
$test_array = array_filter($_FILES['Photo']['name'], function($var) {
return empty($var);
});
if (count($test_array) === 3) {
$query = ... // the rest of your code
}
Of course this assumes that there are only three elements in the array. If you only want to check the first 3 elements, you would want to add an array_slice() like this:
$test_array = array_filter(array_slice($_FILES['Photo']['name'], 0, 3), function($var) {
return empty($var);
});
I would have a script that counts the keys within the "name" level.
$count = sizeof($name_of_array->Photo->name);
Then in a for loop check to see if the keys are empty.
for($i = 0; $i <= $count; $i++)
{
if(empty($name_of_array->Photo->name[$i])
{
... continue code
}
else
{
... continue code
}
}

Categories