can't understand how it works preg_match, tryed today few hours to create my function with lot of examples, even documentation and didnt help me. so need yours help please.
need te get 2 elements
first is element name menu, secound is content between tags {main}
looks like
{main item=menu} bla bla bla{/main}
An simple regex would be /\{([a-z]+)\s*item=([a-z]+)\}(.*?)\{\/\1\}/. Applied to your example, this would return the matching groups main, menu and bla bla bla.
if (preg_match('/\{([a-z]+)\s*item=([a-z]+)\}(.*?)\{\/\1\}/', $data, $m)) {
if ($m[2] == 'menu') {
// do something usefull..
$content = $m[3];
}
}
you could even use preg_match_all, to iterate over all elements, matching this pattern.
Related
Here's my problem. I'll try to keep it concise:
I have a wab page that displays the texts in the selected language like this:
<p><?php echo $langFile->data->message; ?></p>
The actual text can look like this:
Hello, %1. You have %2 orders. If you %forgot% your password click %here% !
So I have to write a function that can replace (called one time for each replacement) the %1 and %2 with certain texts, and the words between % to be replaced with a link text. The reason it's tricky is that I can have texts that look like this:
Bla bla %1, bla %yada yada %2 yada% bla bla bla.
So here, the function has to replace %yada yada %2 yada% with a linkable text and, when called again, can replace %2 with another text.
I'm kind of new with programming, so I could use some pointers since I don't know how to get where I want if even possible. Thanks a lot in advance.
Regards
$whatever = explode('%', $something);
Then run through it like any other array. If you can find a common denominator and explode it, you can usually get any puzzle of regex or if/then to work how you need. The logic practically reveals itself afterwards.
As an example, I tried to find a way to guarantee removal of ALL script tags. Honestly, no one's regex worked. Then, I found the common denominator in html that I can use. I came up with this. It will guarantee to strip all script tags. Of course, it's only this simple with script tags because they won't be nested. However, it's a great example of how to use "exploding logic" or "accordion coding" to get your mind wrapped around the problem and make it happen.
$h = explode('>', $html);
foreach($h as $k => $v){
$v = trim($v);
if(preg_match('/^(<script[.*]*)/ius', $v)){
$counter = $k;//starting key of the script stored for later
}elseif(preg_match('/([.*]*<\/script$)/ius', $v)){
$script = $k - $counter;//difference between opening and closing tag
$counter = 0;//reset counter for next script
for($i = $script; $i >= 0; $i--){//now use the keys to empty everything in between
$h[$k-$i] = '';
}
}
}
for($i = 0; $i <= count($h); $i++){
if($h[$i] != ''){
$ht[$i] = $h[$i];//clean out the blanks so when we implode it works right.
}
}
$html = implode('> ', $ht);//all scripts stripped.GUARANTEED
I believe you can use this same idea with what you are trying to do. Though your internal statements will vary, but you will begin to see how it can flow more easily and actually show progress on what you are trying to do.
Try this: preg_replace http://php.net/manual/es/function.preg-replace.php
May be %[1-9] for the %1, %2, %3 and %[A-Za-z ]+% for the other.
There is something important... You should change the % to any other caracter for one of the cases... that make easier the search, because...
This case is easy: Hello, %1. You have %2 orders. If you %forgot% your password click %here% !
This is not: Bla bla %1, bla %yada yada %2 yada% bla bla bla.
But this, for example is easier: Bla bla #1, bla %yada yada #2 yada% bla bla bla.
Rather than using % you can use string variables in the text (unless you're writing some sort of a dynamic thing that will allow people to add their own vars like a CMS). You would make the variables come out of a database or something like that for the different languages. Example:
$name = 'Bob';
$salutation = "Hello, $name.";
$order_count = '2';
if ($order_count == '1'){
$ordertext = "You have $order_count order.";
} else{
$ordertext = "You have $order_count orders.";
}
$forgot = 'forgot';
$link = 'http://www.domain.com/reset/password';
$forgotphrase = "If you $forgot your password click <a href='$link'>here</a>!";
$message = $salutation.$ordertext.$forgotphrase;
Output
Hello, Bob. You have 2 orders. If you forgot your password click here!
Update
To do this on a larger scale you could have a database table called 'phrasing'.
id,salutation,ordertext_plur,ordertext_sing,forgot,link,forgotphrase,language,updated
So in MySQL might look like this:
1,
'Hello, $name.',
'You have $order_count orders.',
'You have $order_count order.',
'forgot',
'http://www.domain.com/reset/password/en',
'If you $forgot your password click <a href='$link'>here</a>!',
'EN',
'2013-04-23 00:00:00'
Your SQL statement would look like:
select * from phrasing where language='EN';
Then you would assign the appropriate vars based on the output. You would have to give more thought to how you would implement this and how large the database should be.
Other thoughts You might consider using something like the Google Translate Gadget on your pages to translate the HTML code, instead of hard-coding translations into the database. Their database of translations is updated daily. Some of my large international clients use it instead of paying the money to translate into every language. Also it makes it easier to make changes to the code in one language without having to worry about missing it in others.
I know a bit about Regular Expression but really want to learn more about it and now i'm trying to make a function that detects all {} in my content (from a database) and checks what between the brackets. If there is a POST or GET with a name (format: POST:name or GET:name} i would like to replace them with that value.
Example:
When i have a form with the following inputs:
Name
Email
Message
And then in the value attribute i type: {POST:Name}
Then the script must detect the {POST:Name} and will replace it with the string in $_POST['name']. I already searched on Google, but found too much that i don't know what to really use.
Now i have:
<?php
preg_match_all("/{(POST|GET):[.*](})/", $content, $matches, PREG_SET_ORDER);
foreach($matches AS $match)
{
if(isset($_POST[$match]))
$content = str_replace('{POST:'.$match, $_POST[$match], $content);
else
$content = str_replace('{GET:'.$match, $_GET[$match], $content);
}
?>
But this don't work.
You should use preg_replace, better than str_replace.
And if you use preg_replace, you don't need no more your first condition, et can do the same code with only one instruction.
http://fr2.php.net/preg_replace
<?php preg_replace('#{(POST|GET):(.*)}#','$_$1[$2]',$content); ?>
My regex can be false, but something like this should work.
I am trying to create a Wordpress shortcode-style feature in PHP to replace shortcodes like "[[133]]" with images. Basically, I have a MySQL table of image URLs/titles/subtitles with IDs 1-150, and I want to be able to dynamically insert them into the text of my pages with shortcodes like this:
Blabla bla bla bla bla. [[5]] Also, bla bla bla bla bla [[27]]
Hey, and bla bla bla! [[129]]
So, I just want to grab the ID as $id, and then feed it to a MySQL query like
mysql_query("SELECT title,subtitle,url FROM images WHERE id = $id")
and then replace the "[[id]]" with the img/title/subtitle. I would like to be able to do this multiple times on the same page.
I know this has to involve regex and some combination of preg_match, preg_replace, strstr, strpos, substr... but I don't know where to start and which functions I should be using to do which things. Can you recommend a strategy? I don't need the code itself—just knowing what to use for which parts would be extremely helpful.
If you want to be able to write shortcodes like this :
[[function_name_suffix parameter1 parameter2 ...]]
here is a more complete way, using preg_replace_callback and call_user_func_array to implement parameterized shortcodes.
function shortcodify($string){
return preg_replace_callback('#\[\[(.*?)\]\]#', function ($matches) {
$whitespace_explode = explode(" ", $matches[1]);
$fnName = 'shortcode_'.array_shift($whitespace_explode);
return function_exists($fnName) ? call_user_func_array($fnName,$whitespace_explode) : $matches[0];
}, $string);
}
If this function is defined :
function shortcode_name($firstname="",$lastname=""){
return "<span class='firstname'>".$firstname."</span> <span class='lastname'>".$lastname."</span>";
}
Then this call
print shortcodify("My name is [[name armel larcier]]");
Will output :
My name is <span class='firstname'>armel</span> <span class='lastname'>larcier</span>
This is just something I implemented right now based on supertrue's idea.
Any feedback is more than welcome.
With a function getimage($id) that does the MySQL query and formats the replacement text, this almost does everything you need:
$text = "Blabla [[5]] and [[111]] bla bla bla [[27]] and bla bla bla! [[129]]";
$zpreg = preg_match_all('#\[\[(\d{1,3})\]\]#', $text, $matches );
var_dump( $matches[1] );
$newtext = preg_replace('#\[\[(\d{1,3})\]\]#', getimage($matches[1][?????]), $text);
echo $newtext;
I just need to figure out what to put inside getimage() (where ????? is) that will make it put in the right image for the right [[id]].
Refer preg_match_all and preg_replace on official documentation for more details.
Various different approaches can be taken for this, depending on how you plan to display ect,
Take the sentence "Hello [34] world"
Create a simple function e.g replaceCode($string)
function replaceCode($string){
$pos = strpos($string, '['); // Find the first occurrence of the bracket
if($pos != false){
// If everything is ok take the next 2 numbers from it
// Check for a close bracket & remove ]
// call another function to replace the number with the image text
}
}
If anymore occurrences of brackets are found, recursively call the function again, passing the rest of the string to the function again.
Note: Validation may need to be done first to ensure the [ and ] are properly balanced!
My bet is PHP's strtr function...
<?php
function get_profile_image($image_url){
return "<img src='{$image_url}' height='200px' width='200px' />";
}
$trans = array(
"[[1]]" => "Vishal",
"[[2]]" => "Kumar",
"[[3]]" => "Sahu",
"[[4]]" => "Web Designer",
"[[5]]" => "Draw and Paint",
"[[6]]" => ucwords("any programming language"),
"[[7]]" => strtoupper("PHP, JAVASCRIPT and HTML"),
"[[8]]" => get_profile_image("http://php.net/images/logos/php-logo.svg"),
"[[9]]" => "http://php.net/images/logos/php-logo.svg"
);
$str = <<<HEREDOC_1
[[8]]
<pre>My name is [[1]] [[2]] [[3]].
I am a [[4]] and I love to [[5]].
I don't know [[6]] but I know [[7]] little bit.</pre>
Here is my profile image <img src='[[9]]' alt='[[1]]-[[2]]-[[3]]-[[4]]' />
HEREDOC_1;
echo strtr($str, $trans);
it's output is
[http://php.net/images/logos/php-logo.svg] My name is Vishal Kumar
Sahu. I am a Web Designer and I love to Draw and Paint. I don't know
Any Programming Language but I know PHP, JAVASCRIPT AND HTML little
bit. Here is my profile image [Vishal-Kumar-Sahu-Web Designer]
It is working fine on 5.6.
The regex, I believe, would be:
/\[\[[1-9]{1,3}\]\]/g
(for a 1-to-3 digit number inside double brackets.)
can any body help me on separating this example of data that i need to parse and seperate text just like PHPDoc. It is PHP source code.
The example string :
function one_to_tree() {
//bla bla bla
return FALSE;
}
function two_to_tree() {
//bla bla bla
return FALSE;
}
function three_to_tree() {
if ($sample){ //bla bla bla }
return FALSE;
}
can anybody help me how to seperate above string based on "function" word and create and array. Thank you
I think you are looking for token_get_all().
This function uses the PHP parser to split PHP source code into tokens. I think it's safe to say it's the most reliable method of parsing PHP code - if it's usable for whatever you are planning to do.
An example from the manual:
$tokens = token_get_all('<?php echo; ?>');
Results in
array(
array(T_OPEN_TAG, '<?php'),
array(T_ECHO, 'echo'),
';',
array(T_CLOSE_TAG, '?>')
);
Okay so i set up this thing so that I can print out page that people came from, and then put dummy tags on certain pages. Some pages have commented out "linkto" tags with text in between them.
My problem is that some of my pages don't have "linkto" text. When I link to this page from there I want it to grab everything between "title" and "/title". How can I change the eregi so that if it turns up empty, it should then grab the title?
Here is what I have so far, I know I just need some kind of if/then but I'm a rank beginner. Thank you in advance for any help:
<?php
$filesource = $_SERVER['HTTP_REFERER'];
$a = fopen($filesource,"r"); //fopen("html_file.html","r");
$string = fread($a,1024);
?>
<?php
if (eregi("<linkto>(.*)</linkto>", $string, $out)) {
$outdata = $out[1];
}
//echo $outdata;
$outdatapart = explode( " " , $outdata);
echo $part[0];
?>
Here you go: if eregi() fails to match, the $outdata assignment will never happen as the if block will not be executed. If it matches, but there's nothing between the tags, $outdata will be assigned an empty string. In both cases, !$outdata will be true, so we can fallback to a second match on the title tag instead.
if(eregi("<linkto>(.*?)</linkto>", $string, $link_match)) {
$outdata = $link_match[1];
}
if(!$outdata && eregi("<title>(.*?)</title>", $string, $title_match)) {
$outdata = $title_match[1];
}
I also changed the (.*) in the match to (.*?). This means, don't be greedy. In the (.*) form, if you had $string set to
<title>Page Title</title> ...
... <iframe><title>A second title tag!</title></iframe>
The regex would match
Page Title</title> ... ... <iframe><title>A second title tag!
Because it tries to match as much as possible, as long as the text is between any and any other !. In the (.*?) form, the match does what you'd expect - it matches
Page Title
And stops as soon as it is able.
...
As an aside, this thing is an interesting scheme, but why do you need it? Pages can link to other pages and pass parameters via the query string:
...
Then somescript.php can access the prevpage parameter via the $_GET['prevpage'] superglobal variable.
Would that solve your problem?
The POSIX regex extension (ereg etc.) will be deprecated as of PHP 5.3.0 and may be gone completely come PHP 6, you're better off using the PCRE functions (preg_match and friends).
The PCRE functions are also faster, binary safe and support more features like non-greedy matching etc.
Just a pointer.
you need if, else.
if(eregi(...))
{
.
.
.
}
else
{
just grab title;
}
perhaps you should have done a quick google search to find this very simple answer.
Just add another if test before you assign the match to $outdata:
if (eregi("<linkto>(.*)</linkto>", $string, $out)) {
if ($out[1] != "") {
$outdata = $out[1];
} else {
// Look in the title.
}
}