php array, only last item in array is correct - php

Below is the code that should make the problem clear. Code that is irrelevant to the problem has been left out, e.g. fetching the contents of a url, printing the contents to a new file.
Can anyone explain why variables are jumbled except for the last item?
<?php
$f = fopen("cucina2.txt", "r");
// Read line by line until end of file
while (!feof($f)) {
// Make an array using newline as delimiter
$arrM = explode("\n",fgets($f));
//Add the word to the url address
$url = 'hhttp://www.some.com/vocab/' . $arrM[0] . '/';
//Create a text file with the word
$glossary = $arrM[0];
$glossary .= '.txt';
//Check the functions
echo "arrM is: ";
echo $arrM[0];
echo "\n";
echo "glossary is: ";
echo $glossary;
echo "\n";
echo "url is: ";
echo $url;
echo "\n";
}
?>
cucina.txt:
batticarne
battuto
bavarese
bavetta
results:
arrM is: batticarne
.txtsary is: batticarne
/rl is: hhttp://www.some.com/vocab/batticarne
arrM is: battuto
.txtsary is: battuto
/rl is: hhttp://www.some.com/vocab/battuto
arrM is: bavarese
.txtsary is: bavarese
/rl is: hhttp://www.some.com/vocab/bavarese
arrM is: bavetta
glossary is: bavetta.txt
url is: hhttp://www.some.com/vocab/bavetta/

It appears that your data file (cucina.txt) contains Windows-style line breaks ("\r\n"). When you split the input lines at \n, you are left with a trailing carriage return \r at the end of each slice.
Try this instead:
$arrM = preg_split('/[\r\n]+/',fgets($f));
Also, be aware that while (!feof($f)) is generally wrong. You should check for an EOF when you are actually reading from the file, not at the top of your loop. That way you will avoid processing empty lines.
while (!feof($f)) {
$s = fgets($f);
if (!$s) break;
$arrM = preg_split('/[\r\n]+/',$s);
:
:
}

I just ran your file. Made my own word list however.
I put just a list of stuff around me in into a text file:
style
charity
new
samsung
asus
sharpie
tape
It prints fine. Returns
arrM is: style
glossary is: style.txt
url is: hhttp://www.some.com/vocab/style/
arrM is: charity
glossary is: charity.txt
url is: hhttp://www.some.com/vocab/charity/
arrM is: new
glossary is: new.txt
url is: hhttp://www.some.com/vocab/new/
arrM is: samsung
glossary is: samsung.txt
url is: hhttp://www.some.com/vocab/samsung/
arrM is: asus
glossary is: asus.txt
url is: hhttp://www.some.com/vocab/asus/
arrM is: sharpie
glossary is: sharpie.txt
url is: hhttp://www.some.com/vocab/sharpie/
arrM is: tape
glossary is: tape.txt
url is: hhttp://www.some.com/vocab/tape/
Your issue could be coming from using explode. If the file your reading from is already words or series of words denoted from one another by line returns you don't need to explode the string. Just read the file line by line until you reach the end.
<?php
//create variable to iterate though the array until it is out of values.
$itter = 0;
$f = fopen("WordsList.txt", "r");
// Read line by line until end of file
while (!feof($f)) {
//read the text file line by line.
$line=fgets($f);
//Removed any whitespace left at the end of the line or whitespace generated from returning.
//Trim can be used to trim any character from a string though.
$line=trim($line);
//Add the line to the array.
$arrM[]=$line;
//Add the word to the url address
$url = 'http://www.some.com/vocab/' . $arrM[$itter] . '/';
//Create a text file with the word
$glossary = $arrM[$itter];
$glossary .= '.txt';
//Check the functions
echo "arrM is: ";
echo $arrM[$itter];
echo "<br />";
echo "glossary is: ";
echo $glossary;
echo "<br />";
echo "url is: ";
echo $url;
echo "<br />";
$itter++;
}
//After you read from a file always a food idea to close it/dump it from memory.
fclose($f);
?>
Try that block of code. It uses trim to fgets to read line by line. Then trims any white space from the end of the line. Every time a line is pulled out by fgets it trims and sets that line equal to the variable $line. Then as each line is read and stripped it takes that line and adds it to your array.
The variable $itter then echos back the array starting at zero until it reaches the end of the number of lines found in the file/array generated from the file.

