Accessing class instances in an array - php

I'm working on a project, and I've come across an issue that has me stumped. The code below is a class file and a test page to make sure it's working. It's for somebody else who is programming the site, otherwise I would code the JSON output differently. Basically, the person implementing it just has to pull a bunch of data (like below) from a database, and loop through, instantiating a class object for each result, and plugging each instance into an array, and passing the array to the printJson function, which will print the JSON string. Here is what I have:
Results.php
<?php
class Result
{
public $Category = NULL;
public $Title = NULL;
public $Price = NULL;
public function __construct($category, $title, $price)
{
$this->Category = $category;
$this->Title = $title;
$this->Price = $price;
}
public static function printJson($arrayOfResults)
{
$output = '{"results": [';
foreach ($arrayOfResults as $result)
{
$output += '{"category": "' . $result->Category . '",';
$output += '"title": "' . $result->Title . '",';
$output += '"price": "' . $result->Price . '",';
$output += '},';
}
$output = substr($output, 0, -1);
$output += ']}';
return $output;
}
}
?>
getResults.php
<?php
require_once('Result.php');
$res1 = new Result('food', 'Chicken Fingers', 5.95);
$res2 = new Result('food', 'Hamburger', 5.95);
$res3 = new Result('drink', 'Coke', 1);
$res4 = new Result('drink', 'Coffee', 2);
$res5 = new Result('food', 'Cheeseburger', 6.95);
$x = $_GET['x'];
if ($x == 1)
{
$array = array($res1);
echo Result::printJson($array);
}
if ($x == 2)
{
$array = array($res1, $res2);
echo Result::printJson($array);
}
if ($x == 3)
{
$array = array($res1, $res2, $res3);
echo Result::printJson($array);
}
if ($x == 5)
{
$array = array($res1, $res2, $res3, $res4, $res5);
echo Result::printJson($array);
}
?>
The end result is if I go to getResults.php?x=5, it will return $res1 thru $res5 (again, this is just to test, I would never do something like this in production) formatted as JSON. Right now, I get '0' outputted and I cannot for the life of me figure out why. Could my foreach loop not be written properly? Please, any help you could provide would be awesome!

It's because you're using + for concatenation rather than .:
$output .= '{"category": "' . $result->Category . '",';
$output .= '"title": "' . $result->Title . '",';
$output .= '"price": "' . $result->Price . '",';
$output .= '},';
But you should really not construct the JSON yourself, as it leads to a number of errors making for invalid JSON (trailing commas etc). Use something like this instead:
public static function printJson(array $arrayOfResults)
{
$results['results'] = array_map('get_object_vars', $arrayOfResults);
return json_encode($results);
}

Related

PHP loop outputting duplicates

public function select(){
$rows = [];
$connection = $this->connect();
$result = $connection->query("SELECT username FROM users");
while ($row = $result->fetch_assoc()){
$rows[] = $row;
}
$userlist = 0;
foreach($rows as $username){
$userlist .= $username['username'];
}
$get_rankings = [1,2,3,4];
$get_image_path = "images/";
$total = 0;
for ($x = 0; $x < count($get_rankings); $x++){
$total = $get_rankings[$x];
$path .= "<img src = '" . $get_image_path . $total . ".png'>\n" . $userlist . "<br/>";
// echo "<span class = 'align-down'>{$path}";
// echo "<p class = 'user-name'> {$rows['0']}</p>";
// echo "</span>";
}
echo $path;
}
I'm trying to output a simple ranking but using the number index as images to display them.
In the past i've tried to do something similar but couldn't figure out how to match player it with images on the side.
The output im getting is this:
It's outputting each entry 4 times(I get why, its in a loop) but I can't figure out the correct solution to write it outside of a loop or properly
The desired output is:
My DataBase reads as:
[id][username][password]
If there is an easier solution, i'm all ears. I don't know how to approach this.
There's no need for $userlist. Output the username from $rows[$x].
$path = "";
$max = min(count($rows), count($get_rankings));
for ($x = 0; $x < $max; $x++){
$total = $get_rankings[$x];
$path .= "<img src = '" . $get_image_path . $total . ".png'>\n" . $rows[$x]['username'] . "<br/>";
// echo "<span class = 'align-down'>{$path}";
// echo "<p class = 'user-name'> {$rows['0']}</p>";
// echo "</span>";
}

php array values not being pushed onto associative array

