I am currently making a BBCode class for my website.
I need to do the following.
function bbCode([skill]Q[/skill]_________[skill]Q[/skill]_________[skill]Q[/skill]);
bbCode function has to replace all Q's between [skill] and [/skill] tags, and replace it with $skillArray['Q'] value. ($skillArray is character dependant.)
How can I do this?
A little clearer version is:
For example you're on a page of "Orc" character.
[skill]Q[/skill] tag should get "Orc's Q skill name" automatically.
For example you're on a page of "Hunter" character.
[skill]Q[/skill] tag should get "Hunter's Q skill name" automatically.
Ps. Don't want to use explode.
Assuming the tags you want to be replaced are within some form of template, you could use file_get_contents and then loop through the tags you want to replace with the desired values, for example:
$file = file_get_contents ( 'yourfile.php' );
$skillArray = array ( 'Q' => 'Hunter name' );
foreach ( $skillArray as $key => $val )
{
$file = str_replace ( '[skill]' . $key . '[\skill]', $val, $file );
}
Thats just a completely rough example, but if I'm understanding what you are trying to do; that should be along the right lines....
This is what you need
$data = "[skill]Q[/skill]_________[skill]Q[/skill]_________[skill]Q[/skill]";
$r['Q'] = "Yahoo";
function b($a){
global $r;
return $r[$a[1]];
}
$data = preg_replace_callback('|\[skill\](Q)\[\/skill\]|', 'b' , $data);
var_dump($data);
If you want to replace all the Qs with single "Yahoo" use Q+ instead of Q. If you want to match all words use \w+.
<?php
$skillArray=array('Q'=>'fishing');
$txt="test [skill]Q[/skill] test";
$txt=preg_replace("#\[skill\](.*)\[\/skill\]#e",'$skillArray["$1"]',$txt);
echo $txt; //test fishing test
?>
Related
I am making a price crawler for a project but am running into a bit of an issue. I am using the below code to extract values from an html page:
$content = file_get_contents($_POST['url']);
$resultsArray = array();
$sqlresult = array();
$priceElement = explode( '<div>value I want to extract</div>' , $content );
Now when I use this to get certain elements I only get back
Finance: {{value * value2}}
I want to get the actual value that would be displayed on the screen e.g
Finance: 7.96
The other php methods I have tried are:
curl
file_get_html(using simple_html_dom library)
None of these work either :( Any ideas what I can do?
You just set the <div>value I want to extract</div> as a delimiter, which means PHP looks for it to separate your string to array whenever this occurs.
In the following code we use , character as a delimiter:
<?php
$string = "apple,banana,lemon";
$array = explode(',', $string);
echo $array[1];
?>
The output should be this:
banana
In your example you set the value you want to extract as a delimiter. That's why this happens to you. You'll need to set a delimiter between your string you want to obtain and other string you won't need at the moment.
For example:
<?php
$string = "iDontNeedThis-dontExtractNow-value I want to extract-dontNeedEither";
$priceElement = explode('-', $string);
echo "<div>".$priceElement[2]."</div>";
?>
The code should output this to your HTML page:
<div>value I want to extract</div>
And it will appear on your page like this:
value I want to extract
If you don't need to save the whole array in a variable, you can save the one index of it to variable instead:
$priceElement = explode('-', $string)[2];
echo $priceElement;
This will save only value I want to extract so you won't have to deal with arrays later on.
I have a PHP project ( Using laravel ) and I need to show just part of an article in the view . For example this is the full content of article :
Hello World It is my First Post and I decided to share it on my
personal blog .
and I wanted to show part of that in the recent posts part such this :
Hello world it is ...
I made a function but it doesn't work when I want to limit the text ( But there is no problem with short texts ) This is my function :
function limitText($text,$length=300) {
if(strlen($text)<$length) {
$new = $text."...";
return $new;
}
$new = substr($text,0,$length);
$new = $new."...";
return $new; }
any idea or suggestion ?
One way to do that is to use str_limit()
$value = str_limit('Just string', 4, '...'); // Output is 'Just...'
The str_limit function limits the number of characters in a string. The function accepts a string as its first argument and the maximum number of resulting characters as its second argument
I am creating an OpenCart extension where the admin can change his email templates using the user interface in the admin panel.
I would like the user to have the option to add variables to his custom email templates. For example he could put in:
Hello $order['customer_firstname'], your order has been processed.
At this point $order would be undefined, the user is simply telling defining the message that is to be sent. This would be stored to the database and called when the email is to be sent.
The problem is, how do I get "$order['customer_firstname']" to become a litteral string, and then be converted to a variable when necessary?
Thanks
Peter
If I understand your question correctly, you could do something like this:
The customer has a textarea or similar to input the template
Dear %NAME%, blah blah %SOMETHING%
Then you could have
$values = array('%SOMETHING%' => $order['something'], '%NAME%' => $order['name']);
$str = str_replace(array_keys($values), array_values($values), $str);
the user will be using around 40 variables. Is there a way I can set it to do that for each "%VARIABLE%"?
Yes, you can do so for each variable easily with the help of a callback function.
This allows you, to process each match with a function of your choice, returning the desired replacement.
$processed = preg_replace_callback("/%(\S+)%/", function($matches) {
$name = $matches[1]; // between the % signs
$replacement = get_replacement_if_valid($name);
return $replacement;
},
$text_to_replace_in
);
From here, you can do anything you like, dot notation, for example:
function get_replacement_if_valid($name) {
list($var, $key) = explode(".", $name);
if ($var === "order") {
$order = init_oder(); // symbolic
if(array_key_exists($key, $order)) {
return $order[$key];
}
}
return "<invalid key: $name>";
}
This simplistic implementation allows you, to process replacements such as %order.name% substituting them with $order['name'].
You could define your own simple template engine:
function template($text, $context) {
$tags = preg_match_all('~%([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)%~', $text, $matches);
for($i = 0; $i < count($matches[0]); $i++) {
$subject = $matches[0][$i];
$ctx = $matches[1][$i];
$key = $matches[3][$i];
$value = $context[$ctx][$key];
$text = str_replace($subject, $value, $text);
}
return $text;
}
This allows you to transform a string like this:
$text = 'Hello %order.name%. You have %order.percent%% discount. Pay a total ammount of %payment.ammount% using %payment.type%.';
$templated = template($text, array(
'order' => array(
'name' => 'Alex',
'percent' => 20
),
'payment' => array(
'type' => 'VISA',
'ammount' => '$299.9'
)
));
echo $templated;
Into this:
Hello Alex. You have 20% discount. Pay a total ammount of $299.9 using VISA.
This allows you to have any number of variables defined.
If you want to keep the PHP-syntax, then a regex would be appropriate to filter them:
$text = preg_replace(
"/ [$] (\w+) \[ '? (\w+) \'? \] /exi",
"$$1['$2']", # basically a constrained eval
$text
);
Note that it needs to be executed in the same scope as $order is defined. Else (and preferrably) use preg_replace_callback instead for maximum flexibility.
You could also allow another syntax this way. For example {order[customer]} or %order.customer% is more common and possibly easier to use than the PHP syntax.
You can store it as Hello $order['customer_firstname'] and while accessing make sure you have double-quotes "" to convert the variable to its corresponding value.
echo "Hello $order['customer_firstname']";
Edit: As per the comments, a variation to Prash's answer,
str_replace('%CUSTOMERNAME%', $order['customer_name'], $str);
What you're looking for is:
eval("echo \"" . $input . "\";");
but please, PLEASE don't do that, because that lets the user run any code he wants.
A much better way would be a custom template-ish system, where you provide a list of available values for the user to drop in the code using something like %user_firstname%. Then, you can use str_replace and friends to swap those tags out with the actual values, but you can still scan for any sort of malicious code.
This is why Markdown and similar are popular; they give the user control over presentation of his content while still making it easy to scan for HTML/JS/PHP/SQL injection/anything else they might try to sneak in, because whitelisting is easier than blacklisting.
Perhaps you can have a template like this:
$tpl = "Hello {$order['customer_firstname']}, your order has been processed.".
If $order and that specific key is not null, you can use echo $tpl directly and show the content of 'customer_firstname' key in the text. The key are the curly braces here.
I'm trying to simulate a bbcode tag, like code below:
[code]this is code to render[/code]
[code attributeA=arg]this is code to render[/code]
[code attribute C=arg anotherAtributte=anotherArg]this is code to render[/code]
As you can see, the code tag can take as many attributes as needed, also could exists too many code tags in the same "publishment". I only have dealed with easiest tags like img, b, a, i. For example:
$result = preg_replace('#\[link\=(.+)\](.+)\[\/link\]#iUs', '$2', $publishment);
That works fine since it returns the final markup. But, in the code tag I need to have the "attributes" and "values" in array in order to build the markup myselft according to these attributes in order to simulate someting like this:
$code_tag = someFunction("[code ??=?? ...] content [/code]", $array );
//build the markup myself
$attribute1 = array_contains("attribute1", $array)? $array["attribute1"] : "";
echo '<pre {$attribute1}>' . $array['content'] . </pre>
So, I don't expect that you do it entirely for me, I need you just help to take me to the right direction because I never have used regex.
Thank you in advance
I like to use preg_replace_callback for such things:
function codecb($matches)
{
$original=$matches[0];
$parameters=$matches[1];
$content=$matches[2];
return "<pre>". $content ."</pre>";
}
preg_replace_callback("#\[code(.*)\](.+)\[\/code\]#iUs", "codecb", $str);
so when you have [code argA=test argB=test]This is content[/code] then in the function "codecb" you will have:
$original = "[code argA=test argB=test]This is content[/code]"
$parameters = " argA=test argB=test"
$content = "This is content"
and can preg_match the arguments and return the replacement for the whole.
I'm writing a mail class that pulls content stored in a database and loads it into a template before sending it as a HTML e-mail. However, because each e-mail contains PHP variables and dynamic content, I've decided to use delimiters. So instead of the content looking like:
Hello $username, welcome to the site.
It'll look like:
Hello {{username}}, welcome to the site.
So far I'm using these methods:
function load($name,$content)
{
// preps the template for HTML
}
function content($template_id)
{
$template = $this->db->get_where('email_templates',array('id'=>$template_id));
return $template->content;
}
function new_email($email,$name,$user_type)
{
$msg = $this->load($name,$this->content(1));
$this->send($email,'Thanks for your application',$msg,1);
}
The trouble I'm having is how to convert a {{variable}} into a $variable so that it will parse - I don't want it to just be loaded as $username in the e-mail template. Is it just a case of using regular expressions and escaping the string so that it'll parse? Something like:
$content = str_replace("{{","'.$",$template->content);
$content = str_replace("}}",".'",$template->content);
Or is this flawed? Does anybody know what's the best thing to do?
I would not create my own templating system, because there are existing ones out there.
The most popular is probably Smarty, but there is an another one which has the same format as you created, that is mustache.
Update:
The problem with your code is that you're replacing the {{ to a .$ and store that in $content variable, then replacing }} to . and overwrite this replaced $content variable.
A possible working solution could be:
if (preg_match_all("/{{(.*?)}}/", $template, $m)) {
foreach ($m[1] as $i => $varname) {
$template = str_replace($m[0][$i], sprintf('$%s', $varname), $template);
}
}
But then you would also need to eval your code somehow.
So after converting {{variable}} to $variable in your email template, you will use eval to get it replaced by the actual contents of that variable?
Why not just replace {{variable}} with the contents of $variable straight away?
Perhaps have a function that takes the template text and an array of placeholder => "text to replace it with". Then it's as simple as making up the placeholders' exact strings by adding {{ and }} around that array's key and doing str_replace.
foreach ($replacements as $placeholder => $value) {
$placeholder = "{{" . $placeholder . "}}" ;
$text = str_replace($placeholder, $value, $text) ;
}
Couple this with (class) constants for the placeholders and you have a very solid and typo-repelant templating system. It will not be as elegant or easy to use as a full blown templating solution, and it might require extra work from whoever writes code that uses it, but they will not make mistakes during development due to mis-named variables.
If you are going to do it yourself it is probably best to just be explicit with str_replace. If you try to convert the curly bracers to $ you'll then need to eval() which is a potential security hole.
This would be my approach with str_replace - this becomes difficult to maintain as you add more variables but it really doesn't get much simpler either.
$content = str_replace(
array('{{username}}','{{var2}}'),
array($username,$var2),
$template->content
);
use preg_replace_callback , see : http://codepad.org/EvzwTqzJ
<?php
$myTemplateStr = "Hello {{username}} , this is {{subject}} ,and other string {{example}}";
$tagRegex = "|{{(.*?)}}|is";
$result = preg_replace_callback($tagRegex,"myReplaceFunc",$myTemplateStr);
echo $result ;
/* output :
Hello $username , this is $subject ,and other string {{example}}
*/
function myReplaceFunc($matches)
{
$validTags = array('username','subject','name');
$theFull = $matches[0];
$theTag = $matches[1];
if(in_array($theTag,$validTags) == true)
return '$'.$theTag;
return $theFull ;
}
?>
$template = "Hello {{username}} , this is {{subject}} ,and other the answer is on page {{example}}";
$replacements = array(
'username' => 'Jeffrey',
'subject' => 'your final notice',
'page' => 43
);
function bind_to_template($replacements, $template) {
return preg_replace_callback('/{{(.+?)}}/',
function($matches) use ($replacements) {
return $replacements[$matches[1]];
}, $template);
}
echo bind_to_template($replacements, $template);
Credit to https://www.labnol.org/code/19266-php-templates