I have an array of names that I'd like to convert to variables. These are names of tests generated from a database (so if a new test is added a new index would be added to the array), our tests are updated on a regular basis so I don't want to hard-code my variables, I want to generate them dynamically.
I've tried this code:
$data = array();
foreach($tests as $v) {
$$v = ${};
array_push($data, $v);
}
My aim is to create the variables dynamically and then add to them for each instance of a test being taken, for example, if 6 people have had one of our instant tests, the variable 'instant' will have the value 6. Am I on the right track? Thanks!
***** UPDATE *****
Im trying to populate a morris.js chart using these variables, everything works when hard coded like so:
$pos = 0;
$neg = 0;
$pen = 0;
$cont = 0;
$misc = 0;
foreach ($data as $item) {
if ($item['result'] === 'Positive') {
$pos++;
} elseif ($item['result'] === 'Negative') {
$neg++;
} elseif ($item['result'] === 'Pending') {
$pen++;
} elseif ($item['result'] === 'Contact the Clinic') {
$cont++;
} else {
$misc++;
}
}
$res = array("Positive"=>$pos, "Negative"=>$neg, "Pending"=>$pen, "Contact the Clinic"=>$cont, "Misc"=>$misc);
$data = json_encode($res);
This gives me:
But im tryng to populate it dynamically from our databases so that if a new test / result set is added I don't have to go in and manually update the code, This is giving me data but no values as im not sure how to dynamically create variables based on the data:
/* Create dynamic variables: */
$vars = array();
foreach($tests as $k => $v) {
array_push($vars, $v);
$$v = extract($vars);
/* Loop through each instance and create a count for all matching instances */
foreach($data as $item){
if($item['name'] === $k){
${$v}++;
}
}
}
Is giving me the labels but with no value:
{"Positive","Negative","Pending","Contact the Clinic","Misc"}
Im currently using the Codeigniter (latest release) Cheers
Well if you use mysqli, you could do it like this:
// your query stuff:
$stmt->query($query);
$data = $stmt->fetch_assoc();
// just for example data contains:
// array('id'=>1,'name'=>'Andy')
foreach($data as $field => $value) {
${$field} = $value;
}
// then output:
echo $name; // should output 'Andy';
What about double dollar ?
You can read it here
http://php.net/manual/en/language.variables.variable.php
Related
I am trying to modify phpgraphlib so that I can generate a legend when multiple bar colors are used. I added an array with colors as optional parameter in generateLegend() but it doesn't seem to work. I don't know what's wrong. I have no prior experience with PHP, but it seemed to me passing an array as optional parameter must be possible
Here is my code:
protected function generateLegend(array $colors = array())
{
// here is some code
if($this->bool_multi_color_bars) {
// gets here
if (!empty($colors)) {
// doesn't get here
$index = 0;
foreach($colors as $key => $item) {
// here is some code that creates the colored boxes
$index++;
}
}
}
}
And here is the code that calls the function:
$colors = array();
foreach($data as $key => $value) {
if($value < 3) {
$colors[$key] = 'green';
}
elseif($value < 8) {
$colors[$key] = 'orange';
}
else {
$colors[$key] = 'red';
}
}
$graph->setBarColors($colors);
$graph->setLegend(true, $colors);
$graph->createGraph();
EDIT: generateLegend() is called with the follwing code:
if ($this->bool_legend) {
$this->generateLegend();
}
For the sake of readability I left most of the code out, but I can see that the method is called (therefore I added the comments where the code does get and not)
I'm not sure, what you actually want. What you currently see is the expected behavior of empty. An array without elements is empty.
var_dump(empty([])); // true
If you want to test, if the optional param was actually set, you could use func_num_args.
if (func_num_args() > 0) {
// $colors was set
}
Or use an other default argument and test against the type.
function foo(array $bar = null) {
if ($bar === null) {
// ...
}
}
So a bit of background information is I'm creating a web app and I have 50~ arrays that I'm currently using what I get from an API, I've created a script to find the arrays that I don't need lets call them "bad arrays" but the problem is I'm unsure how I can filter these arrays out with the method I'm using to search through them
I'm searching through them with this script
$tagItems = [];
foreach($tags['items'] as $item) {
if (!$item['snippet']['tags'] || !is_array($item['snippet']['tags'])) {
continue;
}
foreach($item['snippet']['tags'] as $tag) {
$tag = strtolower($tag);
if (!isset($tagItems[$tag])) {
$tagItems[$tag] = 0;
}
$tagItems[$tag]++;
}
}
But let's say I didn't want it to include the 8th array and the 15th array
$tags['items'][8]['snippet']['tags'];
$tags['items'][15]['snippet']['tags'];
I want these to be removed from the original $tags array. How can i achieve this?
EDIT: This needs to be dynamic. I do not know if there are going to be 45/50 arrays that will need removing or just 2/50. the array that needs removing can be reffered to as $index
I have a script which determines what array(s) need to be removed
$i = 0;
while ($i <= 50) {
$x = 0;
while ($x <= 50) {
if ($tags['items'][$i]['snippet']['channelId'] == $tags['items'][$x]['snippet']['channelId']) {
if ($x < $i) {
break;
} else {
echo $x.", ";
break;
}
}
$x++;
}
$i++;
}
I'm going to edit this a little more to provide some extra information that may be useful. My overall goal is to use the YouTube API to remove all but the first array of tags where the channel id appears multiple times. I'm using a script which finds all the array numbers that dont need to be removed an URL.
You can check for the array key
$tagItems = [];
$toRemove = array(8,15);
foreach($tags['items'] as $key => $item) {
if(in_array($key,$toRemove)){
continue;
}
if (!$item['snippet']['tags'] || !is_array($item['snippet']['tags'])) {
continue;
}
foreach($item['snippet']['tags'] as $tag) {
$tag = strtolower($tag);
if (!isset($tagItems[$tag])) {
$tagItems[$tag] = 0;
}
$tagItems[$tag]++;
}
}
In php I am converting posted data from a form to objects like this:
<?php
...some code...
$post = new stdClass;
foreach ($_POST as $key => $val)
$post->$key = trim(strip_tags($_POST[$key]));
?>
Then in my page I just echo posted data like this :
<?php echo $post->Name; ?>
<?php echo $post->Address; ?>
etc...
This works fine but I have multiple checkboxes that are part of a group and I echo the results of that, like this:
<?php
$colors = $_POST['color_type'];
if(empty($colors))
{
echo("No color Type Selected.");
}
else
{
$N = count($colors);
for($i=0; $i < $N; $i++)
{
echo($colors[$i] . ", ");
}
}
?>
That works when I am just using array, but how do I write this as object syntax?
using your code
function array_to_object($arr) {
$post = new stdClass;
foreach ($arr as $key => $val) {
if(is_array($val)) {
$post->$key = post_object($val);
}else{
$post->$key = trim(strip_tags($arr[$key]));
}
}
return $post;
}
$post = array_to_object($_POST);
or more complex solution
function arrayToObject($array) {
if(!is_array($array)) {
return $array;
}
$object = new stdClass();
if (is_array($array) && count($array) > 0) {
foreach ($array as $name=>$value) {
$name = strtolower(trim($name));
if (!empty($name)) {
$object->$name = arrayToObject($value);
}
}
return $object;
}
else {
return FALSE;
}
}
from http://www.richardcastera.com/blog/php-convert-array-to-object-with-stdclass
why would you want that? What's wrong with an array?
Use Object Oriented Programming, which might be what you are looking for. Treat it as an object, by making a class called Color and doing $colors[$i] = new Color();
This way you can do whatever you want with it, and add functions to it.
Pretty simple -- when you attach the color_type key to your object, it'll become an array that's a property of your object. This is most likely what you want: you probably won't want to turn that array into its own stdClass-based object, because then you won't be able to iterate through all the values (as easily). Here's a snippet:
<?php
// putting in both of these checks prevents you from throwing an E_WARNING
// for a non-existent property. E_WARNINGs aren't dangerous, but it makes
// your error messages cleaner when you don't have to wade through a bunch
// of E_WARNINGS.
if (!isset($post->color_type) || empty($post->color_type)) {
echo 'No colour type selected.'; // apologies for the Canadian spelling!
} else {
// this loop does exactly the same thing as your loop, but it makes it a
// bit more succinct -- you don't have to store the count of array values
// in $N. Bit of syntax that speeds things up!
foreach ($post->color_type as $thisColor) {
echo $thisColor;
}
}
?>
Hope this helps! Of course, in a real-life setting, you'll want to do all sorts of data validation and cleaning -- for instance, you'll want to check that the browser actually passed an array of values for $_POST['color_type'], and you'll want to clean the output in case someone is trying to inject an exploit into your page (by going echo htmlspecialchars($thisColor); -- this turns all characters like < and > into HTML entities so they can't insert JavaScript code).
I'm going crazy, spent a couple of hours trying different methods in replace values in arrays, but I can't get it to work.
foreach($potentialMatches as $potentialKey)
{
$searchKeywordQuery = "SELECT keyword, id FROM picture WHERE id='$potentialKey'";
$searchKeywords = mysql_query($searchKeywordQuery) or die(mysql_error());
while ($searchKeyWordsRow = mysql_fetch_array($searchKeywords))
{
$keyword = $searchKeyWordsRow['keyword'];
$pictureKeywordArray[$searchKeyWordsRow['id']]['keywords'] = explode(",", $keyword);
$pictureKeywordArray[$searchKeyWordsRow['id']]['match'] = 4;
}
}
foreach($pictureKeywordArray as $key = > $picValue)
{
foreach($picValue['keywords'] as $key = > $picIdValue)
{
if ($picIdValue == $searchIdKey)
{
echo $picValue['match'];
$picValue['match']++;
echo $picValue['match'];
}
}
}
foreach($pictureKeywordArray as $key = > $picValue)
{
echo $picValue['match'];
}
I'm novice as you can see, When I echo the picValue['match'] in the foreach loop it gives me a correct value after "++". But then below when I call the array again it gives me the value of 4 instead of 5 as intended. Thanks in advance for any help with this.
Cause you work with the item copy in first case try $pictureKeywordArray[$key]['match'] instead of $picValue['match']
In that second foreach you need to call it by reference:
foreach($pictureKeywordArray as $key => &$picValue)
{ //^-- `&` makes it by reference
foreach($picValue['keywords'] as $key => $picIdValue)
{
if ($picIdValue == $searchIdKey)
{
echo $picValue['match'];
$picValue['match']++; //now updates what you want it to update
echo $picValue['match'];
}
}
}
foreach works on a copy of the data. You must use a reference to modify the original:
foreach ($foo as $i => &$f)
{
$f++;
}
unset($f); // important to do this if you ever want to reuse that variable later
I am using PHP. I need to implement the following logic:
My $List has the following data:
array('id' =>'1','flag'=>'1','place1' =>'val2' ,'place2'=>'val3')
array('id'=> '1','flag'=>'0','place1' =>'val3' ,'place2'=>'val7')
array('id'=> '1','flag'=>'0','place1' =>'val4' ,'place2'=>'val8')
array('id'=> '1','flag'=>'0','place1' =>'val5' ,'place2'=>'val9')
array('id'=> '2','flag'=>'1','place1' =>'val10','place2'=>'val11')
array('id'=> '3','flag'=>'1','place1' =>'val11','place2'=>'val14')
My logic:
if (flag == 0){
Store the values of place1 ,Place2
in the Index of id
/*example
$store[1]= {place1}+{place2}
hence output:
store[1]= {val3+val4+val5}+{val7+val8+val9}
similarly
store[2]= empty
store[3]= empty
*/
}
else{
Print the Values of place1,place2 of its index
/* example
print place1[1]="val2" ,place2[1]='val3'
place1[2]="val10",place2[2]='val11'
place1[3]="val11",place2[3]='val14'
*/
}
My partial snippet has:
foreach ($List as $key => $val)
{
if($val['flag']!==0){
//how to implementation
}
else{
echo '$val['place1']'.'$val['place2']';
}
}
What is the best way to proceed?
Assumed that you actually have numeric values in place1 and place2 and thus commutative addition is allowed. If you really have text and need the braces, then I would join the two parts with another pass over store later (but then I would not understand the {0}+{0}).
I tried to keep your quotation marks in the else part. Not tested at all.
$store = array();
foreach ($List as $key => $val)
{
$id = $val['id'];
if (!array_key_exists($id, $store)) {
$store[$id] = 0;
}
if ($val['flag'] == 0) {
$store[$id] += $val['place1'];
$store[$id] += $val['place2'];
} else {
printf("place1[%d]=\"%s\",place2[%d]='%s'\n", $id, $val['place1'], $id, $val['place2']);
}
}
There is a nice function for filtering data out of an array: array___filter. The function requires a callback function, a function that will make the decision whether an element should stay in the array. We create a filter function using create_function and extract the interesting part of the array.
$reducingFunction = create_function('$value', 'return $value["flag"] == 0;');
$reduced = array_filter($list, $reducingFunction);
The next neat function (array_walk) is one that transforms the elements of our array (i.e. $value = $value['param1']), so we create another callback function:
$extractingFunction = create_function('&$value, $key, $index', '$value = $value[$index];');
$valuesParam1 = $reduced;
$valuesParam2 = $reduced;
array_walk($valuesParam1, $extractingFunction, 'param1');
array_walk($valuesParam2, $extractingFunction, 'param1');
Now we have two arrays containing all the data we need:
$store = array(1 => implode('', $valuesParam1).implode('', $valuesParam2));
I don't seem to understand what you want the array $store to contain else. Or what the else-branch should do, so this would require further explanation.
The code newbie friendly :
$store = array(); // Don't forget to initialize your vars
foreach ($List as $key => $val)
{
if ($val['flag']==0)
{
// we check if $store[$val['id']] contains any value first and set it to zero
if (isset($store[$val['id']]))
{
// we add the previous value with the new one
$store[$val['id'] = $store[$val['id']] + $val['place1'] + $val['place2'];
}
else
{
// first time seeing this id, we set the value to 0
$store[$val['id']] = 0;
}
}
else
{
echo '$val['place1']'.'$val['place2']'."\n"; // adding line break (use </ br> if in a web browser)
}
}
I didn't get if "flag" should be 0 or not, so tweak it on.
Version 2 :
If "flag" is just used for boolean logic, you'd may just replace the above code with :
if (!$val['flag'])
Then you can use PHP shortcuts to sum up :
$store[$val['id'] += $val['place1'] + $val['place2'];
Bracelets are not required for one line operations :
if (isset($store[$val['id']]))
$store[$val['id'] = $store[$val['id']] + $val['place1'] + $val['place2'];
else
$store[$val['id']] = 0;
And you don't need the "$key" var either.
So the code becomes :
$store = array();
foreach ($List as $val)
if (!$val['flag'])
if (isset($store[$val['id']]))
$store[$val['id'] += $val['place1'] + $val['place2'];
else
$store[$val['id']] = 0;
else
echo '$val['place1']'.'$val['place2']'."\n";
Version 3 :
if / else/ set operations can be shorten using the ternary operator (beware it's less readable and slower):
$store[$val['id'] = isset($store[$val['id']]) ? 0 : $store[$val['id']] + $val['place1'] + $val['place2'];
So the code becomes :
$store = array();
foreach ($List as $val)
if (!$val['flag'])
$store[$val['id'] = isset($store[$val['id']]) ? 0 : $store[$val['id']] + $val['place1'] + $val['place2'];
else
echo '$val['place1']'.'$val['place2']'."\n";
Pro version
Once you get this one, check soulmerge's code. It is really smarter to use fonctional programming when you can since it's smaller, and result can be piped to each others, so the code is more reusable. What's more, using generators consume often less memory.