Array and substring php - php

//array data
{
$results[] = $result;
$SiteID=$result["site_id"];
$pay_sale_id=$result["pay_sale_id"];
$pay_payment_info=$result["pay_payment_info"];
$payNo= substring_index(substring_index('$result["pay_payment_info"]', '$USER=', -1), '~$TAGROLE', 1);
}
The content of pay_payment_info is as follows
#$TAG=6F0000173~$USER=james~$TAGROLE=0
I want to extract only the user info, but i get error:
Fatal error: Call to undefined function substring_index() in line

Considering the user info always begins with ~$USER= and ends with a ~ we can get the result using simple regex:
preg_match('/\~\$USER=(?<user>[^~]+)/', $pay_payment_info, $match);
var_dump($match['user']);

As previous comments said - there is no such function like substring_index in core PHP
This question is possible duplicate of following Php get string between tags
topic
Here is working example with usage of strpos http://php.net/manual/pl/function.strpos.php
and substr http://php.net/manual/pl/function.substr.php
$var = '$TAG=6F0000173~$USER=james~$TAGROLE=0';
$m = substr($var, strpos($var, '~$USER=')+7);
var_dump($m); //returns string(16) "james~$TAGROLE=0"
$m = substr($m, 0, strpos($m, '~$'));
var_dump($m); //returns string(5) "james"

it seems that the problem is you have no substring_index() function or method, yet you attempt to invoke it twice.
I am not sure why you use the ~ as a delimiter but that should be ok, although using a , would have resulted in less work; each of the attributes of your querystring would have been able to be addressed directly then.
what you want to do is use the php version of split() which is explode() here is a link to the manual.
what you want to do is split the inc string:
$aUserInfo = explode('~', $result['pay_payment_info']);
now you have an array. loop through it and make it like you want:
$result = array();
foreach($aUserInfo as $v){
$aTmp = explode('=',$v);
$result[$aTmp[0]] = $aTmp[1];
}
at the end of this you have an array with keys as keys and their respective values as values, i.e.
$result = array( 'tag' => '6F0000173',
'user'=> 'James',
'tagrole'=> 0 );

The error tells you exactly why it is an error: substring_index is not a valid/native PHP function... you can define your own function of substring_index, though.
However, given the string:
$TAG=6F0000173~$USER=james~$TAGROLE=0
to get the $USER=james part, you can use explode as follows--
$payNo = explode("~", $result["pay_payment_info"])
Now, you have the $USER info in $payNo[1]
If you want to go even further and just get the value of what $USER value is, then you can use PHP's native substr function:
$justUserPart = substr($payNo[1], strpos($payNo[1], "=")+1);
echo $justUserPart;
Please Note: The above assumes that you will always have the string in the format of
$TAG=...~$USER=...~$TAGROLE=...

Related

How to get equal parts of multiple strings/array?

I have the following point: a xls file contains one column with codes. The codes have a prefix and a unique code like this:
- VIP-AX757
- VIP-QBHE6
- CODE-IUEF7
- CODE-QDGF3
- VIP-KJQFB
- ...
How can I get equal parts of strings or an array? perfect would be if I get an array like this:
- $result[VIP] = 3;
- $result[CODE] = 2;
An array with the found prefix and the sum of cells with that prefix. But the result is not so important at the moment.
I couldn't find a soloution how to get equal parts of two strings: how to compare this "VIP-AX757" and "VIP-QBHE6" and get a result that says: "VIP-" is the same prefix/part in this two strings?
Hope someone has an idea.
thx!
-drum roll- Time for a one-liner!
$result = array_count_values(array_map(function($v) {list($a) = explode("-",$v); return $a;},$input));
(Assumes $input is your array of codes)
If you are using PHP 5.4 or newer (you should be), then:
$result = array_count_values(array_map(function($v) {return explode("-",$v)[0];},$input));
Tested in PHP CLI:
If the prefix is always followed by a '-' then you can do something like this:-
foreach ($codes as $code) {
$tmp = explode("-",$code);
$result[$tmp[0]] += 1;
}
print_r($result);
Depends on the variability of the data, but something like:
preg_match_all('/^([^-]+)/m', $string, $matches);
$result = array_count_values($matches[1]);
print_r($result);
If you don't know that there is an - after the prefix but the prefix is always letters then:
preg_match_all('/^([A-Z]+)/im', $string, $matches);
$result = array_count_values($matches[1]);
Otherwise you'll have to define exactly what the prefix can contain if it's not the delimiter.
Since you stated via comment to Niet that you don't have a reliable delimiter, then we can only write a pattern that identifies your targeted substrings based on their location in each line.
I recommend preg_match_all() with no capture group, a start of the line anchor, and a multi-line pattern modifier (m).
I've written a preg_split() alternative, but the pattern is a little "clunkier" because of the way I'm handling the line returns.
Code: (Demo)
$string = 'VIP-AX757
VIP-QBHE6
CODE-IUEF7
CODE-QDGF3
VIP-KJQFB';
var_export(array_count_values(preg_match_all('~^[A-Z]+~m', $string, $out) ? $out[0] : []));
echo "\n\n";
var_export(array_count_values(preg_split('~[^A-Z][^\r\n]+\R?~', $string, -1, PREG_SPLIT_NO_EMPTY)));
Output:
array (
'VIP' => 3,
'CODE' => 2,
)
array (
'VIP' => 3,
'CODE' => 2,
)