Related

PHP Form implode / explode

I am using the a db field merchant_sku_item in a form. the original value is separated by / in the db like this:
2*CC689/1*CC368-8/1*SW6228-AB
I want to display in a text area on each line so I tried like this:
<textarea name="merchant_sku_item" rows="5" class="form-control" id="merchant_sku_item"><?
$items=explode('/',$merchant_sku_item);
foreach($items as $item){
echo $item."\r\n";
}
?></textarea>
All works fine:
2*CC689
1*CC368-8
1*SW6228-AB
but when I post the form I get a value like this:
2*CC689 1*CC368-8 1*SW6228-AB
but I wan't it back in the original format to update the DB in the correct format:
2*CC689/1*CC368-8/1*SW6228-AB
I tried to implode it with the / but I think it's just one string now so it's not working. I could replace the spaces I guess but this will not work if the field contains spaces.
Could somebody please tell me the best way to handle this?
The explode is correct, but you cannot just echo $item . "\r\n" because if $item contains </textarea> or whatever HTML you'll skrew up the page. You have to use echo htmlspecialchars($item) . "\n";. Normally, HTML pages have Linux line endings with "\n" and not Windows line endings with "\r\n".
To re-create the value for the DB, you have to take in consideration that the user may add some spaces or new lines. So you might not just get "\r\n" between the values but also " \n" or I don't know what. This is why a regular expression will be more flexible than a simple explode().
The regular expression pattern: \s+
The pattern \s will match any space, tab or new line chars. If you add the + sign after, it means that it can be 1 or multiple times. So this means that " \r\n" will match as it contains spaces, a carriege return and a new line. In PHP, you put the pattern between a delimiter char that you choose and that you put at the begin and the end. Commonly it's a slash so it becomes /\s+/. But you sometimes see also #\s+# or ~\s+~. After this delimiter, you can put some flags to change the way the regular expression is executed. Typically /hello/i will match "Hello" or "hello" because the i flag makes the search case-insensitive.
Similar to what you did: explode and re-implode example:
<?php
// Example of values that could be posted because users are always
// stupid and add spaces that they then don't see anymore.
$examples = [
"2*CC689 1*CC368-8 1*SW6228-AB", // spaces
"2*CC689\n1*CC368-8\n1*SW6228-AB", // new lines
"2*CC689\r\n1*CC368-8\r\n1*SW6228-AB", // carriege returns and new lines
"2*CC689\n 1*CC368-8 \n1*SW6228-AB", // new lines and spaces
];
foreach ($examples as $merchant_sku_item) {
$values = preg_split('/\s+/', $merchant_sku_item);
$merchant_sku_item_for_db = implode('/', $values);
echo $merchant_sku_item_for_db . "\n";
}
?>
Output:
2*CC689/1*CC368-8/1*SW6228-AB
2*CC689/1*CC368-8/1*SW6228-AB
2*CC689/1*CC368-8/1*SW6228-AB
2*CC689/1*CC368-8/1*SW6228-AB
Simplier, you could also just do a replacement with the same regular expression like this:
<?php
// Example of values that could be posted.
$examples = [
"2*CC689 1*CC368-8 1*SW6228-AB", // spaces
"2*CC689\n1*CC368-8\n1*SW6228-AB", // new lines
"2*CC689\r\n1*CC368-8\r\n1*SW6228-AB", // carriege returns and new lines
"2*CC689\n 1*CC368-8 \n1*SW6228-AB", // new lines and spaces
];
foreach ($examples as $merchant_sku_item) {
$merchant_sku_item_for_db = preg_replace('/\s+/', '/', $merchant_sku_item);
echo $merchant_sku_item_for_db . "\n";
}
?>
And just another important point regarding the data the user could input: What happens if the user types "2*CC/689" in the textarea?
Well, this will break your DB value :-/
This means that you have to validate the user input with some checks:
<?php
header('Content-Type: text/plain');
$examples = [
"2*CC689 1*CC368-8 1*SW6228-AB", // spaces
"2*CC689\n1*CC368-8\n1*SW6228-AB", // new lines
"2*CC689\r\n1*CC368-8\r\n1*SW6228-AB", // carriege returns and new lines
"2*CC689\n 1*CC368-8 \n1*SW6228-AB", // new lines and spaces
// Test with invalid datas:
"2*C/C689\n1*CC368-8\n1*SW6228-AB", // slash not allowed
"*CC689\n1*CC368-8\n1*SW6228-AB", // missing number before the *
"1*\n1*CC368-8\n1*SW62?28-AB", // missing product identifier and invalid ?
"1CC689 1*CC368-8 1SW6228-AB", // missing *
];
foreach ($examples as $example_nbr => $merchant_sku_item) {
echo str_repeat('=', 80) . "\n";
echo "Example $example_nbr\n\$merchant_sku_item = \"$merchant_sku_item\"\n";
$values = preg_split('/\s+/', $merchant_sku_item);
$errors = [];
foreach ($values as $i => $value) {
echo "Value $i = \"$value\"";
// Pattern: a number followed by * and followed by a product id (length between 3 and 10).
if (!preg_match('/^\d+\*[\d\w-]{3,10}$/i', $value)) {
echo " <-- ERROR\n";
$errors[] = $value;
} else {
echo "\n"; // It's ok
}
}
if (!empty($errors)) {
// You should handle the error and reload the form with the posted value and an error
// message explaining to the user what format is allowed.
echo "ERROR: Cannot save the value because the following products are wrong:\n";
echo implode("\n", $errors) . "\n";
}
}
?>
Test it here: https://onecompiler.com/php/3xtff6nk8
You can use preg_replace for your final post string like below code
$str = "2*CC689 blue 1*CC368-8 red 1*SW6228-AB";
$items = preg_replace('/\s+/', '/', $str);
echo $items;
output
2*CC689/blue/1*CC368-8/red/1*SW6228-AB
I Hope understand your question exactly.
Try replacing the created spaces and removing newline characters like so:
<?php
$merchant_sku_item = str_replace("\r\n","/",trim($_POST["merchant_sku_item"]));
?>
Make it this way:
<textarea name="merchant_sku_item" rows="5" class="form-control" id="merchant_sku_item"><?
$items=explode('//',$merchant_sku_item);
foreach($items as $item){
echo $item."\r\n";
}
?></textarea>

