PHP: How to assign large string with single and double quotes - php

I need to assign large strings in an array. These strings contain single and double quotes as well as backslashes which cannot be escaped at first.
My code looks like:
$myArray = [
'x' => 'this_is_my_string',
];
Now instead of 'this_is_my_string' I have large strings as:
\relative c' {
\key ees \major
bes'2 \mf c bes4. (as8) g4 (as) \breathe
\bar "|."
How to write my code to directly assign large strings like this one?
I have tried with HEREDOC and NOWDOC and addslashes/addcslashed but they require to escape at least one of ´or ".
BTW: the large strings are Lilypond snippets

Simply use a nowdoc.
A nowdoc is specified similarly to a heredoc, but no parsing is done
inside a nowdoc. The construct is ideal for embedding PHP code or
other large blocks of text without the need for escaping.
<?php
$myArray = [
'x' => <<<'STR'
\relative c' {
\key ees \major
bes'2 \mf c bes4. (as8) g4 (as) \breathe
\bar "|."
STR
];
echo $myArray['x'];

You're looking for Output Buffering.
<?php
ob_start();
?>\relative c' {
\key ees \major
bes'2 \mf c bes4. (as8) g4 (as) \breathe
\bar "|."<?php
$myArray = [
'x' => ob_get_clean()
];
?>
ob_start() initialises output buffering, redirecting STDOUT to the buffer. ob_end_clean() will end output buffering, and return the buffer up to that point for use.

Related

Replacing array string values which contains multiple special characters in php

I would like to replace array string values which contains multiple special characters to normal one.
Tried Code (array values):
$data['ENV_TEST'] = "rambo";
$data['ENV_DEV'] = "Project Bribara<"${ENV_TEST}"#gmail.com>"
echo str_replace("${ENV_TEST}", $data['ENV_DEV'], $data['ENV_DEV']);
also tried
echo str_replace("\"${ENV_TEST}\"", $data['ENV_DEV'], $data['ENV_DEV']);
Expected:
"Project Bribara<rambo#gmail.com>"
Actual:
"Project Bribara<"${ENV_TEST}"#gmail.com>"
How can I get the expected output?
You should on PHP strings sometime. The important part about double quoted strings for your question is that you need to put a backslash before every $ and every " inside your string. Your code will then look like this:
$data['ENV_TEST'] = "rambo";
$data['ENV_DEV'] = "Project Bribara<\"\${ENV_TEST}\"#gmail.com>";
echo str_replace("\${ENV_TEST}", $data['ENV_TEST'], $data['ENV_DEV']);
//also tried
echo "\n\n";
echo str_replace("\"\${ENV_TEST}\"", $data['ENV_TEST'], $data['ENV_DEV']);
If you use single quoted strings you don't need to escape $ (see the manual), and instead of \", you would need to escape single quotes (but there aren't any in your example).
$data['ENV_TEST'] = "rambo";
$data['ENV_DEV'] = 'Project Bribara<"${ENV_TEST}"#gmail.com>';
echo str_replace("\${ENV_TEST}", $data['ENV_TEST'], $data['ENV_DEV']);
//also tried
echo "\n\n";
echo str_replace('"${ENV_TEST}"', $data['ENV_TEST'], $data['ENV_DEV']);
I also fixed a missing semicolon and replaced DEV with TEST in one place.
String concatenation in PHP is done through the . operator. Your code would be:
$data['ENV_DEV'] = "Project Bribara<".$data['ENV_TEST']."#gmail.com>"

php nested heredoc and escaping variables