PHP Regex get command from a chat

Im currently developing a AJAX based chat, and i'm trying to get to the part where i can input commands in the chat as in this example:
"/roll 20" will give a random number between 1 and 20.
And i thought it would be best to fetch commands with regex, but i cant get the values from the string and this is what i've tried.
$message = "/roll 20";
preg_match("/roll \d+", $message, $matches);
print_r($matches);
I would like to get "/roll 20" from the message but it wont print any matches. So is it that my regex is wrong or am i handling the preg_match wrong?
ps. If you have another PHP based style to fetch commands with, i'l gladly take a look.
You'd need to use delimiters around the regex and also add regex to catch the beginning and end of a string. I've also wrapped the roll amount in parameters so you get a variable for the roll amount. So a phrase with the /roll command in the middle of the input wouldn't be caught.
$message = "/roll 20";
preg_match("#^/roll (\d+)$#", $message, $matches);
print_r($matches);
I honestly don't see why you would use regex for this. I assume you only have a fixed set of commands against which you might be matching, and that you would only issue such commands when the input starts with /. And that the command would need to come as first item in line and have parameters to the command separated by spaces.
So, using preg_match() you would need to have a series of patterns that you loop through to compare the line. This could become bulky to maintain.
I would propose a different parser-like approach, using explode to break apart the input line, inspecting the first element to see if it is a command. If so, you collect the parameters and call a function to do what you want to do.
$input = '/roll 20';
$commands = array(
'roll' => array('range'), // single parameter
'foo' => array('param1', 'param2'), // multiple parameters
'bar' => array() // no parameters
);
$input_array = explode(' ', $input);
$command = ltrim($input_array[0], '/');
if (strpos($input_array[0], '/') === 0 && array_key_exists($command, $commands)) {
$parameters = array();
$i = 1;
foreach($commands[$command] as $param_key) {
if(empty($input_array[$i])) {
// error we did not get expected number of parameters
// handle this error somehow
die('Not enough parameters passed for command');
} else {
$parameters[$param_key] = $input_array[$i];
$i++;
}
}
// perhaps have a function defined for each command that you can call
// while passing in the parameter array
call_user_func($command, $parameters);
} else {
// this is just text content
// do whatever
}
No need for the relatively slow regex functionality.
Use delimiter for your regex:
preg_match("~/roll \d+~", $message, $matches);
^ ^
Use Delimiter
preg_match("#/roll \d+#", $message, $matches);

very large php string magically turns into array

I am getting an "Array to string conversion error on PHP";
I am using the "variable" (that should be a string) as the third parameter to str_replace. So in summary (very simplified version of whats going on):
$str = "very long string";
str_replace("tag", $some_other_array, $str);
$str is throwing the error, and I have been trying to fix it all day, the thing I have tried is:
if(is_array($str)) die("its somehow an array");
serialize($str); //inserted this before str_replace call.
I have spent all day on it, and no its not something stupid like variables around the wrong way - it is something bizarre. I have even dumped it to a file and its a string.
My hypothesis:
The string is too long and php can't deal with it, turns into an array.
The $str value in this case is nested and called recursively, the general flow could be explained like this:
--code
//pass by reference
function the_function ($something, &$OFFENDING_VAR, $something_else) {
while(preg_match($something, $OFFENDING_VAR)) {
$OFFENDING_VAR = str_replace($x, y, $OFFENDING_VAR); // this is the error
}
}
So it may be something strange due to str_replace, but that would mean that at some point str_replace would have to return an array.
Please help me work this out, its very confusing and I have wasted a day on it.
---- ORIGINAL FUNCTION CODE -----
//This function gets called with multiple different "Target Variables" Target is the subject
//line, from and body of the email filled with << tags >> so the str_replace function knows
//where to replace them
function perform_replacements($replacements, &$target, $clean = TRUE,
$start_tag = '<<', $end_tag = '>>', $max_substitutions = 5) {
# Construct separate tag and replacement value arrays for use in the substitution loop.
$tags = array();
$replacement_values = array();
foreach ($replacements as $tag_text => $replacement_value) {
$tags[] = $start_tag . $tag_text . $end_tag;
$replacement_values[] = $replacement_value;
}
# TODO: this badly needs refactoring
# TODO: auto upgrade <<foo>> to <<foo_html>> if foo_html exists and acting on html template
# Construct a regular expression for use in scanning for tags.
$tag_match = '/' . preg_quote($start_tag) . '\w+' . preg_quote($end_tag) . '/';
# Perform the substitution until all valid tags are replaced, or the maximum substitutions
# limit is reached.
$substitution_count = 0;
while (preg_match ($tag_match, $target) && ($substitution_count++ < $max_substitutions)) {
$target = serialize($target);
$temp = str_replace($tags,
$replacement_values,
$target); //This is the line that is failing.
unset($target);
$target = $temp;
}
if ($clean) {
# Clean up any unused search values.
$target = preg_replace($tag_match, '', $target);
}
}
How do you know $str is the problem and not $some_other_array?
From the manual:
If search and replace are arrays, then str_replace() takes a value
from each array and uses them to search and replace on subject. If
replace has fewer values than search, then an empty string is used for
the rest of replacement values. If search is an array and replace is a
string, then this replacement string is used for every value of
search. The converse would not make sense, though.
The second parameter can only be an array if the first one is as well.

