Storing PHP syntax in variables - php

Is it possible to store PHP syntax in variables for later use and repetition like this:
$ifStart = "if(";
$ifEnd = "){ echo 'Test'; }";
$ifStart 'A' == 'B' $ifEnd;
Edit: What I'm trying to accomplish is this:
I have 3 form fields, and when the PHP script is loaded, any of the three can be set. None can be set, two, one... So I need some way to determine how many are set and what to output according to that. That's why.
Edit: Right, so I have one HTML Select and two text input fields. My script checks if those fields are set (isset) and does some code accordingly, putting information into arrays etc. What I want to do now though, is to check if the variables have been set one by one, so I can output the correct results which I have stored in arrays.
New edit: This is obviously so hard to explain. But imagine a search engine where you decide which fields you'd like to fill out and then the script checks which fields are set and loops through the array with all the results, only gathering out the elements with sub-elements corresponding to the requested search, that's what I'm trying to achieve.
Here's the array design with AGE and COUNTY selected/set in the POST (hence why there's no [city] elements:
Array
(
[1] => Array
(
[id] => 1
[age] => 19
[county] => 4353
)
[2] => Array
(
[id] => 2
[age] => 20
[county] => 4020
)
[3] => Array
(
[id] => 3
[age] => 30
[county] => 4020
)
)
Still trying to figure out how to only select out a specific array element depending on -its- contents. For example, I have an array like this:
Array ( 1: [age][county], 2: [age][county], 3: [age], 4: [county], 5: [age][county] )
I'd then like to only select the IDs containing both age and county, in this example ID 1, 2 and 5.
Edit: It'll be similar to a SQL query: WHERE age AND county, only this is in an array

It is possible...
BUT
if you have to do it, there's definitely something wrong with your design!
[Edit after your edit]
Your edit shows me that I was right. What you're trying to do, can be accomplished in a better way!
So if I understand you correctly, you want to alter your output according to which form fields have been filled/answered by the user. So far you are storing some values from the $_POST array in another array. In order to generate your output, it would be best to loop over that array and concatenate strings, depending on what has been filled.
foreach ($myArray as $formField => $value)
{
//do something for each $formField, depending on the $value
}
If that still leaves you puzzled, comment here.
The way you wrote it, it would not work, you would need to use eval(). The use of eval() , is in most cases bad practice. That would not be the main problem though, the main problem is, that such code is hard to read, hard to debug as well as maintain and hard to document. All it all, it is bad practice and will lead to a bad solution and more problems.

One clean way (clean because it avoids eval()) to do relatively dynamic code would be to store either a function name or, after php 5.3, a function reference.
E.g. something like:
$callback = "truth_check";
$condition_result = ($a == $b);
if(is_callable($callback)){
$callback($condition_result);
}
See a running example here: http://ideone.com/1SBYS
In your case the callback could be a result to run, e.g. "print_message_on_true_input" as some comparison function and the input could be the result of a conditional tested anywhere in your code, e.g. $print = (false || $a == $b);
Give your specific use cases, though, because 90% of the time intended behavior can be acheived much less fragily without resorting to any dynamic code at all.

Is it possible? Yes, using eval.
Should you do it? NO NO NO NO PLEASE DON'T.

No. You can use functions instead.
function my_compare($a, $b, $symbol = '==') {
eval('$result = $a ' . $symbol . ' $b;');
if ($result) echo 'Test';
}
// ...
my_compare('A', 'B');

Keep in mind the comments above that warn you about this idea!
But you could probably do this:
$ifStart = "if(";
$ifEnd = "){ echo 'Test'; }";
eval( " {$ifStart} 'A' == 'B' {$ifEnd} " );