I wrote a javascript function which takes in a string and parses it as an associative array.
function getValues(string){
var array_values = new Array();
var pairs_array = string.split('\n');
if(pairs_array[0] == 'SUCCESS'){
window.success = true;
}
for(x=1; x< pairs_array.length; x++){
var parsedValue = '';
//console.log(pairs_array[x] + "<br>");
var pair = pairs_array[x].split('=');
//console.log(pair[1]);
var variable = pair[0];
if(pair[1]){
var value = pair[1];
for(i=0; i< value.length; i++){
var character = value.charAt(i);
if(character == '+'){
parsedValue = parsedValue + character.replace('+', ' ');
}else{
parsedValue = parsedValue + value.charAt(i);
}
}
array_values[variable] = decodeURIComponent(parsedValue);
}else{
array_values[variable] = '';
}
}
return array_values;
}
Then the function is called on the string window.name_value_pairs as follows
var array_callback = getValues(window.name_value_pairs);
for(x in array_callback){
console.log("call" + x + " " + array_callback[x]);
}
Works fine. Now i have been trying to write the function in php because i would prefer it on the server side but it is not working out. I'm not sure if the array values ar getting pushed onto the array because nothing gets returned. heres the php code i have tried:
Note: $results_values is a string
$result_values = $_REQUEST['result_values'];
echo "php array " . getValuesPhp($result_values);
function getValuesPhp($string){
$array_values = array();
$pairs_array = explode("\n",$string);
if($pairs_array[0] == 'SUCCESS'){
$success = true;
echo "TRUE";
}
for($x=1; $x< count($pairs_array); $x++){
$parsedValue = '';
$pair = explode("=",$pairs_array[$x]);
$variable = $pair[0];
if(isset($pair[1])){
$value = $pair[1];
for($i=0; $i< strlen($value); $i++){
$character = $value[$i];
//echo "char \n" . $character;
if(strpos($character, '+') !== false){
//echo "plus";
$parsedValue .= str_replace('+', ' ', $character);
}else{
//echo "hi2";
$parsedValue .= $value[$i];
}
}
echo "\n var " . $variable;
echo "\n parsed " . $parsedValue;
$array_values['" . $variable . "'] = $parsedValue;
//echo "arrayValues " . $array_values['" . $variable . "'];
//array_push($GLOBALS[$array_values]['" . $variable . "'], $parsedValue);
}else{
$array_values['" . $variable . "'] = '';
//array_push($GLOBALS[$array_values]['" . $variable . "'], '');
}
}
//echo "array payment stat" . $array_values['payment_status'];
return $array_values;
}
note: where it says $array_values['" . $variable . "'] this does print out the write result as it goes through the loop however it seems like the array elements are not being added to the array as nothing is returned at the end.
Thanks for any help
Sarah
Update:
#ChrisWillard I would like to return an associative array from the string. the string is in the format where each line is in the form key=value .. it is actually the string which comes back from a paypal pdt response. For example:
SUCCESS
mc_gross=3.00
protection_eligibility=Eligible
address_status=confirmed
item_number1=3
tax=0.00
item_number2=2
payer_id=VWCYB9FFJ
address_street=1+Main+Terrace
payment_date=14%3A26%3A14+May+22%2C+2014+PDT
payment_status=Completed
charset=windows-1252
address_zip=W12+4LQ
mc_shipping=0.00
mc_handling=0.00
first_name=Sam
address_country_code=GB
address_name=Sam+Monks
custom=
payer_status=verified
business=mon%40gmail.com
address_country=United+Kingdom
num_cart_items=2
mc_handling1=0.00
mc_handling2=0.00
address_city=Wolverhampton
payer_email=monks%40gmail.com
mc_shipping1=0.00
mc_shipping2=0.00
tax1=0.00
tax2=0.00
txn_id=3PX5572092U
payment_type=instant
last_name=Monks
address_state=West+Midlands
item_name1=Electro
receiver_email=mon%40gmail.com
item_name2=Dub
quantity1=1
quantity2=1
receiver_id=WHRPZLLP6
pending_reason=multi_currency
txn_type=cart
mc_gross_1=1.00
mc_currency=USD
mc_gross_2=2.00
residence_country=GB
transaction_subject=
payment_gross=3.00
thanks for all your answers and help. it was a combination of two things that caused it to not print.. firstly my silly syntax error (being just new at programming haha I wont go into the logic i had behind this but it did make sense to me at the time haha) $array_values['" . $variable . "'] = $parsedValue; changed to this:
$array_values[$variable] = $parsedValue;
it was also the line
echo "php array" . getValuesPhp($result_values); that caused it not to print.
when i changed this to
print_r(getValuesPhp($result_values)); it printed perfect thanks to #ChrisWillard for this. So here is my final code. A combination of #ChrisWillard answer and #Mark B and #Jdo answers. I also wanted to check first if pair[1] existed and go through each character of pair[1] changing any '+' to a space ' ' if it existed so that it could be read by the user. Now i have found the function to do this for me haha. I'm sure it is not new information for a lot of you but for anyone who doesn't know it is urldecode so you can see below ive commented out the loop that i did not need (going through the characters of the string changing the plus value) and instead ive written: $finished_array[$key] = urldecode($value); thanks for all your help.
$result_values = $_REQUEST['result_values'];
print_r(getValuesPhp($result_values));
function getValuesPhp($string){
$finished_array = array();
$pairs_array = explode("\n",$string);
if($pairs_array[0] == 'SUCCESS'){
$success = true;
//echo "TRUE";
}
for($x=1; $x< count($pairs_array); $x++){
$parsedValue = '';
$pair = explode("=",$pairs_array[$x]);
$key = $pair[0];
if(isset($pair[1])){
$value = $pair[1];
//for($i=0; $i< strlen($value); $i++){
//$character = $value[$i];
//if(strpos($character, '+') !== false){
//$parsedValue .= str_replace('+', ' ', $character);
//}else{
//$parsedValue .= $value[$i];
//}
//}
$finished_array[$key] = urldecode($value);
}else{
$finished_array[$key] = '';
}
}
return $finished_array;
}
This is totally non-sensical:
$array_values['" . $variable . "'] = $parsedValue;
You're literally using " . $variable . " as your array key - remember that '-quoted strings do NOT expand variables.
Why not just
$array_values[$variable] = $parsedValue
From what I can gather, this should get you what you need:
$result_values = $_REQUEST['result_values'];
print_r(getValuesPhp($result_values));
function getValuesPhp($string){
$finished_array = array();
$pairs_array = explode("\n",$string);
if($pairs_array[0] == 'SUCCESS'){
$success = true; ////Not sure what you're trying to do here
}
for($x=1; $x< count($pairs_array); $x++) {
$pair = explode("=",$pairs_array[$x]);
$key = $pair[0];
$value = $pair[1];
$finished_array[$key] = $value;
}
return $finished_array;
}