PHP : Get a number between 2 strings

I have this string:
a:3:{i:0;i:2;i:1;i:3;i:2;i:4;}
I want to get number between "a:" and ":{" that is "3".
I try to user substr and strpos but no success.
I'm newbie in regex , write this :
preg_match('/a:(.+?):{/', $v);
But its return me 1.
Thanks for any tips.
preg_match returns the number of matches, in your case 1 match.
To get the matches themselves, use the third parameter:
$matches = array();
preg_match(/'a:(\d+?):{/', $v, $matches);
That said, I think the string looks like a serialized array which you could deserialize with unserialize and then use count on the actual array (i.e. $a = count(unserialize($v));). Be careful with userprovided serialized strings though …
If you know that a: is always at the beginning of the string, the easiest way is:
$array = explode( ':', $string, 3 );
$number = $array[1];
You can use sscanfDocs to obtain the number from the string:
# Input:
$str = 'a:3:{i:0;i:2;i:1;i:3;i:2;i:4;}';
# Code:
sscanf($str, 'a:%d:', $number);
# Output:
echo $number; # 3
This is often more simple than using preg_match when you'd like to obtain a specific value from a string that follows a pattern.
preg_match() returns the number of times it finds a match, that's why. you need to add a third param. $matches in which it will store the matches.
You were not too far away with strpos() and substr()
$pos_start = strpos($str,'a:')+2;
$pos_end = strpos($str,':{')-2;
$result = substr($str,$pos_start,$pos_end);
preg_match only checks for appearance, it doesn't return any string.

PHP : simple string to array

I have strings like var=test;path=test.html
I want to convert these kind of strings like the array printed below :
Array
{
var => test
path => test.html,
}
I tried to use PHP's explode function for this task, but this is converting the string to associative array, and then i decided to convert that associate array to the one shown above.
But my own code isn't what i'm looking for, 'cause it contain 2 times PHP's explode function and some foreach loops, thus my own code will not stand in the department of performance for such a simple task.
Your help will be much appreciated, thanks.
Use parse_str for this:
http://www.php.net/manual/en/function.parse-str.php
You could explode by semicolon, then explode by =, and then use array_combine().
The solution is really not all that pretty, since it's quite verbose. I typed it out just in case, but you're probably better off with another method.
$s = "var=test;path=test.html";
$b = array_map(function($x){return explode("=", $x); }, explode(";", $s));
$c1 = array_map(function($x){return $x[0]; }, $b);
$c2 = array_map(function($x){return $x[1]; }, $b);
$result = array_combine($c1, $c2);
You could use preg_match_all to get an array of keys, and an array of values, then combine them into an associative array using array_combine:
$str = "var=test;path=test.html";
preg_match_all("/([^;=]+)=([^;=]+)/", $str, $matches);
$result = array_combine($matches[1], $matches[2]);
I just figured out how you can do that by using the parse_str php built-in function.
From the php.ini documentation:
; List of separator(s) used by PHP to parse input URLs into variables.
; PHP's default setting is "&".
; NOTE: Every character in this directive is considered as separator!
; http://php.net/arg-separator.input
; Example:
;arg_separator.input = ";&"
So, if you do this:
ini_set('arg_separator.input', ';&');
The parse_str should explode query arguments both on ; and &. This shouldn't affect in any way the filling of $_GET and $_POST since they are loaded before your code execution. If you want to be sure you don't affect the behavior of any other function calling parse_str, you could use a function like this:
function my_parse_str($str, &$arr) {
$orig = ini_get('arg_separator.input');
ini_set('arg_separator.input', ';');
parse_str($str, $arr);
ini_set('arg_separator.input', $orig);
}
Two advantages over exploding on & and then on =:
Maximum execution speed since the parse_str() function is built-in
parse_str() also considers recursive splitting: a=1&a=2 -> array('a'=>array('1', '2')); or 'a[one]=1&a[two]=2' -> array('a'=>array('one'=>'1', 'two'=>'2')).
Update - performance benchmarking
I just run a test to compare the plain-php splitting vs parse_str(), on an array of 10000 query strings each made of 500 arguments. The my_parse_str() above took ~0.952 seconds, while the pure-php one (parseQueryString()) took ~4.25 seconds.
It would require a larger set of data to test exactly how much it is faster, but it's pretty clear which one wins :) (if you want the test data + scripts, I'll upload them somewhere, since the data file is 125MB).
How about str_replace?
$text = "var=test;path=test.html";
$text = str_replace(';',"\n\t", $text);
$text = str_replace('='," => ", $text);
echo <<<END
Array
{
\t$text
}
END;
You'll need to do some extra work to get the proper formatting, though

Categories