Ok, so what you need has little relation to the dynamic code involved in your original question, so I'm going to start over and propose a different approach entirely:
//INITIALIZE
//get your input variables, defaulting to null
$inputs = array('select'=>#$_REQUEST['select_name'], 'input1'=>#$_REQUEST['input_1_name'], 'input2'=>#$_REQUEST['input_2_name']);
// initialize your output variables
$out1 = $out2 = $out3 = null;
//MANIPULATIONS
//perform actions based on the presence of variables in the array
if($inputs['select'] == 'whatever'){
$out1 = 'select was '.htmlentities($inputs['select']);
}
// .... perform more manipulations, setting output strings ...
// OUTPUT SECTION
echo $out1.$out2.$out3;

Related

Loop Columns in Recordset

Please understand this is not how I would have designed this, nor is it the proper way to do something like this.
However, since I was given this task, and have absolutely no way around the way the data is structured, I am tasked with working with what I was given.
I have a table structured as such:
ID
UniqueName
DisplayName
Tag1
Tag...
Tag27
Yes, I have 27 columns, Tag1 - Tag27
NOTE: This cannot be changed due to the data coming from 15 year old software that is not updated, nor is there any chance of it being updated. (Hence my dilema)
I am getting my resultset utilizing PDO's fetchAll(PDO::FETCH_ASSOC)
How can I loop over these Tag* columns, and just the Tag* columns, without having to type out rs[$i]['Tag#'] for each individual one, also noting that there may be instances where I could have 14 Tag columns` instead of the 27 I state in this example...
COLUMN CODE:
// prod_opts_value_fields_prefix = "Tag"
foreach ($rs[$i] as $key => $val) {
if ( strpos ( strtolower ( $key ), strtolower ( $prod_opts_value_fields_prefix ) ) !== false ) {
$vals .= $val . '|';
echo $val . '<br />';
}
}
Nothing is getting echo'd
You could run a foreach over the rs[$i] and check if the key contains 'Tag' with strpos and go from there.
Alternatively you could use just a for loop running on 1 to 27 (or any maximum Tag value) and have an if condition checking if rs[$i]['Tag$N'] (where N is the for loop counting variable) isset, if not break from the loop as that means you've gone through all possible Tags.
The second solution here does have the assumption Tags are always numbered sequentially and in ascending order.
If you need it in multiple places, I'd probably add a setting to a preferences array or a constant that you can easily re-use:
const TAG_COLUMNS = [
'Tag1',
...
'Tag27',
];
You can use that wherever you need it to loop over a result set.

Splitting up an array formed by an api in PHP

I'm working on some stat tracking code for a game (yes, it's runescape. sue me).
I want to pull information from the high scores using an api which produces an array looking like this (captured using print_r)
Array
(
[getHiscore] => Array
(
[overall] => Array
(
[rank] => 61995
[lvl] => 2273
[totalxp] => 193310588
)
[attack] => Array
(
[rank] => 93406
[lvl] => 97
[totalxp] => 11747494
)
...and so on.
My question is how can i take what this api gives me and place it into a database table; I want to get an array such as this for a particular user and update their stats with it.
Would i use explode? It seems like the right idea to me but how would i actually use it to split the separate numbers and words?
My database is not totally realised yet, however each record will include a user name and then the level and total xp in each of 27 "skills". This almost certainly not best practice for database design but i'm as novice as they come so it's the best i can do.
You don't need to explode. It's an array and therefore it's already exploded. You need to iterate through it to build meaningful queries.
I'm not familiar with runescape so I don't know if your example is showing just the relevant fields of you need to discard some part. If it's the former, then you should try something like
$query="insert into stats_table (description, rank, lvl, totalexp) values (:description, :rank, :lvl, :totalext);";
$Statement = $DBConn->prepare($query);
foreach($fullArray as $description=>$subArray) {
$Statement->bindValue(':description',$description, PDO::PARAM_STR);
foreach($subArray as $key=>$value) {
$Statement->bindValue($key,$value, PDO::PARAM_STR);
}
$Statement->execute();
}
That will insert two rows containing
overall 61995 2273 193310588
attack 93406 97 11747494
PD: $DBConn is a PDO connection instance to whatever DB engine you're using.
Let's say this is all stored in the variable $ary:
$ary['getHiscore']['overall']['rank'] = 61995;
$ary['getHiscore']['overall']['lvl'] = 2273;
$ary['getHiscore']['overall']['totalxp'] = 193310588;
$ary['getHiscore']['attack']['rank'] = 93406;
$ary['getHiscore']['attack']['lvl'] = 97;
$ary['getHiscore']['attack']['totalxp'] = 11747494;
So, to get those values, it's:
$attackLevel = $ary['getHiscore']['attack']['lvl'];
If you
echo $attackLevel;
it would be 97.
Just pull the arrays out with a foreach loop and write some sql to insert the data. I don't know anything about your DB so if you want help there update your question please.
Simplest way to do this:
foreach($highscores as $highScoreType => $highScoreValues){
$rank = $highScoreValues['rank'];
$lvl = $highScoreValues['lvl'];
$totalXp = $highScoreValues['totalxp'];
//then it's up to you to put it into a table somehow.
}
$highScoreType will contain the values 'overall','attack',etc
This format of the foreach loop is extremely handy when iterating over an associative array (hash map/hash table, which is actually what all PHP arrays are underneath) will allow you to not only grab the value of the current pointed to entry, but also the key for that entry.
So, assume we have a single entry hashmap with key 'foo' and value 'bar'. If I want to show 'bar' I would simple
echo $map['foo'];//will output 'bar'
and if I put this into the above type of foreach loop
foreach($map as $fooKey => $barValue) {
echo $fooKey;//outputs 'foo'
echo $barValue;//outputs 'bar'
}

Filtering posts from a large multi-dimentional array, PHP, Facebook API

I need help moving through the large array returned by the Facebook PHP SDK. I am trying to find all posts from the user, then also check if the post does/doesn't contain the 'link' key. I have read that it is inefficient to use the foreach loop on arrays of this size due to the copying of the 1MB+ of data to process it. How should I traverse through the information effectively?
The array is structured like this, where 'x' is the number of each post:
Array
(
[data] => Array
(
[x] => Array
(
[from] => Array
(
[name] => james
)
[message] => Thanks for the great interview!
[link] => http://example.com/link.html
[description] => Description here
[etc] => Various other keys possible
)
)
)
Then my current code looks like this where $feed is the array from the Facebook API:
for ($x=0, $y=0; $x<=1000, $y<=19; $x++) {
if (array_key_exists('james', $feed['data'][$x]['from']['name'])) {
if (!array_key_exists('link', $feed['data'][$x])) {
echo "<div>" . $feed['data'][$x]['message'] . "<hr>" . $feed['data'][$x]['description'] . "</div>";
$y++;
};
};
};
I have read about the various iterators but I wouldn't know which to use! Hope you can help me out, cheers, Joe
Speaking about foreach performance
and using array_key_exists in actual fact it's a non sense
imho it's far better like
foreach($feed['data'] as $post){
if($post['from']['name']==='youruser'){
//has user
}
if(isset($post['link'])){
//has link
}
}
put it in the cillosis way
and it should be faster.
You are correct in the fact that foreach can be slow when iterating over large arrays because by default it uses a copy of the value and like you mentioned, that copying can consume memory and take a bit of a time hit.
But, another way to use foreach is by reference which does not create a copy. It works with the original value. This means no matter what size the array is, it won't be placed into memory again. Here is an example of a foreach by reference as shared by another StackOverflow user:
$a = array('hello', 'world');
$asRef =& $a;
$ontime = 0;
foreach($asRef as $i => $v)
{
if (!$ontime++) $a = array('hash', 'the cat');
echo " $i: $v\n";
}
You have the option of using the ArrayIterator from the SPL which is written in C and is pretty fast. Just a quick example of how that would work:
// This would be your large facebook array
$big_array = array(1,2,3,...,10000,10001);
// Get the iterator object
$array_iterator = new ArrayIterator($big_array);
foreach($array_iterator as $item)
{
//Do something with $item here
}
I've not done any benchmarking but I would imagine passing the array by reference and using the ArrayIterator would probably be a good solution.
foreach doesn't always copy. when it does copy, it copies only the immediate data structure being iterated; it doesn't copy any values. for example, if you did
foreach ($arr['data'] as $k => $v) ....
if there were 100 sub elements (you abbreviated one as [x] ), then it would make an array, copy those 100 keys, but would not copy the values that the keys point to, the values being the sub arrays/trees. internally it just stores a pointer and has it point to the subarray's memory address, without copying.
I think you're making a big deal for nothing, as the amount of data that actually gets copied is very little. foreach is almost always very very fast...
if you want to glimpse, look at memory_get_usage() and memory_get_peak_usage() before and after your loop.

PHP Matching value in an multi-dimensional array

I am looping between 2 times in 10 minute intervals, which works fine and outputs a time like so:
<?=$time->format('H:i')?>
I then am pulling data from the database of times I then want to see if the data in the loop matches whats coming out of the database. I have created a method to get me all the records from the database and outputs them into an array. I then wanted to use in_array to match them up then run the value through another method to get data about it. Problem is that it doesnt match up, problem being:
if (array_search($time->format('H:i'), $bookings))
echo "Match";
$booking is a multi-dimension array looking like:
Array (
[0] => Array ( [id] => 1 [time] => 12:00 )
[1] => Array ( [id] => 2 [time] => 15:00 )
...
)
Thanks in advance!
It would be much easier if you get the values directly from database. still if you want to process it in php, you can try with array_walk(). I am not sure about the syntax but should be something like
function search($value, $key, $needle)
{
array_search($needle, $value);
}
array_walk($bookings, 'search', $time->format('H:i'));
where $value will be your inner arrays.
Guys, please correct me if i am wrong with the syntax
It would probably be simpler to directly query the database accordingly - if you can - and than your query would be something like
select * from `table_name` WHERE `date_field` = $your_date
If that does not form a solution you can use array_walk as above or simply loop a little more:
foreach($bookings as $array) {
if(array_search($time->format('H:i'), $array)) {
echo 'match';
// If you don't want to keep searching use 'break'.
}
}

Adding to a parameter for category filtering

Ok so i have a question about PHP, and I don't know if i'm just being stupid or if this is just a lot harder than i thought :/
So i'm trying to filter some results down through GET parameter's in the URL. I'm thinking the best way to do this would be similar to what ebuyer.com do.
When you filter there search results by different category's the URl is built up like so
filtercat=36,134,142,62 etc
How are they adding to the parameter whilst keeping the rest of the selected category's?
Help!
I'm basically trying to create what is on this site, on the left sidebar where you can select and deselect filters for your search
Many thanks for any replies
UPDATE
Below is some code but repeated clicking on the link causes multiple occurrences of the same value
e.g. categories.php?filtercat=361343636
how can I stop this and add commas in between so the output is?
e.g. categories.php?filtercat=36,134 etc
<?php
$filter = $_GET['filtercat'];
$pieces = explode(",", $filter);
$edit_url = http_build_query( Array( 'filtercat' => ''.$pieces[0].$pieces[1].$pieces[2].'' ) );
echo($edit_url);
?>
Then in my links I have
36catagory
134catagory
The explode does not work though as there are no commas... the whole things a giant mess really and I'm so confused :/ Help!
In addition to explode(), you'll need implode(), and probably array_unique().
$filter = $_GET['filtercat'];
$pieces = explode(',', $filter);
$edit_url = http_build_query( Array(
'filtercat' => implode(',', array_unique($pieces))
));
script.php?filtercat[]=36&filtercat[]=134
Another wat to pass multiple values like that is serializing an array with the values.
$array = array('filtercat' =>
array(25, 32, 49)
);
$passme = serialize($array);
Then send $passme as GET.
<a href='test.php?val=<?php echo $passme; ?>'>Link</a>
Then you can unserialize it later and get the array containing all your values
$serilized = $_GET['val'];
$array = unserialize($serialized);
Which will print out as:
Array
(
[filtercat] => Array
(
[0] => 25
[1] => 32
[2] => 49
)
)
Why don't you just use http_build_query to rebuild the querystring? I assume you know the value of all the $_GET parameters, so why bothering to append to the querystring, when you can rebuild it?

Categories