I'm trying to get 3 pdf files attached to an email, the problem I have is that is_file gives a false on the first two files but the third file it works. The files come from a textbox and are exploded like this:
$pdfs = explode("\n", $string);
And I put it in a foreach loop to attach to an email like this:
foreach($pdfs as $pdf) {
if (is_file(JPATH_ROOT . $pdf)) {
$mail['attachment'][] =
array('name' => basename($pdf), 'file' => JPATH_ROOT . $pdf);
}
}
When I run this code I only get the third pdf file attached, however if I remove the is_file() they are in the array but won't attach to the sent email.
So the results then are:
[attachment] => Array
(
[0] => Array
(
[name] => pdf_file_1.pdf
[file] => /home/psinke/domains/*****/public_html/pdf_file_1.pdf
)
[1] => Array
(
[name] => pdf_file_2.pdf
[file] => /home/psinke/domains/*****/public_html/pdf_file_2.pdf
)
[2] => Array
(
[name] => pdf_file_3.pdf
[file] => /home/psinke/domains/*****/public_html/pdf_file_3.pdf
)
)
But the first two files do not attach to the sent email.
Likely the line break that separates those entries in your input data is not just \n ... so you might have left a \r at the end of the first two, which of course makes PHP not find those files.
The third file won’t have this problem, because likely after that line there is no more line break.
The files come from a textbox
Assuming you mean an HTML textarea element - all modern browsers send \r\n for a line break in a textarea - so if you only get your content from there, exploding at "\r\n" should work. If you are not sure about the exact line break format used beforehand, you can also use a preg_split solution as shown here, https://stackoverflow.com/a/36851287/1427878
Related
$content="The value of this variable is {$array['1']['value']}"
I have to do this multiple times within many paragraphs for different mutli-dimensional array values. Can't seem to find the answer online. Thank you!
Edit:
I have a multi dimensional array currently being posted to the page I am posting the array to, so lets say I wanted to get the value that is currently in:
$array['1']['thisvalue']
In the same file I have a variable $content:
I am using $content to store text from an article. In this article in the $content variable, I have some fill in the blanks which I will use the array value ($array['1']['thisvalue']) to fill in. so for example:
$content="my name is_____ and my height is ____"
$array['1']['thisvalue'] would contain my name and $array['2']['thisvalue'] would contain my height
so
$content="my name is $array['1']['thisvalue'] and my height is $array['2']['thisvalue']"
Then at the end of filling in all the blanks I have
file_put_contents($file, $content);
$file is a file I have generated in another directory, and I am putting the contents into the file.
MY QUESTION IS:
How do I use my multidimensional arrays to fill in the blanks of my article so that it will expand with the correct values when i write to this separate $file file.
A foreach or any other kind of loop will do the work for you.
i.e. :
Array :
print_r($arr);
Array
(
[0] => Array
(
[some_key] => Something
)
[1] => Array
(
[some_key] => Another Something
)
[2] => Array
(
[some_key] => Again Another Something
)
[3] => Array
(
[some_key] => Something Else
)
[4] => Array
(
[some_key] => Need more imagination...
)
)
Loop :
foreach ($arr as $item) {
echo $item['some_key'] . "\n";
}
Output :
Something
Another Something
Again Another Something
Something Else
Need more imagination...
I noticed that str_getcsv doesn't seem to enclose the first value it receives in double quotation marks, even when the string data is passed this way.
In the example below, the first value in the 3rd row is "Small Box, But Smaller", but after running it through str_getcsv it becomes Small Box, But Smaller (without double quotation marks). Like this:
// multi-line csv string
$csvString = <<<'CSV'
"Title","Description",Quantity
"Small Box","For storing magic beans.",2
"Small Box, But Smaller","Not sure why we need this.",0
CSV;
// split string into rows (don't use explode in case multi-line values exist)
$csvRows = str_getcsv($csvString, "\n"); // parse rows
echo '<pre>';
print_r($csvRows);
echo '</pre>';
Outputs:
Array
(
[0] => Title,"Description",Quantity
[1] => Small Box,"For storing magic beans.",2
[2] => Small Box, But Smaller,"Not sure why we need this.",0
)
The problem this causes is that now if each row is parsed using str_getcsv, a comma in the first value makes it split into two rows. If it keeps running this:
foreach($csvRows as &$csvRow) {
$csvRow = str_getcsv($csvRow); // parse each row into values and save over original array value
}
unset($csvRow); // clean up
// output
echo '<pre>';
print_r($csvRows);
echo '</pre>';
Outputs:
Array
(
[0] => Array
(
[0] => Title
[1] => Description
[2] => Quantity
)
[1] => Array
(
[0] => Small Box
[1] => For storing magic beans.
[2] => 2
)
[2] => Array
(
[0] => Small Box
[1] => But Smaller
[2] => Not sure why we need this.
[3] => 0
)
)
The problem is in the last array value, which is an array of 4 keys instead of 3. It's split on the comma of the value "Small Box, But Smaller".
On the other hand, parsing just one row string works:
$csvRowData = '"Small Box, But Smaller","Not sure why we need this.",0';
$csvValues = str_getcsv($csvRowData);
echo '<pre>';
print_r($csvValues);
echo '</pre>';
Outputs:
Array
(
[0] => Small Box, But Smaller
[1] => Not sure why we need this.
[2] => 0
)
Why is this happening and how do I solve the problem with multi-line CSV data? Is there a best practice for working with multi-line CSV data when it is a string and is not read directly from a file? Also, I need to handle multi-line values, such as "foo \n bar" so I can't just use explode() instead of the first str_getcsv().
After much headache I think I understand the problem now. According to the PHP folks, "str_getcsv() is designed to parse a single CSV record into fields" (see https://bugs.php.net/bug.php?id=55763). I discovered that using str_getcsv() for multiple rows causes these not-so-well documented problems:
Double quotation marks are not maintained (as I demontrate above).
Line breaks in values cause it to think a new row has begun. This can have many unintended consequences.
I solved the issue by creating a temporary file and writing the CSV content to it. Then I read the file using fgetcsv(), which did not result in the 2 issues I described above. Example code:
// multi-line csv string
$csvString = <<<'CSV'
"Title","Description",Quantity
"Small Box","For storing magic beans.",2
"Small Box, But Smaller","This value
contains
multiple
lines.",0
CSV;
// ^ notice the multiple lines in the last row's value
// create a temporary file
$tempFile = tmpfile();
// write the CSV to the file
fwrite($tempFile, $csvString);
// go to first character
fseek($tempFile, 0);
// track CSV rows
$csvRows = array();
// read the CSV temp file line by line
while (($csvColumns = fgetcsv($tempFile)) !== false) {
$csvRows[] = $csvColumns; // push columns to array (really it would be more memory-efficient to process the data here and not append to an array)
}
// Close and delete the temp file
fclose($tempFile);
// output
echo '<pre>';
print_r($csvRows);
echo '</pre>';
Results in:
Array
(
[0] => Array
(
[0] => Title
[1] => Description
[2] => Quantity
)
[1] => Array
(
[0] => Small Box
[1] => For storing magic beans.
[2] => 2
)
[2] => Array
(
[0] => Small Box, But Smaller
[1] => This value
contains
multiple
lines.
[2] => 0
)
)
I'll also add that I found some options on GitHub, and 2 major projects for PHP 5.4+ and PHP 5.5+. However, I am still using PHP 5.3 and only saw options with limited activity. Furthermore, some of those processed CSV strings by writing to files and reading them out also.
I should also note that the documentation for PHP has some comments about str_getcsv() not being RFC-compliant: http://php.net/manual/en/function.str-getcsv.php. The same seems to be true for fgetcsv() yet the latter did meet my needs, at least in this case.
I don't know why you PHP_EOL is not working correctly as it does on my server however I did encounter this problem before.
The approach I took goes as follows.
Firstly I like to make sure all my fields are surrounded by double quotes regardless of the value in the field so to use your example text (with some slight modifications):
// multi-line csv string
$csvString = <<<CSV
"Title","Description","Quantity"
"Small Box","For storing magic beans.","2"
"Small Box, But Smaller","Not sure why we need this.","0"
"a","\n","b","c"
CSV;
$csvString .= '"a","' . "\n" . '","' . PHP_EOL . '","c"';
Secondly I target solo PHP_EOL that may be lingering in values so I can replace any "PHP_EOL" strings with "\r\n"
// Clear any solo end of line characters that are within values
$csvString = str_replace('","' . PHP_EOL . '"', '",""',$csvString);
$csvString = str_replace('"' . PHP_EOL . '","', '"","',$csvString);
$csvString = str_replace('"' . PHP_EOL . '"', '"'. "\r\n" . '"',$csvString);
and then finally this allows me to use the php explode function and display output:
$csvArr = explode("\r\n",$csvString);
foreach($csvArr as &$csvRow) {
$csvRow = str_getcsv($csvRow); // parse each row into values and save over original array value
}
unset($csvRow); // clean up
// output
echo '<pre>';
print_r($csvArr);
echo '</pre>';
Which outputs:
Array
(
[0] => Array
(
[0] => Title
[1] => Description
[2] => Quantity
)
[1] => Array
(
[0] => Small Box
[1] => For storing magic beans.
[2] => 2
)
[2] => Array
(
[0] => Small Box, But Smaller
[1] => Not sure why we need this.
[2] => 0
)
[3] => Array
(
[0] => a
[1] =>
[2] => b
[3] => c
)
[4] => Array
(
[0] => a
[1] =>
[2] =>
[3] => c
)
)
As you can see from the output the new line characters are not targeted, just the PHP_EOL.
Please check the below array:
Array([bunrey] => Array ([0] => 20130730181908615391000000)
[mt.shasta] => Array (
[0] => 20130708203742347410000000
[1] => 20130213201456984069000000
[2] => 20130712144459481348000000
)
[shingletwon] => Array
(
[0] => 20130801233842122771000000
)
)
I want to send this array as query string using http_build_query(),
I got the below string after using http_build_query():
bunrey%5B0%5D=20130730181908615391000000&mt.shasta%5B0%5D=20130708203742347410000000&mt.shasta%5B1%5D=20130213201456984069000000&mt.shasta%5B2%5D=20130712144459481348000000&shingletwon%5B0%5D=20130801233842122771000000
As you can see after sending this query string to some other file, there I am trying to retrieve. I had echoed the $_REQUEST object:
Array (
[bunrey] => Array
(
[0] => 20130730181908615391000000
)
[mt_shasta] => Array
(
[0] => 20130708203742347410000000
[1] => 20130213201456984069000000
[2] => 20130712144459481348000000
)
[shingletwon] => Array
(
[0] => 20130801233842122771000000
)
)
please check one of the key mr.shasta had changed to mr_shasta.
Can you people please provide any solution for this.
This is the standard PHP behaviour. Points are converted in underscores when used as array keys in a POST request.
From the documentation:
Dots and spaces in variable names are converted to underscores. For
example < input name="a.b" /> becomes $_REQUEST["a_b"].
The only solution is: stop using spaces and/or dots in array keys when using them in POST requests or, else, operate a string replace on every array key your receive.
$post = array();
foreach ($_POST as $key => $value)
$post[str_replace("_", ".", $key)] = $value;
Note that the code above would fix only the problem of . (converted to _) but not spaces. Also, if you have any _ in your original key this would be converted to . as well (as pointed out in the comments).
As you can see, the only real solution is to avoid . and spaces in $_POST keys. They just can't be received, not with PHP (and not with other server-side solutions that I know of): you'll loose that information.
No, this is not a limitation or a crap feature: this is a programming guideline. If you're using array keys names for something more than what you would normally do with a variable name, you're most likely doing something conceptually wrong (and I've done it many times too).
Just to give you an example on how wrong is that: in some programming solutions like asp.net-mvc (and, I think, codeigniter too) POST/GET requests are supposed to be mapped over functions in what's called a "controller". Which means that if you send a POST which looks like ["myKey" => "myValue", "myOtherKey" => "someValue"] you should then have a function which takes keys as arguments.
function(String myKey, String myOtherKey){ }
PHP have no default "on-top" framework (that I know of) which do this: it allows you to access $_POST directly. Cool: but this toy can breake easely. Use it with caution.
I may be wrong here, but I've replicated what you're doing and have found it depends how you assign the array as to whether or not it changes the key like this:
//doesn't change to mt_shasta
$array['bunrey'][0] = 20130730181908615391000000;
$array['bunrey']['mt.shasta'][0] = 20130708203742347410000000;
$array['bunrey']['mt.shasta'][1] = 20130708203742347410000000;
$array['bunrey']['mt.shasta'][2] = 20130708203742347410000000;
$array['bunrey']['shingletwon'][0] = 20130708203742347410000000;
//does change to mt_shasta
$array = array (
'0' => 20130730181908615391000000,
'mt.shasta' => array (
0 => 20130708203742347410000000,
1 => 20130213201456984069000000,
2 => 20130712144459481348000000,
),
'shingletwon' => array
(
0 => 20130801233842122771000000,
),
);
I'm using print_r for an array but it's not printing it in a "human readable" way in the browser. It's just printing as if I echoed:
Array ( [0] => Array ( [uid1] => 012345 [uid2] => 012345 ) [1] => Array ( [uid1] => 012345 [uid2] => 622279 ) [2] => 012345 ( [uid1] => 012345 [uid2] => 012345 ) [3] => Array ( [uid1] => 012345 [uid2] => 012345 )
etc.
What's causing this?
If you're outputting it to the browser, do this:
echo "<pre>" . print_r($value, true) . "</pre>";
The tabulations and carriage returns are not rendered as such in HTML, unless inside a <pre> block.
Browsers automatically collapse all line breaks, tabs, and spaces in between the characters into a single space, which produces the "not as readable" output. In order to preserve all these, try wrapping your print_r output in <code><pre>.
You can use var_dump($array) or a echo nl2br(print_r($array, true));
right-click with the mouse on the page and hit "View Page Source" you should see the original text...
If your code has no the mission to generate pretty html view, for example, you just working with the some class, you can avoid the pre wrapping by sending header("Content-type: text/plain"). All output will be pre-formatted like monospaced text with the \n line breaks.
In other cases, the better way is using output in Log file. Log files might be view by external application, like the "Console" on a Mac.
I have a .csv template I'd wish for people to fill up, save it and upload it.
The problem is this, assuming some users would insert hidden line breaks in a row, when using fgetcsv() it would output the row broken by the hidden line breaks.
How can I escape the line break or sanitize my data?
Possible solution:
assume first row is correct, $count = count the number of delimiters until line break, the rebuild the text into an array as long as $count;
but i think the're better options available.
LATER EDIT
Here's the input *IMPORTANT[ ! ] : the data inside the excel file is "fine", it isn't broken, it's a single row!!! saving it as a csv file and opening it in notepad shows the following
asd;"asd
asd
asd";asd;asd
Here's the code
$handle = fopen("file.csv","r");
$data = fgetcsv($handle,";");
while($data = fgetcsv($handle)) {
$array = explode(";",$data[0]);
print_r($array);
}
fclose($handle);
Here's the echoed data
Array ( [0] => asd [1] => "asd ) Array ( [0] => asd ) Array ( [0] => asd" [1] => asd [2] => asd [3] => )
Thanks
it is very easy to test your case and see that there are no broken rows, if fields being properly quoted.
So, a CSV line like this
1,"joe
""Big Coyote""
Hopkins",598600
will be read with not a single problem.