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.
Related
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.
Plot: I am building a website where lots of videos will be indexed and I want to allow people to search for videos by keywords and sentences.
Problem: But as we all know Internet is crowded with bad people and robots who can search for bad words or sentences and I want to take them to a different page, So if the query matches specific blocked words they should be redirected to specific url.
<?php include'func.php';
if(!empty($_GET['q'])){
if ($badword ="no")
{$url='/search/'.preg_replace("/[^A-Za-z0-9[:space:]]/","-",$_GET['q']).'';}
else
{$url='/badsearch/'.preg_replace("/[^A-Za-z0-9[:space:]]/","-",$_GET['q']).'';}
}
else{$url='/';}
header('location:'.$url.''); ?>
I want a code something like this in which $badword contains bad words and I will love if I can have a broad match so searching for assassination will also be redirected to /badsearch/ because ass will be a bad word.
Searching and collecting everything took me to an answer. This answer may help other people.
This will also work if user enters DoG or cAt.
This will search for a word after every space so if you have a query like "I have a bad dog" this will work.
<?php
$banned_names = array('dog', 'cat', 'mydog');
$words = explode(" ",$_GET['q']);
if(!empty($_GET['q'])){
foreach($words as $word)
{
$word = strtolower($word);
if(in_array($word, $banned_names))
{$url='/is/bad/'.preg_replace("/[^A-Za-z0-9[:space:]]/","-",$_GET['q']).'/1';}
else
{{$url='/isnot/bad/'.preg_replace("/[^A-Za-z0-9[:space:]]/","-",$_GET['q']).'/1';}}
}
}
else{$url='/';}
header('location:'.$url.'');
?>
A straightforward solution might like this:
$user_input = $_GET['q']);
$badword_list= array("badword1", "badword2", "badword3", "badword4", ...);
if(in_array($user_input, $badword_list))
$url = "something";
else
$url = "something else";
or use if (preg_match('/\b(badword1|badword2|badword3|badword4)\b/i',$user_input ))
I know there are plenty of these, and that my PHP may be riddled with errors (I'm new to PHP), but I cant figure this one out.... it's citing the "function must be a string" error on line 11:
<?php
$dom=new DOMDocument();
$dom->formatOutput=true;
$dom->load('test.xml');
$searchItems=$dom->getElementsByTagName('title');
$voteItems=$dom->getElementsByTagName('vote');
for ($i=0; $i < $searchItems->length; $i++){
$value = $voteItems($i)->textContent;
$value++;
$name=$searchItems($i);
$xpath = new DOMXPath($dom);
$resulted = $xpath->query('div[#class="active"]');
$active= $div->$resulted->query('div[#class="content"]');
$names=$active->getAttribute('song');
preg_match($names, "i");
if(preg_match($names, $name )){
$voteItems($i)->length->textContent=$value;
$vote = voteItems($i)->length->textContent;
$results=array($name, $vote);
$txt=($name." scored: ".$vote." votes");
echo $txt;
}
}
?>
What this is doing, just in case there's a WAYYY better way to do this is, it checks and XML sheet I have that looks like this:
<playslist>
<song>
<source>imgs/Beck.jpg</source>
<title>Modern Guilt</title>
<artist>Beck</artist>
<vote>0</vote>
<plays>y</plays>
</song>
</playlist>
It checks for the title, and vote for each song, and stores those.
It then for each gets the value of the vote tag, adds one, then searches the HTML for the <div> with the class="active", and then searches that div with active and finds the inner div that has the class="content", then returns that div's "song" attribute.
I then have a preg match to check whether the name of the current "i" in the loop matches the string from the "song" attribute.
If it's a match, that "i"'s value will +1 to its value. It will then store that name value, and the new vote value as an array for me to check.
After that I'd like to save the XML sheet's new change. (otherwise I would've just kept this in JavaScript)
Any tips, hints, and help would be greatly appreciated! As a newbie to PHP I love to learn more!
$value = $voteItems($i)->textContent;
This is incorrect. You're trying to take $voteItems and use it as the name of a function.
PHP allows it:
function foo() {}
$name = "foo";
$name(); // calls foo()
However, that can only work if $name is a string. Here, $voteItems is a DOMNodeList, hence the error message.
From looking at the documentation, it seems like you meant to write:
$value = $voteItems->item($i)->textContent;
// ^^^^^^^^^^
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.)
I'm working on a simple templating system. Basically I'm setting it up such that a user would enter text populated with special tags of the form: <== variableName ==>
When the system would display the text it would search for all tags of the form mentioned and replace the variableName with its corresponding value from a database result.
I think this would require a regular expression but I'm really messed up in REGEX here. I'm using php btw.
Thanks for the help guys.
A rather quick and dirty hack here:
<?php
$teststring = "Hello <== tag ==>";
$values = array();
$values['tag'] = "world";
function replaceTag($name)
{
global $values;
return $values[$name];
}
echo preg_replace('/<== ([a-z]*) ==>/e','replaceTag(\'$1\')',$teststring);
Output:
Hello world
Simply place your 'variables' in the variable array and they will be replaced.
The e modifier to the regular expression tells it to eval the replacement, the [a-z] lets you name the "variables" using the characters a-z (you could use [a-z0-9] if you wanted to include numbers). Other than that its pretty much standard PHP.
Very useful - Pointed me to what I was looking for...
Replacing tags in a template e.g.
<<page_title>>, <<meta_description>>
with corresponding request variables e,g,
$_REQUEST['page_title'], $_REQUEST['meta_description'],
using a modified version of the code posted:
$html_output=preg_replace('/<<(\w+)>>/e', '$_REQUEST[\'$1\']', $template);
Easy to change this to replace template tags with values from a DB etc...
If you are doing a simple replace, then you don't need to use a regexp. You can just use str_replace() which is quicker.
(I'm assuming your '<== ' and ' ==>' are delimiting your template var and are replaced with your value?)
$subject = str_replace('<== '.$varName.' ==>', $varValue, $subject);
And to cycle through all your template vars...
$tplVars = array();
$tplVars['ONE'] = 'This is One';
$tplVars['TWO'] = 'This is Two';
// etc.
// $subject is your original document
foreach ($tplVars as $varName => $varValue) {
$subject = str_replace('<== '.$varName.' ==>', $varValue, $subject);
}