I have a php value coming back from my database as a string, like
"this, that, another, another"
And I'm trying to wrap a separate link around each of those strings, but I can't seem to get it to work. I've tried a for loop, but since it's just a string of information and not an array of information that doesn't really work. Is there a way to wrap a unique link around each value in my string?
The easiest way that I see to do this would be using PHP's explode() function. You'll find that it will become very useful as you start to use PHP more and more, so do check out its documentation page. It allows you to split a string up into an array given a certain separator. In your case, this would be ,. So to split the string:
$string = 'this, that, another, another 2';
$parts = explode(', ', $string);
Then use a foreach (again, check the documentation) to iterate through each of the parts and make them into a link:
foreach($parts as $part) {
echo '' . $part . "\n";
}
However, you can do this with a for loop. Strings can be accessed like arrays, so you can implement a parser pattern to parse the string, extract the parts, and create the links.
// Initialize some vars that we'll need
$str = "this, that, another, another";
$output = ""; // final output
$buffer = ""; // buffer to hold current part
// Iterate over each character
for($i = 0; $i < strlen($str); $i++) {
// If the character is our separator
if($str[$i] === ',') {
// We've reached the end of this part, so add it to our output
$output .= '' . trim($buffer) . "\n";
// clear it so we can start storing the next part
$buffer = "";
// and skip to the next character
continue;
}
// Otherwise, add the character to the buffer for the current part
$buffer .= $str[$i];
}
echo $output;
(Codepad Demo)
A better way is to do it like this
$string = "this, that, another, another";
$ex_string = explode(",",$string);
foreach($ex_string AS $item)
{
echo "<a href='#'>".$item."</a><br />";
}
First explode the string to get the individual words in an array. Then add the hyperlinks to the words and finally implode them.
$string = "this, that, another, another";
$words = explode(",", $string);
$words[0] = $words[0]
$words[1] = $words[1]
..
$string = implode(",", $words);
You can also use the for loop to assign hyperlinks that follow a pattern like this:
for ($i=0; $i<count($words); $i++) {
//assign URL for each word as its name or index
}
Related
My problem is it just replicates the number twice, though it does add the break when there is a number, but I'm trying to check if there is a number after the number, so it would say line 12 is.....
Thanks for any help
<?PHP
$lines = file_get_contents('http://www.webstitcher.com/test.txt');
$tag = str_split($lines); // puts all lines into a array
foreach ($tag as $num => $letta){
if (is_numeric($letta) == TRUE){
$num2 = $num++;
if (is_numeric($tag[$num2])){ // checks if next line is going to be another digit
$letta .= $tag[$num2];
unset($tag[$num2]); // removes line if it had another digit and adds to ouput
}
echo '<br />' . $letta;
}
else {
echo $letta;
}
}
?>
Try exploding the string using ' ' as the delimiter. This will allow you to keep the numbers whole and will ultimately help cut out a lot of the complexity.
$lines = file_get_contents('http://www.webstitcher.com/test.txt');
$tag = explode(' ', $lines); // puts all words into a array
foreach ($tag as $word){
if (is_numeric($word)) {
// if the word is numeric, simply skip to next line
// if you need to keep the number, add $word to the echo statement
echo '<br />';
}
else {
echo ' '.$word;
}
}
This way you don't have to keep track of the previous element in the array or check for the next element.
Alternatively, you could also use preg_replace which would remove the need for the loop entirely.
$lines = preg_replace('/[0-9]+/', '<br>', $words);
I have an array with rule field that has a string like this:
FREQ=MONTHLY;BYDAY=3FR
FREQ=MONTHLY;BYDAY=3SA
FREQ=WEEKLY;UNTIL=20170728T080000Z;BYDAY=MO,TU,WE,TH,FR
FREQ=MONTHLY;UNTIL=20170527T100000Z;BYDAY=4SA
FREQ=WEEKLY;BYDAY=SA
FREQ=WEEKLY;INTERVAL=2;BYDAY=TH
FREQ=WEEKLY;BYDAY=TH
FREQ=WEEKLY;UNTIL=20170610T085959Z;BYDAY=SA
FREQ=MONTHLY;BYDAY=2TH
Each line is a different array, I am giving a few clues to get an idea of what I need.
What I need is to write a regex that would take off all unnecessary values.
So, I don't need FREQ= ; BYDAY= etc. I basically need the values after = but each one I want to store in a different variable.
Taking third one as an example it would be:
$frequency = WEEKLY
$until = 20170728T080000Z
$day = MO, TU, WE, TH, FR
It doesn't have to be necessarily one regex, there can be one regex for each value. So I have one for FREQ:
preg_match("/[^FREQ=][A-Z]+/", $input_line, $output_array);
But I can't do it for the rest unfortunately, how can I solve this?
The only way to go would be PHP array destructuring:
$str = "FREQ=WEEKLY;UNTIL=20170728T080000Z;BYDAY=MO,TU,WE,TH,FR";
preg_match_all('~(\w+)=([^;]+)~', $str, $matches);
[$freq, $until, $byday] = $matches[2]; // As of PHP 7.1 (otherwise use list() function)
echo $freq, " ", $until, " ", $byday;
// WEEKLY 20170728T080000Z MO,TU,WE,TH,FR
Live demo
Be more general
Using extract function:
preg_match_all('~(\w+)=([^;]+)~', $str, $m);
$m[1] = array_map('strtolower', $m[1]);
$vars = array_combine($m[1], $m[2]);
extract($vars);
echo $freq, " ", $until, " ", $byday;
Live demo
Notice: For this problem, I recommend the generell approach #revo posted, it's concise and safe and easy on the eyes -- but keep in mind, that regular expressions come with a performance penalty compared to fixed string functions, so if you can use strpos/substr/explode/..., try to use them, don't 'knee-jerk' to a preg_-based solution.
Since the seperators are fixed and don't seem to occur in the values your are interested in, and you furthermore rely on knowledge of the keys (FREQ:, etc) you don't need regular-expressions (as much as I like to use them anywhere I can, and you can use them here); why not simply explode and split in this case?
$lines = explode("\n", $text);
foreach($lines as $line) {
$parts = explode(';', $line);
$frequency = $until = $day = $interval = null;
foreach($parts as $part) {
list($key, $value) = explode('=', $part);
switch($key) {
case 'FREQ':
$frequency = $value;
break;
case 'INTERVAL':
$interval = $value;
break;
// and so on
}
}
doSomethingWithTheValues();
}
This may be more readable and efficient if your use-case is as simple as stated.
You need to use the Pattern
;?[A-Z]+=
together with preg_split();
preg_split('/;?[A-Z]+=/', $str);
Explanation
; match Semikolon
? no or one of the last Character
[A-Z]+ match one or more uppercase Letters
= match one =
If you want to have each Line into a seperate Array, you should do it this Way:
# split each Line into an Array-Element
$lines = preg_split('/[\n\r]+/', $str);
# initiate Array for Results
$results = array();
# start Looping trough Lines
foreach($lines as $line){
# split each Line by the Regex mentioned above and
# put the resulting Array into the Results-Array
$results[] = preg_split('/;?[A-Z]+=/', $line);
}
I want to display just two lines of the paragraph.
How do I do this ?
<p><?php if($display){ echo $crow->content;} ?></p>
Depending on the textual content you are referring to, you might be able to get away with this :
// `nl2br` is a function that converts new lines into the '<br/>' element.
$newContent = nl2br($crow->content);
// `explode` will then split the content at each appearance of '<br/>'.
$splitContent = explode("<br/>",$newContent);
// Here we simply extract the first and second items in our array.
$firstLine = $splitContent[0];
$secondLine = $splitContent[1];
NOTE - This will destroy all the line breaks you have in your text! You'll have to insert them again if you still want to preserve the text in its original formatting.
If you mean sentences you are able to do this by exploding the paragraph and selecting the first two parts of the array:
$array = explode('.', $paragraph);
$2lines = $array[0].$array[1];
Otherwise you will have to count the number of characters across two lines and use a substr() function. For example if the length of two lines is 100 characters you would do:
$2lines = substr($paragraph, 0, 200);
However due to the fact that not all font characters are the same width it may be difficult to do this accurately. I would suggest taking the widest character, such as a 'W' and echo as many of these in one line. Then count the maximum number of the largest character that can be displayed across two lines. From this you will have the optimum number. Although this will not give you a compact two lines, it will ensure that it can not go over two lines.
This is could, however, cause a word to be cut in two. To solve this we are able to use the explode function to find the last word in the extracted characters.
$array = explode(' ', $2lines);
We can then find the last word and remove the correct number of characters from the final output.
$numwords = count($array);
$lastword = $array[$numwords];
$numchars = strlen($lastword);
$2lines = substr($2lines, 0, (0-$numchars));
function getLines($text, $lines)
{
$text = explode("\n", $text, $lines + 1); //The last entrie will be all lines you dont want.
array_pop($text); //Remove the lines you didn't want.
return implode("<br>", $text); //Implode with "<br>" to a string. (This is for a HTML page, right?)
}
echo getLines($crow->content, 2); //The first two lines of $crow->content
Try this:
$lines = preg_split("/[\r\n]+/", $crow->content, 3);
echo $lines[0] . '<br />' . $lines[1];
and for variable number of lines, use:
$num_of_lines = 2;
$lines = preg_split("/[\r\n]+/", $crow->content, $num_of_lines+1);
array_pop($lines);
echo implode('<br />', $lines);
Cheers!
This is a more general answer - you can get any amount of lines using this:
function getLines($paragraph, $lines){
$lineArr = explode("\n",$paragraph);
$newParagraph = null;
if(count($lineArr) > 0){
for($i = 0; $i < $lines; $i++){
if(isset($lines[$i]))
$newParagraph .= $lines[$i];
else
break;
}
}
return $newParagraph;
}
you could use echo getLines($crow->content,2); to do what you want.
Confounded. I've been using the below IF PREG_MATCH to distinguish between words which entire words and words which are parts of other words. It has suddenly ceased to function in this script, and any other script I use, which depend on this command.
The result is it finds parts of words, although you can see it is explicitly told to find only entire words.
$word = preg_replace("/[^a-zA-Z 0-9]+/", " ", $word);
if (preg_match('#\b'.$word.'\b#',$goodfile) && (trim($word) != "")) {
$fate = strpos($goodfile,$word);
print $word ." ";
print $fate ."</br>";
If you only want to read the first word of a line of a text file, like your title suggests, try another method:
// Get the file as an array, each element being a line
$lines = file("/path/to/file");
// Break up the first line by spaces
$words = explode(" ", $lines[0]);
// Get the first word
$firstWord = $words[0];
This would be faster and cleaner than explode and you won't be making any array
$first_word = stristr($lines, ' ', true);
I am trying to write a small php
application and i am facing a problem.
This is suppose to get text like :
this is *noun but it is *name.
And
should take the words that start with
a star and add them to the string
tokens. However this is not working.
// get list of fields (each should have words delimited by underscores
$storyArray = split(' ', $story);
$tokens = ""; // space-delimited list of fields
for ($i = 0; $i < count($storyArray); $i++) {
if ($storyArray[$i][0] == '*')
$tokens .= $storyArray[$i] + " ";
}
$tokensArray = split(' ', $tokens);
Wow, I can't believe I've been debugging this and missing the obvious fault!
This line here:
$tokens .= $storyArray[$i] + " ";
You must concatenate with a period (.), not a plus sign! What you have right now is basically the same as $tokens .= 0;
This worked for me:
$story = "this is *noun but it is *name";
$storyArray = split(' ', $story);
$tokens = array();
for ($i = 0; $i < count($storyArray); $i++) {
if ($storyArray[$i][0] == '*') {
array_push($tokens, substr($storyArray[$i], 1));
}
}
var_dump($tokens);
$tokenString = implode(" ", $tokens);
Note that I'm pushing the tokens directly into an array, then imploding it.
"+" is for addition, not string concatenation. It casts its arguments as numbers, which will always be 0 in your source.
On another note, splitting $tokens is unnecessary. Instead, append tokens to $tokensArray:
$story = "this is *noun but it is *name";
// get list of fields (each should have words delimited by underscores
$storyArray = split(' ', $story);
$tokens = ""; // space-delimited list of fields
$tokensArray=array();
for ($i = 0; $i < count($storyArray); $i++) {
if ($storyArray[$i][0] == '*') {
$tokens .= $storyArray[$i] . " ";
$tokensArray[] = $storyArray[$i];
}
}
If you only needed $tokens for generating $tokensArray, you can get rid of it. Also, depending on whether you need $storyArray, preg_match_all(...) might be able to replace your code:
preg_match_all('/\*\w+/', $story, $tokensArray);
$tokensArray = $tokensArray[0];
You can also use a regular expression to achieve the same effect, without all the string manipulation you are doing right now. This would be the most elegant solution:
$string = "this is *noun but it is *name";
// Lets set up an empty array
$tokens = array();
preg_match_all('/\*\w+/m', $string, $tokens);
$tokens = $tokens[0]; // Only one sub-pattern, dropping unnecessary dimension.
var_dump($tokens);
Regular expressions exists to do mainly exactly the kind of task you are trying to achieve now. They are usually faster than doing string manipulations manually (Regular Expression engine in PHP is compiled code).
To explain my regex:
/: start boundary
\*: an asterisk (*)
\w: any alpha-numeric character or underscore
+: previous marker, 1 or more times. (match \w one or more times)
/: end boundary
m: multiline modifier
Replace
$tokens .= $storyArray[$i] + " ";
with
$tokens .= $storyArray[$i]." ";
And
$tokensArray = split(' ', $tokens);
with
$tokensArray = split(' ', rtrim($tokens));
$tokens .= $storyArray[$i] + " ";
in this line, you should be using the . operator to concatenate strings.