I have array
[Company] => Demo Company 1
[First Name] => Test
[Last Name] => Lead 1
[Designation] => This is testing title 1
[Email] => email1#yopmail.com
[Phone] => 242377
I used extract() function so all the index values will become variable names, I also used {} as there are spaces in variable names. But i dont know why its not working :(
This ${'First Name'} returns blank...below is my code
foreach($vals as $value){
extract($value);
echo '<tr><td>'.${'First Name'}.' '.${"Last Name"}.'</td><td>'.$Company.'</td><td>'.$Phone.'</td><td>'.$Email.'</td></tr>';
}
Variable names cannot contain spaces. For reference, read the manual on variables:
A valid variable name starts with a letter or underscore, followed by
any number of letters, numbers, or underscores. As a regular
expression, it would be expressed thus:
'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
If I were you, I'd just go with a shorter name on the array, so instead of $value use $v or similar. You can also use printf to make the code more readable:
foreach($vals as $v) {
printf('<tr><td>%s %s</td><td>%s</td><td>%s</td><t\
d>%s</td></tr>',
$LEADID,
$v['First Name'],
$v['Last Name'],
$v['Company'],
$v['Phone'],
$v['Email']);
}
I think you should remove the spaces before using extract:
$keys = str_replace( ' ', '', array_keys($vals));
$values = array_values($vals);
$vals = array_combine($keys, $values);
Then, after extract you'd have variables like $FirstName.
In this case you do not really need extract.
You can use array indexes in interpolated strings.
$sample = array('name' => 'frank, 'age' => 42);
echo "{$sample['name']} is {$sample['age']} years old.";
If you can avoid using ${'strange names'} you should do it. If yo REALLY need to do it this way:
Please update your question and tell us HOW $value is defined. Is vals The array from your first code block?
Related
I have a string that I want to explode by commas but only if the comma is not nested inside some parentheses. This is a fairly common use case, and I have been reading through answered posts in this forum, but not really found what I am looking for.
So, in detail: the point is, i have a string (= SQL SELECT ... FROM statement), and I want to extract the elements from the list separated by comma encoded in this string (= the name of the columns that one wants to select from. However, these elements can contain brackets, and effectively be function calls. For example, in SQL one could do
SELECT TO_CHAR(min(shippings.shippingdate), 'YYYY-MM-DD') as shippingdate, nameoftheguy FROM shippings WHERE ...
Obviously, I would like to have an array now containing as first element
TO_CHAR(min(shippings.shippingdate), 'YYYY-MM-DD') as shippingdate
and as second element
nameoftheguy
The approaches I have followed so far are
PHP and RegEx: Split a string by commas that are not inside brackets (and also nested brackets),
PHP: Split a string by comma(,) but ignoring anything inside square brackets?,
Explode string except where surrounded by parentheses?, and
PHP: split string on comma, but NOT when between braces or quotes?
(focussing on the regex expressions therein, since I would like to do it with a single regex line), but in my little test area, those do not give the proper result. In fact, all of them split nothing or too much:
$Input: SELECT first, second, to_char(my,big,house) as bigly, export(mastermind and others) as aloah FROM
$Output: Array ( [0] => first [1] => second [2] => to_char [3] => (my,big,house) [4] => as [5] => bigly [6] => export [7] => (mastermind and others) [8] => as [9] => aloah )
The code of my test area is
<?php
function test($sql){
$foo = preg_match("/SELECT(.*?)FROM/", $sql, $match);
$bar = preg_match_all("/(?:[^(|]|\([^)]*\))+/", $match[1], $list);
//$bar = preg_match_all("/\((?:[^()]|(?R))+\)|'[^']*'|[^(),\s]+/", $match[1], $list);
//$bar = preg_match_all("/[,]+(?![^\[]*\])/", $match[1], $list);
//$bar = preg_match_all("/(?:[^(|]|\([^)]*\))+/", $match[1], $list);
//$bar = preg_match_all("/[^(,\s]+|\([^)]+\)/", $match[1], $list);
//$bar = preg_match_all("/([(].*?[)])|(\w)+/", $match[1], $list);
print "<br/>";
return $list[0];
}
print_r(test("SELECT first, second, to_char(my,big,house) as bigly, export(mastermind and others) as aloah FROM"));
?>
As you can imagine, I am not an regex expert, but I would like to do this splitting in a single line, if it is possible.
Following the conversation here, I did write a parser to solve this problem. It is quite ugly, but it does the job (at least within some limitations). For completeness (if anybody else might run into the same question), I post it here:
function full($sqlu){
$sqlu = strtoupper($sqlu);
if(strpos($sqlu, "SELECT ")===false || strpos($sqlu, " FROM ")===false) return NULL;
$def = substr($sqlu, strpos($sqlu, "SELECT ")+7, strrpos($sqlu, " FROM ")-7);
$raw = explode(",", $def);
$elements = array();
$rem = array();
foreach($raw as $elm){
array_push($rem, $elm);
$txt = implode(",", $rem);
if(substr_count($txt, "(") - substr_count($txt, ")") == 0){
array_push($elements, $txt);
$rem = array();
}
}
return $elements;
}
When feeding it with the following string
SELECT first, second, to_char(my,(big, and, fancy),house) as bigly, (SELECT myVar,foo from z) as super, export(mastermind and others) as aloah FROM table
it returns
Array ( [0] => first [1] => second [2] => to_char(my,(big, and, fancy),house) as bigly [3] => (SELECT myVar,foo from z) as super [4] => export(mastermind and others) as aloah )
I've started with preg_replace in PHP and I wonder how I can replace only first matching array key with a specified array value cause I set preg_replace number of changes parameter to '1' and it's changing more than one time anyways. I also splitted my string to single words and I'm examining them one by one:
<?php
$internal_message = 'Hey, this is awesome!';
$words = array(
'/wesome(\W|$)/' => 'wful',
'/wful(\W|$)/' => 'wesome',
'/^this(\W|$)/' => 'that',
'/^that(\W|$)/' => 'this'
);
$splitted_message = preg_split("/[\s]+/", $internal_message);
$words_num = count($splitted_message);
for($i=0; $i<$words_num; $i++) {
$splitted_message[$i] = preg_replace(array_keys($words), array_values($words), $splitted_message[$i], 1);
}
$message = implode(" ", $splitted_message);
echo $message;
?>
I want this to be on output:
Hey, that is awful
(one suffix change, one word change and stops)
Not this:
Hey, this is awesome
(two suffix changes, two word changes and back to original word & suffix...)
Maybe I can simplify this code? I also can't change order of the array keys and values cause there will be more suffixes and single words to change soon. I'm kinda newbie in php coding and I'll be thankful for any help ;>
You may use plain text in the associative array keys that you will use to create dynamic regex patterns from, and use preg_replace_callback to replace the found values with the replacements in one go.
$internal_message = 'Hey, this is awesome!';
$words = array(
'wesome' => 'wful',
'wful' => 'wesome',
'this' => 'that',
'that' => 'this'
);
$rx = '~(?:' . implode("|", array_keys($words)) . ')\b~';
echo "$rx\n";
$message = preg_replace_callback($rx, function($m) use ($words) {
return isset($words[$m[0]]) ? $words[$m[0]] : $m[0];
}, $internal_message);
echo $message;
// => Hey, that is awful!
See the PHP demo.
The regex is
~(?:wesome|wful|this|that)\b~
The (?:wesome|wful|this|that) is a non-capturing group that matches any of the values inside, and \b is a word boundary, a non-consuming pattern that ensures there is no letter, digit or _ after the suffix.
The preg_replace_callback parses the string once, and when a match occurs, it is passed to the anonymous function (function($m)) together with the $words array (use ($words)) and if the $words array contains the found key (isset($words[$m[0]])) the corresponding value is returned ($words[$m[0]]) or the found match is returned otherwise ($m[0]).
I have this problem:
One string like:
$stringa = "array('name' => 'John')"
I want obtain : array('name' => 'John') for use in my code like array
Any helps? Thanks
Caution using eval...
Caution The eval() language construct is very dangerous because it
allows execution of arbitrary PHP code. Its use thus is discouraged.
If you have carefully verified that there is no other option than to
use this construct, pay special attention not to pass any user
provided data into it without properly validating it beforehand.
<?php
$stringa = "array('name' => 'John')";
$code = "\$a = " . $stringa . ";";
eval($code);
print_r($a);
Gouda Elalfy was on the right idea, but his solution simply made the whole string a single array value.
First, we need to remove the excess datatype information:
$slimString = substr($stringa,6);
$slimString = rtrim($slimString,")");
This now gives us a string of:
'name' => 'John'
So then the Keys and the values in the string need to be split up,
so break at => as so:
For multiple values in the string:
This method also includes the single quotes to limit catching punctuation commas (please note this method was screwed up by trim not being as effective as I'd have liked and requiring str_replace quotes instead).
$slimString = str_replace("', '","=>", $slimString);
Then
$slimStringParts = explode("=>", $slimString);
This will split on => (or ,) so that multiple values of array contents can be generated.
Then cycle through each of the array pieces, on the basis that the EVEN numbers (and zero) are the Keys and the ODD numbers are the values, also removing the quotes as well for each one,
I was originally using trim but for some reason trim was not working as fully as I expected. so instead reverted to st_replace
foreach($slimStringParts as $key => $part){
if(($key%2) == 0){
$part = str_replace("'","",$part);
$arrayOutput[$part] = str_replace("'","",$slimStringParts[$key+1]);
}
}
unset($key, $part);
The foreach only acts upon the even and zero values as referenced above, and they take the original key value + 1 as their contents.
The trim/str_replace removes the single quotes and looks untidy but this works for a string of one or more array values
And finally the Output:
print_r($arrayOutput);
Test with the original:
input : "array('name' => 'John')"
Output : Array ( [name ] => John )
Tested with a multivalue array string:
input : "array('name' => 'John', 'surname' => 'James', 'Ride' => 'horse')"
Output : Array ( [name ] => John [surname ] => James [Ride ] => horse )
Full code:
$stringa = "array('name' => 'John')";
$stringb = "array('name' => 'John', 'surname' => 'James', 'Ride' => 'horse')";
$slimString = substr($stringb,6);
$slimString = rtrim($slimString,")");
$slimString = str_replace("', '","=>", $slimString);
$slimStringParts = explode("=>", $slimString);
foreach($slimStringParts as $key => $part){
if(($key%2) == 0){
$part = str_replace("'","",$part);
$arrayOutput[$part] = str_replace("'","",$slimStringParts[$key+1]);
}
}
unset($key,$part);
print_r($arrayOutput);
exit;
Please note my trim() idea was what I wanted but that seems to be influenced by my page character encoding :-(
You can use eval() function.
But it's not recommanded.
http://php.net/manual/en/function.eval.php
Eval is unsafe, try to use it as temporary method and find a better solution.
Example :
$stringa="array('name' => 'John');";
$array = eval($stringa);
I am trying to match a semi dynamically generated string. So I can see if its the correct format, then extract the information from it that I need. My Problem is I no matter how hard I try to grasp regex can't fathom it for the life of me. Even with the help of so called generators.
What I have is a couple different strings like the following. [#img:1234567890] and [#user:1234567890] and [#file:file_name-with.ext]. Strings like this pass through are intent on passing through a filter so they can be replaced with links, and or more readable names. But again try as I might I can't come up with a regex for any given one of them.
I am looking for the format: [#word:] of which I will strip the [, ], #, and word from the string so I can then turn around an query my DB accordingly for whatever it is and work with it accordingly. Just the regex bit is holding me back.
Not sure what you mean by generators. I always use online matchers to see that my test cases work. #Virendra almost had it except forgot to escape the [] charaters.
/\[#(\w+):(.*)\]/
You need to start and end with a regex delimeter, in this case the '/' character.
Then we escape the '[]' which is use by regex to match ranges of characters hence the '['.
Next we match a literal '#' symbol.
Now we want to save this next match so we can use it later so we surround it with ().
\w matches a word. Basically any characters that aren't spaces, punctuation, or line characters.
Again match a literal :.
Maybe useful to have the second part in a match group as well so (.*) will match any character any number of times, and save it for you.
Then we escape the closing ] as we did earlier.
Since it sounds like you want to use the matches later in a query we can use preg_match to save the matches to an array.
$pattern = '/\[#(\w+):(.*)\]/';
$subject = '[#user:1234567890]';
preg_match($pattern, $subject, $matches);
print_r($matches);
Would output
array(
[0] => '[#user:1234567890]', // Full match
[1] => 'user', // First match
[2] => '1234567890' // Second match
)
An especially helpful tool I've found is txt2re
Here's what I would do.
<pre>
<?php
$subj = 'An image:[#img:1234567890], a user:[#user:1234567890] and a file:[#file:file_name-with.ext]';
preg_match_all('~(?<match>\[#(?<type>[^:]+):(?<value>[^\]]+)\])~',$subj,$matches,PREG_SET_ORDER);
foreach ($matches as &$arr) unset($arr[0],$arr[1],$arr[2],$arr[3]);
print_r($matches);
?>
</pre>
This will output
Array
(
[0] => Array
(
[match] => [#img:1234567890]
[type] => img
[value] => 1234567890
)
[1] => Array
(
[match] => [#user:1234567890]
[type] => user
[value] => 1234567890
)
[2] => Array
(
[match] => [#file:file_name-with.ext]
[type] => file
[value] => file_name-with.ext
)
)
And here's a pseudo version of how I would use the preg_replace_callback() function:
function replace_shortcut($matches) {
global $users;
switch (strtolower($matches['type'])) {
case 'img' : return '<img src="images/img_'.$matches['value'].'jpg" />';
case 'file' : return ''.$matches['value'].'';
// add id of each user in array
case 'user' : $users[] = (int) $matches['value']; return '%s';
default : return $matches['match'];
}
}
$users = array();
$replaceArr = array();
$subj = 'An image:[#img:1234567890], a user:[#user:1234567890] and a file:[#file:file_name-with.ext]';
// escape percentage signs to avoid complications in the vsprintf function call later
$subj = strtr($subj,array('%'=>'%%'));
$subj = preg_replace_callback('~(?<match>\[#(?<type>[^:]+):(?<value>[^\]]+)\])~',replace_shortcut,$subj);
if (!empty($users)) {
// connect to DB and check users
$query = " SELECT `id`,`nick`,`date_deleted` IS NOT NULL AS 'deleted'
FROM `users` WHERE `id` IN ('".implode("','",$users)."')";
// query
// ...
// and catch results
while ($row = $con->fetch_array()) {
// position of this id in users array:
$idx = array_search($row['id'],$users);
$nick = htmlspecialchars($row['nick']);
$replaceArr[$idx] = $row['deleted'] ?
"<span class=\"user_deleted\">{$nick}</span>" :
"{$nick}";
// delete this key so that we can check id's not found later...
unset($users[$idx]);
}
// in here:
foreach ($users as $key => $value) {
$replaceArr[$key] = '<span class="user_unknown">User'.$value.'</span>';
}
// replace each user reference marked with %s in $subj
$subj = vsprintf($subj,$replaceArr);
} else {
// remove extra percentage signs we added for vsprintf function
$subj = preg_replace('~%{2}~','%',$subj);
}
unset($query,$row,$nick,$idx,$key,$value,$users,$replaceArr);
echo $subj;
You can try something like this:
/\[#(\w+):([^]]*)\]/
\[ escapes the [ character (otherwise interpreted as a character set); \w means any "word" character, and [^]]* means any non-] character (to avoid matching past the end of the tag, as .* might). The parens group the various matched parts so that you can use $1 and $2 in preg_replace to generate the replacement text:
echo preg_replace('/\[#(\w+):([^]]*)\]/', '$1 $2', '[#link:abcdef]');
prints link abcdef
Say I have the following email addresses comma separated in a string:
$addrList = 'Kevin.Brine#pppg.com, Robert.Thomas#pppg.com, "Guice, Doug" <Doug.Guice#pppg.com>';
I need the following result:
[0] => Kevin.Brine#pppg.com
[1] => Robert.Thomas#pppg.com
[2] => "Guice, Doug" <Doug.Guice#pppg.com>
Seems fairly simple, but that comma in the quoted name really has thrown me in trying to find a solution using either preg_match_all or preg_split. Also we should accommodate for emails that use single quotes for names too, ie: 'smith, tom' <tom.smith#abc.com>
str_getcsv() should give you what you need, though it will strip the quotes.
EDIT
If you want to put the quotes back in:
$addrList = 'Kevin.Brine#pppg.com, Robert.Thomas#pppg.com, "Guice, Doug" <Doug.Guice#pppg.com>';
$t = str_getcsv($addrList);
foreach($t as $k => $v) {
if (strpos($v,',') !== false) {
$t[$k] = '"'.str_replace(' <','" <',$v);
}
}
var_dump($t);