Read text file and print in the same format

i want to read a text file on a php page and print (echo) the content in the same form (with the paragraphs). So i tried two implementations
Code 1
$textfile = "teste.txt"; // Declares the name and location of the .txt file
$content="";
$fileLocation = "$textfile";
$fh = fopen($fileLocation, 'w ');
if (is_readable($textfile)) {
$content .= fread($fh, 8192);
echo $content;
} else {
echo 'The file is not readable.';
}
fclose($fh);
?>
Using this code nothing apper on the screen. and i had another problem. If i used filesize ($textfile) on the fread i had this error Length parameter must be greater than 0.So i guess this is the problem. but the text file has content
Code 2
<?php
$homepage = file_get_contents('teste.txt');
echo $homepage;
?>
This code works. but the format is not what i want.
the echo prints this
25 ºC 26 ºC 27 ºC 26 ºC 26 ºC
I want that appear one value on each line like i have on the text file.
What can i do to acomplish that
Thanks for the help
note sure if this is answerd, but try this
<?php
$file = "LOCATION/NAME.txt";
$text = file_get_contents($file);
$text = nl2br($text);
echo $text;
?>
This should be as simple as wrapping the output inside the PRE tag:
<?php
$homepage = file_get_contents('teste.txt');
echo '<PRE>' . $homepage . '</PRE>';
?>
This will work better than nl2br() if you also need to keep the exact number of spaces due to needing a fixed-width font. HTML normally turns two or three spaces in a row into just one. But inside a PRE tag if you have 3 spaces, all 3 will be displayed.

How to write file as it is?