var_export prettifier / visualizer

I'm using var_export to dump output to logs when errors occur. However since the result is in pure text, I don't get a chance to push it through some sort of library like krumo so I can interactively explores the output.
What methods do people have to deal with making var_export text more readable?
Here is my function, it works well for multidimensional arrays:
function VE($varname, $varval, $short_syntax=true, $tag = ' ', $comma='', $end_line="\r\n") {
$res = '';
if($short_syntax){
$begin_array = '[';
$end_array = ']';
} else {
$begin_array = 'array(';
$end_array = ')';
}
$arr = explode('/',$varname);
$dim =count($arr)-1;
$lastKey = end($arr);
if (! is_array($varval)){
if( is_string($varval)) $varval = "'$varval'";
$res .= str_repeat($tag,$dim) . $lastKey . ' => ' . $varval . $comma . $end_line;
}else{
$res .= str_repeat($tag,$dim) . $lastKey . ' => ' . $begin_array . $end_line;
$count_varval = 0;
$dim_varval = count($varval);
foreach ($varval as $key => $val){
$count_varval++;
if($count_varval<$dim_varval) $commma=','; else $commma='';
if( is_string($key)) $key = "'$key'";
$res .= VE ($varname . "/" . $key , $val, $short_syntax, $tag, $commma);
}
$res .= str_repeat($tag,$dim) . $end_array . $comma . $end_line;
}
return $res;
}
$bigarray = array(); // your array
$bb = VE ('$bigarray', $bigarray);
echo "<pre>$bb</pre>";
I hope it helps ;)

PHP implode with increment value