I am using heredoc to create a php file which needs to use heredoc in the generated file as the file will create other files.
The <<<EOD bit works fine and I can see all the variables properly escaped.
The problem I'm having is the nested heredoc <<<EOL where \$languageStrings isn't escaped
If I use \$languageStrings and run the generated file ddd.php, the output is this:
<?php
= Array (
'LBL_LOCATION_INFORMATION' => 'Basic Information',
'LBL_CUSTOM_INFORMATION' => 'Custom Information',
'SINGLE_' => ''
);
if i use \\$languageStrings trying to esacpe the backslash i get:
<?php
\ = Array (
'LBL_LOCATION_INFORMATION' => 'Basic Information',
'LBL_CUSTOM_INFORMATION' => 'Custom Information',
'SINGLE_' => ''
);
How can I correct this so i get $languageStrings = Array (? I did think about trying to open the file and insert into a specific line but the file will always be different.
I'm open to suggestions
Here is an example of my heredoc
$text = <<<EOD
This is some text
This is some more text
This is a \$variable //outputs this is a $variable
This is some more text
EOD;
$text .= <<<EOD
\n
\$targetpath = 'modules/' . \$moduleInstance->name;
if (!is_file(\$targetpath)) {
mkdir(\$targetpath);
mkdir(\$targetpath . '/language');
// create the language file
\$languagepath = 'languages/en_us';
\$languageContents = <<<EOL
<?php
\$languageStrings = Array (
'LBL_LOCATION_INFORMATION' => 'Basic Information',
'LBL_CUSTOM_INFORMATION' => 'Custom Information',
'SINGLE_\$moduleInstance->name' => '\$moduleInstance->name'
);
EOL;
file_put_contents(\$languagepath . '/' . \$module->name . '.php', \$languageContents);
}
EOD;
file_put_contents('ddd.php', $text);
I fixed it by creating a variable outside of the heredoc
$strings = '\$languageStrings';
and replacing \$languageStrings with $strings = Array ( in the heredoc string
The output is what I expected
Need a single quotes like Heredoc. This name is Nowdoc.
Nowdocs are to single-quoted strings what heredocs are to double-quoted strings.
$foo = "bar";
echo <<<STR
str $foo
STR;
echo <<<'STR'
str $foo
STR;
OR
echo "str $foo";
echo 'str $foo';
Expected Result:
->str bar
->str $foo
Since PHP 5.3.0, the opening Heredoc identifier may optionally be double quotes
<<<"FOO"
FOO;
same as
<<<FOO
FOO;
I prefer use every time double-quoted heredoc for intelligibility, although it is optional.
Doc says: php.net
Nowdocs are to single-quoted strings what heredocs are to
double-quoted strings. A nowdoc is specified similarly to a heredoc,
but no parsing is done inside a nowdoc. The construct is ideal for
embedding PHP code or other large blocks of text without the need for
escaping. It shares some features in common with the SGML construct, in that it declares a block of text which is not for
parsing.
A nowdoc is identified with the same <<< sequence used for heredocs,
but the identifier which follows is enclosed in single quotes, e.g.
<<<'EOT'. All the rules for heredoc identifiers also apply to nowdoc
identifiers, especially those regarding the appearance of the closing
identifier.

Using multiple quotations in PHP codes

Let's say this is my script down here, as you can see I've used multiple " and '. These quotations conflict in ending the current php variable, so it basically sees this:
$message = "<?php echo '<div class="
As a string, whilst the quotation is only to define the class, not to end the variable. I've tried using ' but then it conflicts with the echo, so I'm kinda stuck at the moment.
<?php
$message = "
<?php
echo '<div class="gebruiker">';
$fh = fopen('_gebruiker.txt','r');
while ($line = fgets($fh)) {
echo($line);
}
fclose($fh);
echo '</div>';
?>
";
**MORE PHP CODE HERE**
?>
How can I use multiple quotations in one PHP script without them having conflicts.
If you use single quotes outside, you need to escape all single quotes inside, but can use double quotes and the dollar char without escaping.
If you use double quotes outside, you need to escape all double quotes and dollar chars inside, but can use single quotes without escaping.
If you use a heredoc string, you need to escape dollar chars but can use both single and double quotes without escaping.
If you use a nowdoc string, you do not need to escape anything unless you have FOO; in the string at the beginning of a new line.
So the solution is to use a nowdoc string:
$message = <<<'EOF'
your stuff with " or ' or $ here!
EOF;
Adding a backslash so PHP can recognize just only double quotes or quotes when escaped.
Example:
echo "<div class=\"gebruiker\">";
I suggest using either Heredoc or Nowdoc
Example
$foo = 'test';
// Heredoc
$here = <<<HERE
I'm here, $foo!
HERE;
// Nowdoc
$now = <<<'NOW'
I'm now, $foo!
NOW;
Heredoc will print the contents of $foo when echoed while Nowdoc will simply echo $foo.
In the references I added below you can do more reading up on this subject.
References:
php.net - strings
stackoverflow - advantages of heredoc vs nowdoc
You can escape the quotes with a slash character like so: \"
This should work, you can't open Php tag without closing before.
<?php
$message = '<div class="gebruiker">';
$fh = fopen('_gebruiker.txt','r');
while ($line = fgets($fh)) {
$message .=$line.'<br/>';
}
fclose($fh);
$message.='</div>';
echo $message;
**MORE PHP CODE HERE**
?>

Does heredoc output variables which contains quotes?

I am using this:
$variable = "Name is \"Bob\"";
$message = <<<EOF
<input type="text" value="$variable">
EOF;
And the result is :
Actually, this is synthetic example and I am working with db. But I tried: this synthetic example works (to simulate problem, actually it shows that what I am doing is not working).
Yes, the quotes will appear in the HTML.
Since the quotes will end the attribute value, you'll make the HTML invalid.
You need to make the variable HTML-safe with htmlspecialchars().
You are generating invalid HTML:
<input type="text" value="Name is "Bob"">
Please use htmlspecialchars() to encode $variable before insertion.
A heredoc is just a convenient shortcut for a multi-line echo. It doesn't care WHAT'S in the string, it'll just be output.
There is NO difference between the following two constructs:
$foo = "A string with an \" embedded quote";
echo <<<EOL
Hello, $foo, how are you
EOL;
echo "Hello, $foo, how are you";
The only real difference is that you don't have escape quotes in the rest of the string:
echo <<<EOL
This is a "quoted phrase" within a sentence
EOL;
echo "This is a \"quoted phrase\" within a sentence";

PHP's json_encode does not escape all JSON control characters

Is there any reasons why PHP's json_encode function does not escape all JSON control characters in a string?
For example let's take a string which spans two rows and has control characters (\r \n " / \) in it:
<?php
$s = <<<END
First row.
Second row w/ "double quotes" and backslash: \.
END;
$s = json_encode($s);
echo $s;
// Will output: "First row.\r\nSecond row w\/ \"double quotes\" and backslash: \\."
?>
Note that carriage return and newline chars are unescaped. Why?
I'm using jQuery as my JS library and it's $.getJSON() function will do fine when you fully, 100% trust incoming data. Otherwise I use JSON.org's library json2.js like everybody else.
But if you try to parse that encoded string it throws an error:
<script type="text/javascript">
JSON.parse(<?php echo $s ?>); // Will throw SyntaxError
</script>
And you can't get the data! If you remove or escape \r \n " and \ in that string then JSON.parse() will not throw error.
Is there any existing, good PHP function for escaping control characters. Simple str_replace with search and replace arrays will not work.
function escapeJsonString($value) {
# list from www.json.org: (\b backspace, \f formfeed)
$escapers = array("\\", "/", "\"", "\n", "\r", "\t", "\x08", "\x0c");
$replacements = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b");
$result = str_replace($escapers, $replacements, $value);
return $result;
}
I'm using the above function which escapes a backslash (must be first in the arrays) and should deal with formfeeds and backspaces (I don't think \f and \b are supported in PHP).
D'oh - you need to double-encode: JSON.parse is expecting a string of course:
<script type="text/javascript">
JSON.parse(<?php echo json_encode($s) ?>);
</script>
I still haven't figured out any solution without str_replace..
Try this code.
$json_encoded_string = json_encode(...);
$json_encoded_string = str_replace("\r", '\r', $json_encoded_string);
$json_encoded_string = str_replace("\n", '\n', $json_encoded_string);
Hope that helps...
$search = array("\n", "\r", "\u", "\t", "\f", "\b", "/", '"');
$replace = array("\\n", "\\r", "\\u", "\\t", "\\f", "\\b", "\/", "\"");
$encoded_string = str_replace($search, $replace, $json);
This is the correct way
Converting to and fro from PHP should not be an issue.
PHP's json_encode does proper encoding but reinterpreting that inside java script can cause issues. Like
1) original string - [string with nnn newline in it] (where nnn is actual newline character)
2) json_encode will convert this to
[string with "\\n" newline in it] (control character converted to "\\n" - Literal "\n"
3) However when you print this again in a literal string using php echo then "\\n" is interpreted as "\n" and that causes heartache. Because JSON.parse will understand a literal printed "\n" as newline - a control character (nnn)
so to work around this: -
A)
First encode the json object in php using json_enocde and get a string. Then run it through a filter that makes it safe to be used inside html and java script.
B)
use the JSON string coming from PHP as a "literal" and put it inside single quotes instead of double quotes.
<?php
function form_safe_json($json) {
$json = empty($json) ? '[]' : $json ;
$search = array('\\',"\n","\r","\f","\t","\b","'") ;
$replace = array('\\\\',"\\n", "\\r","\\f","\\t","\\b", "&#039");
$json = str_replace($search,$replace,$json);
return $json;
}
$title = "Tiger's /new \\found \/freedom " ;
$description = <<<END
Tiger was caged
in a Zoo
And now he is in jungle
with freedom
END;
$book = new \stdClass ;
$book->title = $title ;
$book->description = $description ;
$strBook = json_encode($book);
$strBook = form_safe_json($strBook);
?>
<!DOCTYPE html>
<html>
<head>
<title> title</title>
<meta charset="utf-8">
<script type="text/javascript" src="/3p/jquery/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var strBookObj = '<?php echo $strBook; ?>' ;
try{
bookObj = JSON.parse(strBookObj) ;
console.log(bookObj.title);
console.log(bookObj.description);
$("#title").html(bookObj.title);
$("#description").html(bookObj.description);
} catch(ex) {
console.log("Error parsing book object json");
}
});
</script>
</head>
<body>
<h2> Json parsing test page </h2>
<div id="title"> </div>
<div id="description"> </div>
</body>
</html>
Put the string inside single quote in java script. Putting JSON string inside double quotes would cause the parser to fail at attribute markers (something like { "id" : "value" } ). No other escaping should be required if you put the string as "literal" and let JSON parser do the work.
I don't fully understand how var_export works, so I will update if I run into trouble, but this seems to be working for me:
<script>
window.things = JSON.parse(<?php var_export(json_encode($s)); ?>);
</script>
Maybe I'm blind, but in your example they ARE escaped. What about
<script type="text/javascript">
JSON.parse("<?php echo $s ?>"); // Will throw SyntaxError
</script>
(note different quotes)
Just an addition to Greg's response: the output of json_encode() is already contained in double-quotes ("), so there is no need to surround them with quotes again:
<script type="text/javascript">
JSON.parse(<?php echo $s ?>);
</script>
Control characters have no special meaning in HTML except for new line in textarea.value . JSON_encode on PHP > 5.2 will do it like you expected.
If you just want to show text you don't need to go after JSON. JSON is for arrays and objects in JavaScript (and indexed and associative array for PHP).
If you need a line feed for the texarea-tag:
$s=preg_replace('/\r */','',$s);
echo preg_replace('/ *\n */','
',$s);
This is what I use personally and it's never not worked. Had similar problems originally.
Source script (ajax) will take an array and json_encode it. Example:
$return['value'] = 'test';
$return['value2'] = 'derp';
echo json_encode($return);
My javascript will make an AJAX call and get the echoed "json_encode($return)" as its input, and in the script I'll use the following:
myVar = jQuery.parseJSON(msg.replace(/"/ig,'"'));
with "msg" being the returned value. So, for you, something like...
var msg = '<?php echo $s ?>';
myVar = jQuery.parseJSON(msg.replace(/"/ig,'"'));
...might work for you.
There are 2 solutions unless AJAX is used:
Write data into input like and read it in JS:
<input type="hidden" value="<?= htmlencode(json_encode($data)) ?>"/>
Use addslashes
var json = '<?= addslashes(json_encode($data)) ?>';
When using any form of Ajax, detailed documentation for the format of responses received from the CGI server seems to be lacking on the Web. Some Notes here and entries at stackoverflow.com point out that newlines in returned text or json data must be escaped to prevent infinite loops (hangs) in JSON conversion (possibly created by throwing an uncaught exception), whether done automatically by jQuery or manually using Javascript system or library JSON parsing calls.
In each case where programmers post this problem, inadequate solutions are presented (most often replacing \n by \\n on the sending side) and the matter is dropped. Their inadequacy is revealed when passing string values that accidentally embed control escape sequences, such as Windows pathnames. An example is "C:\Chris\Roberts.php", which contains the control characters ^c and ^r, which can cause JSON conversion of the string {"file":"C:\Chris\Roberts.php"} to loop forever. One way of generating such values is deliberately to attempt to pass PHP warning and error messages from server to client, a reasonable idea.
By definition, Ajax uses HTTP connections behind the scenes. Such connections pass data using GET and POST, both of which require encoding sent data to avoid incorrect syntax, including control characters.
This gives enough of a hint to construct what seems to be a solution (it needs more testing): to use rawurlencode on the PHP (sending) side to encode the data, and unescape on the Javascript (receiving) side to decode the data. In some cases, you will apply these to entire text strings, in other cases you will apply them only to values inside JSON.
If this idea turns out to be correct, simple examples can be constructed to help programmers at all levels solve this problem once and for all.

Categories