I have a string of code like this:
<?php
echo "Hello World";
?>
Now, I want to write that into a php file just the way it is. What I mean is that I want to write this code with new line characters. So the code gets stored in the above fashion. So, how can I do that?
I had tried to use file append and fwrite, but they write the code in one consecutive line and what I want is to have it divided into 3 lines.
On the first line - <?php
On the second line - echo "Hello world";
On the third line - ?>
But I would like to do it by using only one line of code, that would be something like the below one.
$file = 'people.php';
// The new person to add to the file
$person = "John Smith\n";
// Write the contents to the file,
// using the FILE_APPEND flag to append the content to the end of the file
// and the LOCK_EX flag to prevent anyone else writing to the file at the same time
file_put_contents($file, $person, FILE_APPEND | LOCK_EX);
This should work fine using an heredoc:
file_put_contents('people.php', <<<HEREDOC
<?php
echo "Hello World";
?>
HEREDOC
);
<?php
$File = "new.txt"; //your text file
$handle = fopen($File, 'w');
fwrite($handle, '<?php '."\n".' echo "Hello World "; '."\n".'?>');
?>
Your string should be like this
$str = "<?php
echo \"Hello World\";
?>";
then write it to any fileName.php, php while parsing ignores new lines, only semicolons matters.
Edit 1
Since you want to write your string as code, after following above step you will have all your code in a single line more like a compressed code, which will be not human readable, for making it human friendly, you will have to add formatting, a minimal approach for formatting will be to at least add new line chars and tabs for indentation.
for this you will have to do two things, identify chars (a) where you need to add new line feed and those chars (b) where indentation is required. Now before writing to file do some preprocessing add new line chars for char type (a) and at the same time maintain a stack for adding proper number of tabs for indentation.
Try using the following between each line of code to put it on a new line in the php file:
. PHP_EOL .
You can:
<?php
$yourContent = <<<PHP
<?php
echo "Hello world";
echo "This in an example";
$foo = 2;
$bar = 4;
echo "Foo + Bar = ".($foo+$bar);
?>
PHP;
file_put_contents("yourFile.php", $yourContent);
?>
Try following :
<?php
$file = "helloworld.php";
$content = file_get_contents($file);
print_r(htmlspecialchars($content));
?>
Helloworld.php :
<?php
echo "Hello World";
?>
It'll work fine.
It sounds like you need to add a line break to the end of each line. You can use a regular expression search/replace as follows (where $newData already contains the string you want to append to the file):
<?php
$newData = preg_replace('/$/',"\n", $newData);
file_put_contents($file, $newData, FILE_APPEND | LOCK_EX);
?>
This finds the end of each line (indicated by $ in regex) and adds the new line (\n) at that position.
this code is working on my pc. you will also like it.
<?php
$file = 'people.php';
// The new person to add to the file
$person = "<?php
echo 'Hello World';
?>\n";
// Write the contents to the file,
// using the FILE_APPEND flag to append the content to the end of the file
// and the LOCK_EX flag to prevent anyone else writing to the file at the same time
file_put_contents($file, $person, FILE_APPEND | LOCK_EX);
echo $person;
?>

PHP: uploading text file to page, which shows new line for each text entry, and sorted alphabetically

I'm using PHP and I want to upload a text file, with the output / view showing each line from the text file on a new line (so exactly as it is displayed in the text file).
However, I also want the text file to be sorted alphabetically.
I have working code that uploads the file on each new line, and sorts by upper case, then lowercase - using the sort function
And I have code which sorts it alphabetically (regardless of case), but unfortunately the lines are grouped together, and not separated as I want them to be. - using the natcasesort
I've tried numerous things but not getting anywhere, so hoping someone can help either put the two together, or let me know what I need to do to either piece of code which will make each line show on a new line.
1st CODE NEEDS TO BE SORTED ALPHABETICALLY REGARDLESS OF UPPER/LOWERCASE
2nd CODE NEEDS TO SHOW THE LINE BREAKS
<?php
$file = file("users.txt");
sort($file);
for($i=0; $i<count($file); $i++)
{
$states = explode(",", $file[$i]);
echo $states[0], $states[1],"<br />";
}
?>
<?php
$filename="users.txt";
$lines = array();
$file = fopen($filename, "r");
while(!feof($file)) {
$lines[] = fgets($file,4096);
}
natcasesort($lines);
print_r($lines);
fclose ($file);
?>
You must use
$text = implode("<br />", $lines);
echo $text
It would glue the array and pasting a <br /> in every new line. Of course, if it is being printed in HTML, if not use the carrier \n instead.
And your code would look like:
.
.
.
while(!feof($file)) {
$lines[] = fgets($file,4096);
}
natcasesort($lines);
$text = implode("<br />", $lines);
print_r($text)
.
.
.