Is there any way to add an increment value while imploding an array?
This is the piece of code I'd like to have the increment value:
$entries = '<ul class="repeatData"><li class="listEntry1">' . implode('</li><li class="listEntry'. $countme .'">', $data) . '</li></ul>';
I'd like somehow to make the variable $countme increment every time it implodes each array value, if this is even possible.
You cannot do this with implode, but look into applying an anonymous function to the array. You can probably do what you want with not much more code.
$entries = '<ul class="repeatData">';
$countme = 1;
array_walk($data, function ($element) use (&$entries, &$countme) {
$entries .= '<li class="listEntry'. $countme .'">'. $element . '</li>';
$countme++;
});
$entries .= "</ul>";
Explanation: I have written an anonymous function, told it about $entries and $counter (so it is a closure, in fact) so that it can modify them from inside its scope, and passed it to array_walk, which will apply it to all elements of the array.
There is no built in function for that. You have to write your own:
This function generalizes the problem and takes an array of glues and the data as arguments. You may refine it to fit more to your needs...
function custom_implode($glues, $pieces) {
$result = '';
while($piece = array_shift($pieces)) {
$result .= $piece;
$glue = array_shift($glues);
if(!empty($pieces)) {
$result .= $glue;
}
}
return $result;
}
Usage:
$glues = array();
for($i = 0; $i < $end; $i++) {
$glues []= '</li><li class="listEntry'. $i .'">';
}
echo custom_implode($glues, $data);
You can save the for loop which populates $glues if you customize the function a little bit more:
function custom_implode($start, $pieces) {
$result = '';
$counter = $start;
while($piece = array_shift($pieces)) {
$result .= $piece;
if(!empty($pieces)) {
$result .= '</li><li class="listEntry'. $counter .'">';
}
}
return $result;
}
To expand upon #ravloony's answer, you can use a mapping function with a counter to produce what you want, the following function could assist.
function implode_with_counter($glue, $array, $start, $pattern) {
$count = $start;
$str = "";
array_walk($array, function($value) use ($glue, $pattern, &$str, &$count) {
if (empty($str)) {
$str = $value;
} else {
$str = $str . preg_replace('/' . preg_quote($pattern, '/') . '/', $count, $glue) . $value;
$count++;
}
});
return $str;
}
Example use:
echo implode_with_counter(' ([count]) ', range(1,5), 1, '[count]');
// Output: 1 (1) 2 (2) 3 (3) 4 (4) 5
For your case:
$entries = '<ul class="repeatData"><li class="listEntry1">'
. implode_with_counter('</li><li class="listEntry[countme]">', $data, 2, '[countme]')
. '</li></ul>';
Update: Alternative
An alternative approach is to just implement a callback version of implode(), and provide a function. Which is a little more universally usable, than the pattern matching.
function implode_callback($callback, array $array) {
if (!is_callable($callback)) {
throw InvalidArgumentException("Argument 1 must be a callable function.");
}
$str = "";
$cIndex = 0;
foreach ($array as $cKey => $cValue) {
$str .= ($cIndex == 0 ? '' : $callback($cKey, $cValue, $cIndex)) . $cValue;
$cIndex++;
}
return $str;
}
Example use:
echo implode_callback(function($cKey, $cValue, $cIndex) {
return ' (' . $cIndex . ') ';
}, range(1,5));
// Output: 1 (1) 2 (2) 3 (3) 4 (4) 5
Your case:
$entries = '<ul class="repeatData"><li class="listEntry1">'
. implode_callback(function($cKey, $cValue, $cIndex) {
return '</li><li class="listEntry' . ($cIndex + 1) . '">';
}, $data)
. '</li></ul>';
No, implode doesn't work that way.
You will need to create your own function to do that.
You should also consider if this is what you really need. In both Javascript and CSS you can easily reference the n-th child of a node if you need to do that.

Fetch specific field from a MySQL result array

I’m trying to retrive the field media_file from the first line of the query.
I don’t figure how to do that. I’ve tried several times to get it by calling the multidimensional array $pages[0]['media_file'] with no success.
I’m trying to have the first image of a series bigger and then append the other thumbs.
Here the page that we are talking about: http://www.svarnet.it/index.php?/works/svarnet-dream/
this is the code:
function createExhibit()
{
$OBJ =& get_instance();
global $rs;
$pages = $OBJ->db->fetchArray("SELECT *
FROM ".PX."media, ".PX."objects_prefs
WHERE media_ref_id = '$rs[id]'
AND obj_ref_type = 'exhibit'
AND obj_ref_type = media_obj_type
ORDER BY media_order ASC, media_id ASC");
$s = "<div id='text-container'>\n";
$s .= $rs['content'];
$s .= "</div>\n";
$s .= "\n<div class='cl'><!-- --></div>\n";
if (!$pages) return $s;
foreach ($pages as $height)
{
$height = getimagesize(DIRNAME . GIMGS . "/th-$height[media_file]");
$find_smallest_height[] = $height[1];
}
sort($find_smallest_height, SORT_NUMERIC);
rsort($find_smallest_height);
$lowest = array_pop($find_smallest_height);
$i = 1; $a = '';
foreach ($pages as $go)
{
$a .= "\n<a class='group' rel='group' href='" . BASEURL . GIMGS . "/$go[media_file]' title='$go[media_title]'><imgXXX src='" . BASEURL . GIMGS . "/th-$go[media_file]' alt='$go[media_caption]' height='80px' /></a>\n";
$i++;
}
// images
$s .= "<div id='img-container'>\n";
// //////////////// HERE I WANT TO INSERT THE FIRST IMAGE OF THE QUERY
$s .= "<imgXXX src='" . BASEURL . GIMGS . $pages['media_file'] . "' alt='$pages[media_title]' />";
// THEN APPEND THE OTHERS IN THUMB FORMAT
$s .= $a;
$s .= "</div>\n";
return $s;
}
Thanks in advance!
You cannot access your $height['media_file'] variable inside double quoted strings like that. You will either use the complex syntax with curly braces:
"/th-{$height['media_file']}"
"/th-${height['media_file']}"
Or you use the string concatenation operator .:
"/th-".$height['media_file']

Categories