I would like to extract any first char of any word inside a sentence like:
Full time become FT
Part time become PT
Contractor become C
Temp become T
Is that possible in smarty PHP and how? I have {$listing.EmployementType}.
{assign var=firstWord value=" "|explode:"$listing.EmployementType"}
then access the first word by $firstWord[0]..
you might want to look in to it further..
http://www.smarty.net/forums/viewtopic.php?p=6581&sid=f8cc8323a968506f305c803e94f522f1
Here is a somewhat functional way to do it:
function firstLetter($word) {
return uc($word[0]);
}
$result = implode('', array_map('firstLetter', explode(' ', $sentence)));
http://au2.php.net/array_map
http://au1.php.net/explode
http://au1.php.net/manual/en/function.implode.php
Edit: alternatively,
$result = '';
$words = explode(' ', $sentence);
foreach ($words as $word) {
$result .= uc($word[0]);
}
Actually shorter and probably more readable, but less fun haha.
Edit 2: sorry, didn't realise smarty was a requirement of the question. I'll just leave this here in case someone else looking for a pure php solution stumbles upon this question.
Create a smarty plugin that fits your requirements. In this case, a modifier plugin.
If you know some basic php it's very easy: http://www.smarty.net/docs/en/plugins
Related
I'm currently trying out this PHP preg_replace function and I've run into a small problem. I want to replace all the tags with a div with an ID, unique for every div, so I thought I would add it into a for loop. But in some strange way, it only do the first line and gives it an ID of 49, which is the last ID they can get. Here's my code:
$res = mysqli_query($mysqli, "SELECT * FROM song WHERE id = 1");
$row = mysqli_fetch_assoc($res);
mysqli_set_charset("utf8");
$lyric = $row['lyric'];
$lyricHTML = nl2br($lyric);
$lines_arr = preg_split('[<br />]',$lyricHTML);
$lines = count($lines_arr);
for($i = 0; $i < $lines; $i++) {
$string = preg_replace(']<br />]', '</h4><h4 id="no'.$i.'">', $lyricHTML, 1);
echo $i;
}
echo '<h4>';
echo $string;
echo '</h4>';
How it works is that I have a large amount of text in my database, and when I add it into the lyric variable, it's just plain text. But when I nl2br it, it gets after every line, which I use here. I get the number of by using the little "lines_arr" method as you can see, and then basically iterate in a for loop.
The only problem is that it only outputs on the first line and gives that an ID of 49. When I move it outside the for loop and removes the limit, it works and all lines gets an <h4> around them, but then I don't get the unique ID I need.
This is some text I pulled out from the database
Mama called about the paper turns out they wrote about me
Now my broken heart´s the only thing that's broke about me
So many people should have seen what we got going on
I only wanna put my heart and my life in songs
Writing about the pain I felt with my daddy gone
About the emptiness I felt when I sat alone
About the happiness I feel when I sing it loud
He should have heard the noise we made with the happy crowd
Did my Gran Daddy know he taught me what a poem was
How you can use a sentence or just a simple pause
What will I say when my kids ask me who my daddy was
I thought about it for a while and I'm at a loss
Knowing that I´m gonna live my whole life without him
I found out a lot of things I never knew about him
All I know is that I´ll never really be alone
Cause we gotta lot of love and a happy home
And my goal is to give every line an <h4 id="no1">TEXT</h4> for example, and the number after no, like no1 or no4 should be incremented every iteration, that's why I chose a for-loop.
Looks like you need to escape your regexp
preg_replace('/\[<br \/\]/', ...);
Really though, this is a classic XY Problem. Instead of asking us how to fix your solution, you should ask us how to solve your problem.
Show us some example text in the database and then show us how you would like it to be formatted. It's very likely there's a better way.
I would use array_walk for this. ideone demo here
$lines = preg_split("/[\r\n]+/", $row['lyric']);
array_walk($lines, function(&$line, $idx) {
$line = sprintf("<h4 id='no%d'>%s</h4>", $idx+1, $line);
});
echo implode("\n", $lines);
Output
<h4 id="no1">Mama called about the paper turns out they wrote about me</h4>
<h4 id="no2">Now my broken heart's the only thing that's broke about me</h4>
<h4 id="no3">So many people should have seen what we got going on</h4>
...
<h4 id="no16">Cause we gotta lot of love and a happy home</h4>
Explanation of solution
nl2br doesn't really help us here. It converts \n to <br /> but then we'd just end up splitting the string on the br. We might as well split using \n to start with. I'm going to use /[\r\n]+/ because it splits one or more \r, \n, and \r\n.
$lines = preg_split("/[\r\n]+/", $row['lyric']);
Now we have an array of strings, each containing one line of lyrics. But we want to wrap each string in an <h4 id="noX">...</h4> where X is the number of the line.
Ordinarily we would use array_map for this, but the array_map callback does not receive an index argument. Instead we will use array_walk which does receive the index.
One more note about this line, is the use of &$line as the callback parameter. This allows us to alter the contents of the $line and have it "saved" in our original $lyrics array. (See the Example #1 in the PHP docs to compare the difference).
array_walk($lines, function(&$line, $idx) {
Here's where the h4 comes in. I use sprintf for formatting HTML strings because I think they are more readable. And it allows you to control how the arguments are output without adding a bunch of view logic in the "template".
Here's the world's tiniest template: '<h4 id="no%d">%s</h4>'. It has two inputs, %d and %s. The first will be output as a number (our line number), and the second will be output as a string (our lyrics).
$line = sprintf('<h4 id="no%d">%s</h4>', $idx+1, $line);
Close the array_walk callback function
});
Now $lines is an array of our newly-formatted lyrics. Let's output the lyrics by separating each line with a \n.
echo implode("\n", $lines);
Done!
If your text in db is in every line why just not explode it with \n character?
Always try to find a solution without using preg set of functions, because they are heavy memory consumers:
I would go lke this:
$lyric = $row['lyric'];
$lyrics =explode("\n",$lyrics);
$lyricsHtml=null;
$i=0;
foreach($lyrics as $val){
$i++;
$lyricsHtml[] = '<h4 id="no'.$i.'">'.$val.'</h4>';
}
$lyricsHtml = implode("\n",$lyricsHtml);
An other way with preg_replace_callback:
$id = 0;
$lyric = preg_replace_callback('~(^)|$~m',
function ($m) use (&$id) {
return (isset($m[1])) ? '<h4 id="no' . ++$id . '">' : '</h4>'; },
$lyric);
I wanted to write a line of code that contains a long string such as:
addError("This is a really really really really really really really long text");
however I wanted to split the text into multiple lines. How can this be possible aside from this way:
addError("This is a really really really really really really" .
"really long text");
EDIT: I need it such that it dosen't do line breaks either. (forget about that SQL thing i said earlier)
If SQL syntax highlighting is your problem, you can probably format it properly using a heredoc, and still get the IDE's syntax highlighting working:
$query = <<<EOD
select *
from foo
where bar
EOD;
do_query($query);
http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc
If you don't want line breaks, your way of doing it now seems right. With the above, you'd need to remove the line breaks afterwards, e.g. str_replace("\n", " ", $str).
Try this :-
$t = 'This is a really really really really really really';
$t .= ' really really really really really really';
$t .= ' really really really really really really';
$t .= ' long string';
addError( $t );
Assuming you are trying to break the output to rows, you can use str_split( $string, $chunk_length ).
This will split the long text into array of strings with a fixed length.
$array_of_strings = str_split($str, 100);//100 represents the length of the chunk
foreach ($array_of_strings as $line) {
echo $line . '<br>';
}
You can also use chunck_split();
Hope this helps!
Problem
I'd like to expand variables in a string in the same manner that variable in a double quoted string get expanded.
$string = '<p>It took $replace s</>';
$replace = 40;
expression_i_look_for;
$string should become '<p>It took 40 s</>';
I see a obvious solution like this:
$string = str_replace('"', '\"', $string);
eval('$string = "$string";');
But I really don't like it, because eval() is insecure. Is there any other way to do this ?
Context
I'm building a simple templateing engine, that's where I need this.
Example Template (view_file.php)
<h1>$title</h1>
<p>$content</p>
Template rendering (simplified code):
$params = array('title' => ...);
function render($view_file, $params)
extract($params)
ob_start();
include($view_file);
$text = ob_get_contents();
ob_end_clean();
expression_i_look_for; // this will expand the variables in the template
return $text;
}
The expansion of the variables in the template simplifies it's syntax. Without it, the above example template would be:
<h1><?php echo $title;?></h1>
<p><?php echo $content;?></p>
Do you think this approach is good ? Or should I look in another direction ?
Edit
Finally I understand that there is no simple solution due to flexible way PHP expands variables (even ${$var}->member[0] would be valid.
So there are only two options:
Adopt an existing full fledged templating system
Stick with something very basic that essentially is limited to including the view files via include.
I would rather suggest using some existing template engines, like for example Smarty, but if you really want to do it by yourself you can use the simple regular expression to match all variables constructed with for example letters and numbers and then replace them with correct variables:
<?php
$text = 'hello $world, what is the $matter? I like $world!';
preg_match_all('/\$([a-zA-Z0-9]+)/',
$text,
$out, PREG_PATTERN_ORDER);
$world = 'World';
$matter = 'matter';
foreach(array_unique($out[1]) as $variable){
$text=str_replace('$'.$variable, $$variable, $text);
}
echo $text;
?>
prints
hello World, what is the matter? I like World!
Parse
Parse the string look for $ followed by valid variable name (i.e. \[a-zA-Z_\x7f-\xff\]\[a-zA-Z0-9_\x7f-\xff\]*)
Variable²
Use variable variables syntax (i.e. $$var notation).
Are you trying to do this?
templater.php:
<?php
$first = "first";
$second = "second";
$third = "third";
include('template.php');
template.php:
<?php
echo 'The '.$first.', '.$second.', and '.$third.' variables in a string!';
When templater.php is run, produces:
"The first, second, and third variables in a string!"
Do you want something like this ?
$replace = 40;
$string = '<p>It took {$replace}s</p>';
Instead of using single quotes
$string = '<p>It took $replace s</>';
$replace = 40;
use double quotes
$replace = 40;
$string = "<p>It took $replace s</>";
However, for readability and to enable you to remove the space between $replace and the s I would use:
$replace = 40;
string = '<p>It took ' . $replace . 's</>';
The correct way is probably to parse your document as a tree, identify your parser tags ( because you are managing your own parser they don't have to follow php conventions if you don't want them to ) and then add in your values from an associative array or other data structure as the opportunity arises.
This is a more complex solution but will make it far easier when you realise that you want to be able to display lists whose length is unknown ahead of time using some kind of looping structure based on a standard display option. In the long run, you won't find many serious templating systems that aren't parsing the documents into some kind of in-memory tree where the placeholders can be inserted and then the document constructed as required. This also offers many opportunities for cacheing. Also, if you are unafraid of recursion you will be able to perform a lot of operations on it fairly simply.
However, this is not an uncommon problem to solve and as I commented on the question, there are almost guaranteed to be libraries and extensions around that provide most of the functionality you need. Unless this is a purely academic process for you, I would find some existing solutions and either use one of those or get a solid understanding of how it works so you have a starting point for adapting your own solution.
This is a snippet I pulled out from Lejlot's answer. I tested it and it works fine.
function resolve_vars_in_str( $input )
{
preg_match_all('/\$([a-zA-Z0-9]+)/', $input, $out, PREG_PATTERN_ORDER);
foreach(array_unique($out[1]) as $variable) $input=str_replace('$'.$variable, $GLOBALS["$variable"], $input);
return $input ;
}
As part of a CMS admin, I would like to scan new articles for specific keyphrases/tags that are stored in a mysql db.
I am proficient enough to be able to pull the list of keywords out, loop through them and do stripos, and substr_count to build an array of the found keywords. but the average article is about 700 words and there are 16,000 tags and growing so currently the loop takes about 0.5s which was longer than I had hoped, and will only ever get longer.
Is there a better way of doing this? Even if this type of procedure has a special name, that could help.
I have PHP 5.3 on Fedora, it is also on dedicated servers so I don't have any shared host issues.
EDIT - I am such a scatterbrain, I swore blind that I copy and pasted some code! clearly not
$found = array();
while($row = $pointer->fetch_assoc())
{
if(stripos($haystack, $row["Name"]) )
{
$found[$row["Name"]] = substr_count( $haystack, $row["Name"]);
}
}
arsort($found);
I think I explained myself badly, because I want to do the procedure on new articles they are currently not in the database, so I was just going to use $_POST in an ajax request, rather than saving the article to the DB first.
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html is exactly what you are looking for if you don't want to use a search engine script such as sphinx/solr.
It sounds like your code looks something like this:
foreach($keywords as $keyword){
if(strpos($keyword, $articleText) != -1){
$foundKeywords[] = $keyword;
}
}
Something you may consider since the keywords array is so large and will continue to grow is to switch your processing to loop through the words in the text instead of the keywords array. Something like this:
$textWords = explode(" ", $articleText);
foreach($textWords as $word){
if( array_search($word, $keywords) && !array_search($word, $foundKeywords) ){
$foundKeywords[] = $word;
}
}
Is it possible to highlight the modifications in one text paragraph from the other?
For example, there are 3 text fields in a database. Non-admin users can edit the text and submit for approval. When the admin logs in, (s)he can open the approvals page and it shows the original text and user submitted text with modifications. Usually these modifications are very small in nature, like spelling correction or just a deletion or addition of a sentence.
Can it be presented in such a way that the modifications (from the original text) are highlighted so that admin users don't have to check every field and every line before they approve it?
Any help would be appreciated.
Thanks.
Updated:
Somewhat similar to TortoiseSVN's code changes highlighting.
Options:
PHP Inline Diff (uses PEAR text-diff)
PEAR Text_Diff
Diff in Pure PHP
xdiff_string_diff()
Stackoverflow Archive:
Highlight the difference between two strings in PHP
Apply Diff in PHP
Need Help Optimizing php string difference function
If you are familiar with GNU/Linux tools, you might be familiar with the `diff' tool.
And someone has written a fully functional diff for comparing files/strings in php.
You can find it here: php diff example.
This is an old thread but thought I'd catalog my findings.
If you want to use raw php, this is by far the simplest, fastest, and most effective solution I've found: http://paulbutler.org/archives/a-simple-diff-algorithm-in-php/
From what I can tell, the author of the above code is using an algorithm outlined in this article: http://www.codeproject.com/Articles/6943/A-Generic-Reusable-Diff-Algorithm-in-C-II
Basic description of what's happening (taken from the article):
Find the current Longest Matching Sequence (LMS) of items.
Store this LMS in a results pile.
Process all data left above the LMS using recursion.
Process all data left below the LMS using recursion.
Works like a charm!
Not sure, why these long solutions are there.
here I had found an easy one for me.
string1 = "The quick brown fox jumps over the lazy dog.";
$string2 = "The quick brown albino fox jumps the groovy dog.";
$string1 = explode(" ", $string1);
$string2 = explode(" ", $string2);
$diff = array_intersect($string2, $string1);
$tmp = array();
foreach ($string2 as $k => $w) {
if ($diff[$k]==$w) {
$tmp[$k] = $w;
}
else {
$tmp[$k] = "<b>$w</b>";
}
}
$diff = array_diff($string1, $tmp);
foreach ($diff as $k => $w) {
$tmp[$k] .= " [<strike>$w</strike>]";
}
echo join (' ', $tmp);
ref. https://forums.phpfreaks.com/topic/6525-how-do-i-highlight-differences-between-strings/