Why is it starting a new line before it should in PHP array?

I'm having a problem with arrays and file writing, what I want to do is take one file, and copy it onto another file, except with formatting added to it.
To be specific, this:
Line 1
Line 2
Line 3
Would become this:
<br /><hr />Line 1
<br /><hr />Line 2
<br /><hr />Line 3
And I've sorta done that, but something weird happens. Instead of formatting all on one line, it linebreaks and keeps going. Like this
<br />1
THE END<br />7
THE END<br />0
THE END<br />Red
THE END<br />Silent
THE END<br />No ChangesTHE END
My code for this is:
<?php
$filename1 = "directorx_OLDONE.txt";
$filename2 = "directorx_NEWONE.txt";
$file1 = fopen($filename1, "r") or exit ("No");
$file2 = fopen($filename2, "w") or exit ("No");
while (!feof($file1)){
$listArrayf1[] = fgets($file1);
}
fclose($file1);
echo var_dump($listArrayf1) . "<br /><br />";
$entries = count($listArrayf1) - 1;
echo $entries;
for($i=0;$i<=$entries;$i++){
$listArrayf2[] = "<br />".$listArrayf1[$i]."THE END";
fwrite($file2, $listArrayf2[$i]);
}
fclose($file2);
echo var_dump($listArrayf2);
/*
Open file1, r
Open file2, w
While it's not the end of the file, add each line of file1 to an array.
Count the number of lines in file1 and call it Entries. -1 because gotta start at 0.
Make a new array with the values of the old one, but with tags before and after it.
*/
?>
I'm sure there's a better way to accomplish the ultimate goal I'm trying, which is detecting certain words entered into a form, (There's probably a better way than making a formatted and non-formatted copy of what gets entered.) but my PHP vocab is limited and I'd like to figure out the long, prerequisite hard ways before learning how to do em easier.
At first I thought that it was because I was writing the OLDFILE manually, using the return key. So I made a script to write it using \n instead and it changed nothing.
Eh :)
At first, please take a look on var_dump and check what the function is returning (nothing, so correct usage is var_dump( ...); echo "<br />";)
Second, fgets reads string including newline character, so I guess you see in your string something like this:
string( 10) "abcdefghi
"
So you have to remove newline manually for example with trim.
Next, I'd recommend to (at least) take a look at foreach.
So I'd wrote the whole loop as:
foreach( $listArrayf1 as $row){
$row = "<br /><hr />". trim( $row)."THE END";
fwrite($file2, $row);
$listArrayf2[] = $row;
}
You may also use foreach( $listArrayf1 as &$row) and in the end $listArrayf1 will contain exactly the same as $listArrayf2. When you need to preserve all other spaces, you should probably use $row = substr( $row, 0, -1);
btw: you can write normal code, mark it in textarea and by hitting ctrl+k it'll get indented by 4 spaces
fgets returns the newline character at the end of each line as part of its input. That's where your "extra" newline comes from.
Change this
$listArrayf1[] = fgets($file1);
to this:
$listArrayf1[] = rtrim(fgets($file1), "\r\n");
This will remove the newline characters from the end of the return value and make your strings format as intended.
However, as you said yourself you are really doing things in a roundabout way. You could read all of file1 into an array with just
$listArrayf1 = file($filename1);
That's it. No loops, no fopen, no problems with newlines. It pays to look for the most fitting way of doing things.

Categories