I'm creating a Wordpress Plugin which uses a jQuery script. I've created a PHP array which contains its options like:
$settings = array('setting1' => 'value1', 'setting2' => 'value2', 'setting3' => 10)
I was now going to use foreach to loop over the items and print them like this:
foreach($settings as $setting => $value) {
if (is_string($value)) { $value = "'" . $value . "'"; }
$output .= $setting . ':' . $value .',';
}
which should make me end up with:
(window).load(function() {
$('#widget').myWidget({
setting1:'value1',
setting2:'value2',
setting3:10})
With the current setup I end up with the last entry having a ',' at the end (one too many) which means I get a Javascript error, so I need to remove it.
All with all, I have the feeling I'm doing something very dirty (including the is_string check) and I was wondering if there is a neat way to deal with this?
There is a json_encode function if you're using PHP >= 5.2
You should use json_encode() for this. It does all the dirty work for you.
(window).load(function() {
$('#widget').myWidget(
<?php echo json_encode($settings); ?>
);
}
Have you tried json_encode ?
Exemple from the docs:
<?php
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
echo json_encode($arr);
?>
Would output
{"a":1,"b":2,"c":3,"d":4,"e":5}
Here's a little thing I like to use when dealing with situations like this. I know it doesn't really answer your question, but it is an elegant way of solving the comma problem.
$comma = '';
foreach($settings as $setting => $value) {
if (is_string($value)) {
$value = "'" . $value . "'";
$output .= $comma . $setting . ':' . $value;
$comma = ',';
}
}
So on the first run $comma is blank, but after that it gets put between every new entry.
Related
I have array of 3000 elements which are like this
Array[0]= 405adc92-cfad-4be6-9ad2-ca363eda4933
Array[1]= 405adc92-cfad-4be6-9ad2-ca363eda4933
And I need to pass a variable in a function which require only a single quote at the beginning. I tried a solution on web which is pasting single quote on beginning and end aswell .like this
function add_quotes($str) {
return sprintf("'%s'", $str);
}
$csv = implode(',', array_map('add_quotes', $a));
$myArray = explode(',', $csv);
echo gettype($myArray[1]);
so answer is like this
myArray[1]='405adc92-cfad-4be6-9ad2-ca363eda4933'
So what Could I do to get rid ?
could you not just add the ' at the beginning of each string, rather than first add too many of them and afterwards remove the wrongly placed?
foreach($myArray as $key => &$value) {
$value = "'" . $value;
}
or (may be more readable as not by-reference)
foreach($myArray as $key => $value) {
$myArray[$key] = "'" . $value;
}
You can use rtrim - http://uk1.php.net/manual/en/function.rtrim.php to achieve. The generic syntax is:
<?php
$foo = 'my string\'';
$bar = rtrim($foo, '\'');
var_dump($foo); //shows my string'
var_dump($bar); //shows my string
so in your case take the array values, then use rtrim($myArray['myKey'], '\'') - this should do it for you :)
i have the following code:
while (list($key, $value) = each($arr)) {
$implode_keys_values = #"$key=$value,";
echo"$implode_keys_values";
}
which ends up echoing out xxxx=xxxx,xxxx=xxxx,xxxx=xxxx,xxxx=xxxx,
depending on how many keys/values there are.
how do I take this dynamically changing string and remove the very last comma on it?
keep in mind:
$implode_keys_values = substr($implode_keys_values,0,-1);
will not work, it will take out all the commas.
rtrim($implode_keys_values, ",") would cut trailing commas.
You can learn more about rtrim here at the PHP docs
$implode_keys_values = "";
while (list($key, $value) = each($arr)) {
$implode_keys_values .= #"$key=$value,";
}
echo rtrim($implode_keys_values, ",");
PHP has a function built in for that if the data in the array is not too complex (works for the xxxxxx values you have, can break with others):
echo http_build_query($arr, '', ',');
See http_build_query().
Another alternative is using iterators and checking if the current iteration is the last one. The CachingIterator::hasNext() method is helpful for that:
$it = new CachingIterator(new ArrayIterator($arr));
foreach($it as $key => $value) {
echo $key, '=', $value, $it->hasNext() ? ',' : '';
}
This variant does work with any data.
In your case, this would be a better way to implement implode():
$data = array();
while (list($key, $value) = each($arr)) {
$data[] = "$key=$value";
}
echo implode(",",$data);
I have looked over the internet for this but the problem only occurs with somebody when trying to pass an array to foreach and alter it inside. My problem is much easier and confusing.
I have 2 global variables:
$type="";
$rule="";
And i have this code:
foreach($cartasxml->children() as $child) {
$str="insert into cards (title,cost,color,loyalty,type,pow,tgh,hand,life,rules,set,rarity,number,artist,flavor,cost) values('{{{".$child->name."}}}',";
if(isset($child->typelist))
{
foreach($child->typelist as $a)
$type .= "|" . str_replace("{","[",str_replace("}","]",$a->type));
$str.="'{{{".substr($type,1)."}}}',";
}
else
$str.="NULL,";
And at the end of foreach i do:
$type="";
$rule="";
So, when i see the value of $type by printing $str it only shows the last one i included. Maybe an escope problem, but i still don't know how to solve it.
Somebody?
May be you can use array to push all the values into it
$type_array = array();
$str_array = array();
foreach($cartasxml->children() as $child) {
$str="insert into cards (title,cost,color,loyalty,type,pow,tgh,hand,life,rules,set,rarity,number,artist,flavor,cost) values('{{{".$child->name."}}}',";
if(isset($child->typelist))
{
foreach($child->typelist as $a)
$type .= "|" . str_replace("{","[",str_replace("}","]",$a->type));
$str.="'{{{".substr($type,1)."}}}',";
array_push($type_array,$type);
array_push($str_array,$str);
}
else
$str.="NULL,";
print_r($type_array);
print_r($str_array);
Try this:
$type = implode('|',
array_map(function($a)
{ return str_replace("{","[",str_replace("}","]",$a->type)) },
$child->typelist));
$str .= "'{{{".$type."}}}',";
Okay, so I know that using eval() isn't great, but I haven't been able to come up with a better solution to my problem, and until recently, there wasn't a performance reason not to use it. However, I am now passing enough data to the function that it is taking unacceptably long.
The function that is being called is:
public static function makeAMultiDimensionalArrayWithSumsBasedOnMultipleFields($inArray, $dimensionFieldNames, $sumFieldNameArray, $staticFieldNameArray = array())
{
$outArray = array();
// Just in case the array has indices, sort it so array_pop works as expected.
ksort($dimensionFieldNames);
foreach ($inArray as $row)
{
// make sure each row in the inArray has all keys specified by $dimensionFieldNames
$allFieldsPresent = TRUE;
foreach ($dimensionFieldNames as $keyFieldName)
{
if (!array_key_exists($keyFieldName, $row))
{
// Note that alternatively we could set the field to a specified default value.
$allFieldsPresent = FALSE;
}
}
if ($allFieldsPresent)
{
$indexString = '';
$keyFieldNameArrayCopy = $dimensionFieldNames;
foreach ($dimensionFieldNames as $keyFieldName)
{
$indexString .= "['" . $row[$keyFieldName] . "']";
// lets sum values
foreach ($sumFieldNameArray as $sumFieldName)
{
eval ('$outArray' . $indexString . '[' . $sumFieldName . '] += $row[' . $sumFieldName . '];');
}
foreach ($staticFieldNameArray as $staticFieldName)
{
eval ('$outArray' . $indexString . '[' . $staticFieldName . '] = $row[' . $staticFieldName . '];');
}
}
}
}
return $outArray;
}
It is being called like this:
makeAMultiDimensionalArrayWithSumsBasedOnMultipleFields($data, $dimensionArray, $sumArray, $staticArray);
And the variables being passed to the function are similar to:
$dimensionArray = array("firstLevelID", "secondLevelID", "thirdLevelID", "fourthLevelID", "fifthLevelID");
$sumArray = array("revenue", "cost", "profit", "sales", "inquires", "cost", "walkins");
$staticArray = array("date", "storeID", "storeName", "productID", "productName", "managerID", "managerName", "salesperson");
So I want to rewrite the function so that I'm not using eval() any more. I've spent a considerable amount of time on this, and feel that it's time to seek some advice.
The goal is to take an array of arrays, and turn it into a multidimensional array based on the dimensions in the $dimensionArray.
I don't want to bore you with too many details right now, so please ask if you need more or have any other questions
Wow, okay. First time through I missed your indexing concatenation. Try this:
if ($allFieldsPresent) {
$keys = array();
foreach ($dimensionFieldNames as $keyFieldName) {
$keys[] = $row[$keyFieldName];
// lets sum values
foreach ($sumFieldNameArray as $sumFieldName)
self::deepAssign($outArray, $keys, $sumFieldName, $row[$sumFieldName], true);
foreach ($staticFieldNameArray as $staticFieldName)
self::deepAssign($outArray, $keys, $staticFieldName, $row[$staticFieldName]);
}
}
protected static function deepAssign(&$array, $keys, $fieldName, $value, $sum = false) {
$target =& $array;
foreach ($keys as $key) {
if (!isset($target[$key]))
$target[$key] = array();
$target =& $target[$key];
}
if($sum)
$target[$fieldName] += $value;
else
$target[$fieldName] = $value;
}
You should look at create_function() (docs here)
This is probably a simple question, but how do you iterate through an array, doing something to each one, until the last one and do something different?
I have an array of names. I want to output the list of names separated by commas.
Joe, Bob, Foobar
I don't want a comma at the end of the last name in the array, nor if there is only one value in the array (or none!).
Update: I can't use implode() because I have an array of User model objects where I get the name from each object.
$users = array();
$users[] = new User();
foreach ($users as $user) {
echo $user->name;
echo ', ';
}
How can I achieve this and still use these objects?
Update: I was worrying too much about how many lines of code I was putting in my view script, so I decided to create a view helper instead. Here's what I ended up with:
$array = array();
foreach($users as $user) {
$array[] = $user->name;
}
$names = implode(', ', $array);
Use implode:
$names = array('Joe', 'Bob', 'Foobar');
echo implode(', ', $names); # prints: Joe, Bob, Foobar
To clarify, if there is only one object in the array, the ', ' separator will not be used at all, and a string containing the single item would be returned.
EDIT: If you have an array of objects, and you wanted to do it in a way other than a for loop with tests, you could do this:
function get_name($u){ return $u->name; };
echo implode(', ', array_map('get_name', $users) ); # prints: Joe, Bob, Foobar
$array = array('joe', 'bob', 'Foobar');
$comma_separated = join(",", $array);
output: joe,bob,Foobar
Sometimes you might not want to use implode.
The trick then is to use an auxiliary variable to monitor not the last, but the first time through the loop.
vis:
$names = array('Joe', 'Bob', 'Foobar');
$first = true;
$result = '';
foreach ($names as $name)
{
if (!$first)
$result .= ', ';
else
$first = false;
$result .= $name;
}
implode(', ', $array_of_names)
psuedocode....
integer sigh=container.getsize();
sigh--;
integer gosh=0;
foreach element in container
{
if(gosh!=sigh)
dosomething();
else
doLastElementStuff();
gosh++;
}
looking at all the other answers, it seems PHP has gotten a lot more syntactic S since I last wrote anything in it :D
I come accross this a lot building SQL statements etc.
$joiner = " ";
foreach ($things as $thing) {
echo " $joiner $thing \n";
$joiner = ',';
}
FOr some reason its easier to work out the logic if you think of the ",", "AND" or "OR" as an option/attribute that goes before an item. The problem then becomes how to suppress the the "," on the first line.
I personally found the fastest way (if you're into micro optimization) is:
if(isset($names[1])) {
foreach ($names as $name) {
$result .= $name . ', ';
}
$result = substr($result, 0, -2);
} else {
$result = $names[0];
}
isset($names[1]) is the fastest (albeit not so clear) way of checking the length of an array (or string). In this case, checking for at least two elements is performed.
I actually find it easier to create my comma delimited text a little differently. It's a bit more wordy, but it's less function calls.
<?php
$nameText = '';
for ($i = 0; $i < count($nameArray); $i++) {
if ($i === 0) {
$nameText = $nameArray[$i];
} else {
$nameText .= ',' . $nameArray[$i];
}
}
It adds the comma as a prefix to every name except where it's the first element if the array. I have grown fond of using for as opposed to foreach since I have easy access to the current index and therefore adjacent elements of an array. You could use foreach like so:
<?php
$nameText = '';
$nameCounter = 0;
foreach ($nameArray as $thisName) {
if ($nameCounter === 0) {
$nameText = $thisName;
$nameCounter++;
} else {
$nameText .= ',' . $thisName;
}
}