PHP Extract Single String from List of Values - php

I need some assistance with php. I have been trying several things for the past several days including str_replace to no avail.
I have a field that may contain from 1 to 20 values, all listed on their own line, there is no html code in that field to separate them and some of the values may have their own spaces in between, so separating by space doesnt work.
What I need is to extract every single string of each line and convert it to code.
<p>For example, my field with values looks like this: </p>
<p><b>lang_fld </b><br>
------
<br>
English<br>
Spanish<br>
German<br>
French</p>
What I have in mind is to extract each line, ex. "English" from that string, and create a line of code like
<img src="images/flags/english.png> English
Basically I want to add the flag graphic to the word
I already tried
echo str_replace('English','<img src="images/flags/english.png>,lang_fld)<br>
...and so on
what I get after going through every single possible value is a bunch error
messages (different every time since I keep making changes - by guessing)
Can someone offer an easier option to do this? Not all 20 values will be in
that areatext field, some may contain just one language, some ten, some all 20,
etc.
Thank you!

Assuming you have all the values on a separate line, you can do explode() on the string to convert it to array of separate items, then loop through the array with foreach and perform any modifications with the single item. After you are done with the items and you would like to get them back together, you can use implode() to combine them into a single string.
A short sample ( you can of course use a for loop, I just prefer foreach here as it shows you better what is happening with the data ):
$text =
"French language
Italian language
English language";
$items = explode( "\n", $text ); // Split by newline ( you can also use "<br>" as separator )
$result = array(); // Modified data will be placed here
foreach ( $items as $item )
{
// Do something with $item
$item = "<img src=\"images/flags/$item.png\"> $item";
$result[] = $item;
}
// Merge them back together
$text = implode("\n", $result);

Related

WordPress PHP htmlspecialchars(get_field... cannot read arrays?

I am working on a WordPress Website/Blog with two main functions.
Create reports.
Compile final report.
People can write reports, selecting the fields they need and publish it. Then at the end of the day, they can "compile" a final report from all of the reports (it concatenate the fields of all reports).
The theme is twentyten (in case it might be useful).
In my function.php file, I concatenate everthing for the final report using a foreach and lines like that:
$Urgences_Environnementales .= htmlspecialchars("<br/>".get_field('Urgences_Environnementales', $idnumber->ID));
$avezvous_regardé_des_indices_de_temps_violent_aujourdhui .= htmlspecialchars(get_field('avezvous_regardé_des_indices_de_temps_violent_aujourdhui', $idnumber->ID));
$quelle_est_cette_raison .= htmlspecialchars(get_field('quelle_est_cette_raison', $idnumber->ID));
One line per field, all the same way. After the loop is done, I update the fields:
update_field('Urgences_Environnementales',preg_replace('/(<br[\s]?[\/]?>[\s]*){2,}/', '<br/><br/>', htmlspecialchars_decode($Urgences_Environnementales)), $identificationRapport);
update_field('avezvous_regardé_des_indices_de_temps_violent_aujourdhui',preg_replace('/(<br[\s]?[\/]?>[\s]*){2,}/', '<br/><br/>', htmlspecialchars_decode($avezvous_regardé_des_indices_de_temps_violent_aujourdhui)), $identificationRapport);
update_field('quelle_est_cette_raison',preg_replace('/(<br[\s]?[\/]?>[\s]*){2,}/', '<br/><br/>', htmlspecialchars_decode($quelle_est_cette_raison)), $identificationRapport);
Then it's printed for the final report like this (this is a single field):
if(strip_tags(html_entity_decode(get_field('Urgences_Environnementales')))!=''){
simplebox(strip_tags(html_entity_decode(get_field('Urgences_Environnementales')))!='', get_field('Urgences_Environnementales'));
}
And for those fields it works perfectly.
My problem is that all my fields composed of arrays (checkboxes that people can select multiple choices using the ACF plugin) are empty in my databse... They appear perfectly in the single reports, but they appear blank in the final report.
As an exemple, this is what I see in my database for a single report for one of my arrays:
a:4:{i:0;s:49:"L’indice d’intensité d’orage violent (STI)";i:1;s:35:"L’indice d’orage violent (TMPV)";i:2;s:34:"Potential Severe Storm Environment";i:3;s:6:"Autres";}
The corresponding field in my final report is empty.
Would someone have an idea on how to read those arrays and record them correctly in my databse? Could I transform them in strings in my foreach loop? Should I do something differently?
If you need more code don't hesitate to ask. I didn't put all my 3 functions (functions.php, report.php, finalreport.php) that I have in my WordPress theme as it would take tons of lines and I'm pretty sure the most important ones are right here. If I'm wrong, I could post the functions.
I searched and searched, but I can't seem to find the answer by myself, so I'm searching for help here.
PS: This is my 1st post, if you have any reccomandations, you can send them to me and I will change my post.
Thank you very much for your help!
PPS: I'm sorry for my english, I'm french, from Montreal, Qc, Canada.
Advanced Custom Fields stores some values as serialized arrays (checkboxes, repeaters, etc). Your code is assuming that you will be getting a string back. As you suggested in your answer, the easiest way to account for this in your current code would be to use the is_array() method to check the type of the returned value, and then another inner loop to handle the summary. This code assumes you just want to concatenate all the values, you could just as easily use another array to make sure they are unique, etc.
// get the value from acf
$value = get_field( 'Urgences_Environnementales', $idnumber->ID );
// if it's already an array, use that, if not make it into an array with a single element
$value_arr = ( is_array( $value ) )? $value : array( $value );
$text = ""; // reset since this is in a loop
// concatenate each checkbox value
foreach ( $value_arr as $val ){
$text .= $val . ', ';
}
// append it to the main summary
$Urgences_Environnementales .= htmlspecialchars( "<br/>". $text );

PHP preg_replace inside for loop

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);

PHP Replace tags / placeholders / markers in text string with dynamic values

Basically, what I want to achieve is dynamically replace {SOME_TAG} with "Text".
My idea was to read all tags like {SOME_TAG}, put them into array.
Then convert array keys into variables like $some_tag, and put them into array.
So, this is how far I got:
//Some code goes here
$some_tag = "Is defined somewhere else.";
$different_tag = 1 + $something;
Some text {SOME_TAG} appears in different file, which contents has been read earlier.
//Some code goes here
preg_match_all('/{\w+}/', $strings, $search);
$search = str_replace(str_split('{}'),"",$search[0]);
$search = array_change_key_case( array_flip($search), CASE_LOWER);
...some code missing here, which I cant figure out.
Replace array should look something like this
$replace = array($some_tag, $different_tag);
//Then comes replacing code and output blah blah blah..
How to make array $replace contain variables dynamically depending on $search array?
Why not something along the lines of:
<?php
$replace = array(
'{TAG_1}' => 'hello',
'{TAG_2}' => 'world',
'{TAG_3}' => '!'
);
$myString = '{TAG_1} {TAG_2}{TAG_3}{TAG_3}';
echo str_replace(array_keys($replace), array_values($replace), $myString);
If I understand correctly:
You're working on trying to create a customizable document, using {TAGS} in order to represent replaceable areas that can be filled in with dynamic information. At some point in time while replacing the {TAGS} with the dynamic information, you want the dynamic information to be stored in automatically generated basic variable names, as $tags.
I'm not sure why you want to convert these tags to basic variables instead using them entirely as array keys. I would like to point out that this represents a security or functionality hole - what happens if someone puts {REPLACE} in as a tag in your document? Your replace array would get overwritten with dynamic data, and your whole program would fall apart. Either that, or the whole replace array would get dumped in for {REPLACE}, making for a very messy document with perhaps data you don't WANT them to have in it. Perhaps you have this dealt with - I don't have all the context here - but I thought I'd point out the risk factor.
As for a better solution, unless there's some specific need that you're addressing by going through $tags instead of using using the $replace array directly, I like #Emissary's answer.

php search and replace

I am trying to create a database field merge into a document (rtf) using php
i.e if I have a document that starts
Dear Sir,
Customer Name: [customer_name], Date of order: [order_date]
After retrieving the appropriate database record I can use a simple search and replace to insert the database field into the right place.
So far so good.
I would however like to have a little more control over the data before it is replaced. For example I may wish to Title Case it, or convert a delimited string into a list with carriage returns.
I would therefore like to be able to add extra formatting commands to the field to be replaced. e.g.
Dear Sir,
Customer Name: [customer_name, TC], Date of order: [order_date, Y/M/D]
There may be more than one formatting command per field.
Is there a way that I can now search for these strings? The format of the strings is not set in stone, so if I have to change the format then I can.
Any suggestions appreciated.
You could use a templating system like Smarty, that might make your life easier, as you can do {$customer_name|ucwords} or actually put PHP code in your email template.
Try a RegEx and preg_replace_callback:
function replace_param($matches)
{
$parts = explode(',',$matches[0]);
//$parts now contains an array like: customer_name,TC,SE,YMD
// do some substitutions and:
return $text;
}
preg_replace_callback('/\[([^\]]+)\]/','replace_param',$rtf);
You can use explode on it to separate them into array values.
For Example:
$customer_name = 'customer_name, TC';
$get_fields = explode(',', $customer_name);
foreach($get_fields as $value)
{
$new_val = trim($value);
// Now do whatever you want to these in here.
}
Sorry if I'm not understanding you.

PHP: Formatting irregular CSV files into HTML tables

My client receives a set of CSV text files periodically, where the elements in each row follow a consistent order and format, but the commas that separate them are inconsistent. Sometimes one comma will separate two elements and other times it will be two or four commas, etc ...
The PHP application I am writing attempts to do the following things:
PSEUDO-CODE:
1. Upload csv.txt file from client's local directory.
2. Create new HTML table.
3. Insert the first three fields FROM csv.txt into HTML table row.
4. Iterate STEP 2 while the FIRST field equals the First field below it.
5. If they do not equal, CLOSE HTML table.
6. Check to see if FIRST field is NOT NULL, IF TRUE, GOTO step 2, Else close HTML table.
I have no trouble with steps 1 and 2. Step 3 is where it gets tricky since the fields in the csv.txt files are not always separated by the same number of commas. They are, however, always in the same relative order and format. I am also having issues with step 4. I don't know how to check if the beginning field in a row matches the beginning field in the row below it. Steps 5 should be relatively simple. For step 6, I need to find an eqivalent of a "GOTO" function in PHP.
Please let me know if any part of the question is unclear. I appreciate your help.
Thank you in advance!
If you want to group the rows by their first element you can try something like:
read the next row via fgetcsv()
filter empty elements (a,,b,c -> a,b,c)
if the row contains fields <-> is not empty append the row to "its" group
That's not exactly what you've described but it may be what you want ;-)
<?php
$fp = fopen('test.csv', 'rb') or die('!fopen');
$groups = array();
while(!feof($fp)) {
$row = array_filter(fgetcsv($fp));
if ( !empty($row) ) {
// # because I don't care whether the array exists or not
#$groups[$row[0]][] = $row;
}
}
foreach( $groups as $g ) {
echo '
<table>';
foreach( $g as $row ) {
echo '
<tr>
<td>', join('</td><td>', array_map('htmlentities', $row)), '</td>
</tr>
';
}
echo '</table>';
}
why not simply start by going through any replacing any multiples of commas with a single comma. eg:
abc,def,,ghi,,,,jkl
becomes:
abc,def,ghi,jkl
and then just continue normally.
If you mean that there are different numbers of commas on each line, then as far as I can see it is actually impossible to do what you want to do by looking at the commas alone. For example:
ab,c,d,ef // could group columns a-f in that way, but
a,bc,de,f // could also group columns a-f
... and you would have no way of knowing which was the proper arrangement, unless you're given some other instructions or the type of data is identifiable by regular expression as someone else said.
If on the other hand you just mean that sometimes there are blanks, but there are still the same number of columns, like this:
a,b,,d,e,f
a,,c,d,e,f
... then you can still form the table correctly. I would recommend using explode(',' $line) in that case and then doing your processing on the elements of the exploded array without worrying about what is inside them.

Categories