1

I have a php / javascript scrip which needs to print some text. unfortunately it seems that the js breaks down if the string has special characters such

'

Below is a snippet from the script. $messageContent and $subject are the strings with html tags. (actually "'" characters) .


echo '
<script language="javascript">
function SelectRedirect(){
switch(document.getElementById(\'s1\').value)
{
';

echo '
case "?vrj_name='.$vrj_name.'":
window.location="?vrj_name='.$vrj_name.'&messageContent='.$messageContent_vrj.'&from_email='.$from_email.'&email='.$email.'&subject='.$subject.'";
break;
';
}

I added a function in php to replace "'" with "\'" and it works (the js executes successfully ) but I can't get ride of them when I display them in the webpage .

user1963938
  • 115
  • 1
  • 2
  • 7
  • 1
    [json_encode](http://php.net/manual/en/function.json-encode.php) the strings – Supericy Feb 06 '13 at 00:01
  • 1
    You simply should not echo Javascript with PHP. Unmaintanable, unreadable, error-prone. See http://stackoverflow.com/questions/2766041/whats-the-best-way-to-pass-a-php-variable-to-javascript – kapa Feb 06 '13 at 00:01
  • @bažmegakapa: What's wrong with `json_encode`? – Jon Feb 06 '13 at 00:05
  • this really i an excellent question. i'd refer to the answer below by @gahooa, as he really does nail this one on the head. – Joshua Burns Feb 06 '13 at 00:06
  • @Jon Still better than the concatenated nightmare, but I'd prefer not to mix JS with PHP at all. Of course, in certain situations, it seems to be the best option, but I'd prefer the `data-` attribute solution. – kapa Feb 06 '13 at 00:07
  • @bažmegakapa: your comment is completely unrealistic for real-world applications. PHP is a general purpose templating language that works equally well for HTML, text, css, javascript, and others. – gahooa Feb 06 '13 at 00:13
  • @gahooa Means I have created a lot of unrealistic applications :). I guess it's a matter of taste, my stomach does like separation of concerns better. I have not said I have never got into a situation where I was stuck with doing it the echo-to-js way. – kapa Feb 06 '13 at 00:18
  • @bažmegakapa: Please forgive any offence. I think the main use case is outlined in my comment under my answer -- virtually the only use case I run into (but pretty frequently). – gahooa Feb 06 '13 at 03:14

3 Answers3

3

The best way to do this is to encode the values using json_encode. Here is a simple example:

<?php
$name = "Jason's Bakery";

?>
<script>
   var name = <?php echo json_encode($name); ?>;
   DoSomethingWithName(name);
</script>

This can be used for integers, strings, and other values. Keep in mind that it will add quotes as needed, so you need to assemble and encode a "whole value at once". In your example of using the URLs, you need to use the PHP urlencode() function to encode them FIRST, and then pass it through json_encode to convert to a javascript value. And if you are placing that inside of an HTML attribute, like onclick, you need to further pass it through htmlspecialchars(..., ENT_QUOTES) and then place it in double quotes.

http://php.net/manual/en/function.json-encode.php

So for example, you need to build a URL in PHP and then use it in javascript...

<?php
$name = "Jason's \"Awesome\" Bakery";
$url = "http://site.com/page.php?name=" . urlencode($name);

?>
<script>
   var name = <?php echo json_encode($name); ?>;
   DoSomethingWithName(name);
</script>

<input type="button" onclick="<?php echo htmlspecialchars('window.location = ' . json_encode($url) . ';', ENT_QUOTES); ?>" value="Click Me" />

Which results in something like this:

<script>
   var name = "Jason's \"Awesome\" Bakery";
   DoSomethingWithName(name);
</script>

<input type="button" onclick="window.location = &quot;http:\/\/site.com\/page.php?name=Jason%27s+%22Awesome%22+Bakery&quot;;" value="Click Me" />

Needless to say, you do not want to do without these:

http://php.net/manual/en/function.json-encode.php
http://www.php.net/manual/en/function.urlencode.php
http://www.php.net/manual/en/function.htmlspecialchars.php

gahooa
  • 131,293
  • 12
  • 98
  • 101
  • I'd argue "best way", but nice answer otherwise. – kapa Feb 06 '13 at 00:08
  • @bažmegakapa: please explain, for my benefit, how you would do it? (Considering my edit) – gahooa Feb 06 '13 at 00:12
  • I'd not use PHP to echo something into Javascript code, but I'd use the `data-` attribute of an HTML element to pass the data (normally it fits on an element, if not, you still have `body`). Described here: http://stackoverflow.com/questions/2766041/whats-the-best-way-to-pass-a-php-variable-to-javascript . I upvoted your answer btw. – kapa Feb 06 '13 at 00:15
  • @bažmegakapa: Yes, I agree and prefer that as well. However, there is not much more distasteful things than a page that loads only to trigger an ajax call to get the data. This is the prime use-case for injecting JSON data into an HTML page -- to eliminate that. And you can retain full ajax functionality by using a separate function to get the data and process it -- initial page load only calls the processing function using the `json_encode` outputted data while subsequent calls use AJAX to get data and pass it on. – gahooa Feb 06 '13 at 03:12
  • Now I realized I'm talking to the same person in the comments under the question :D. You're right, using Ajax for this is overkill. I'm only saying that instead of `var x = =$y?>;` (where `$y` is a JSON string), you should put the data into the HTML: `
    ` where `$y` is a JSON string properly escaped to be inserted into a HTML attribute. Now the DOM can be used to retrieve the data, and everything remains separated. I find this cleaner. I just wanted to mention it though, so that later visitors will see that there is an alternative and they can choose.
    – kapa Feb 06 '13 at 11:44
1

Due to respects of readability and future maintainability, I'd like to point out a few things which may help you out.

First, I see you're generating HTML elements in a PHP string. This isn't inherently bad, but when your string wraps across 2 or more lines, it becomes increasingly difficult to manage. Instead, you may want to think about escaping PHP for outputting HTML portions, and re-entering PHP for logical portions. You can escape PHP and enter HTML within if statements, function declarations etc, so there's really no good reason not to. Look at the following example (this solution also escapes the strings in an appropriate manner where its value can contain single quotes, double quotes or line breaks):

<?php

function urlFriendly($input) {
    return urlencode($input);
}

function jsFriendly($input, $urlFriendly = True) {
    $output = htmlentities($input, ENT_QUOTES);
    // Double quotes in PHP translate "\n" to a newline.
    // Single quotes in PHP keep the literal value.
    $output = str_replace("\r\n", '\n', $output); // Windows support
    $output = str_replace("\n", '\n', $output); // Linux support
    if($urlFriendly) { // Encode for use in URLs
      $output = urlFriendly($output);
    }
    return $output;
}

$vrj_name = 'vrj';
$messageContent_vrj = 'message content';
$from_email = 'from email';
$email = 'email';
$subject = 'subject line';

?>
<script type="text/javascript">
    function SelectRedirect() {
    switch(document.getElementById('s1').value) {
        case '?vrj_name=<?php print jsFriendly($vrj_name);?>':
            var toloc = '?vrj_name=<?php print jsFriendly($vrj_name);?>';
            toloc    += '&messageContent=<?php print jsFriendly($messageContent_vrj);?>'';
            toloc    += '&from_email=<?php print jsFriendly($from_email);?>';
            toloc    += '&email=<?php print jsFriendly($email);?>';
            toloc    += '&subject=<?php print jsFriendly($subject);?>';
            window.location = toloc;
            break;
    }
</script>
Joshua Burns
  • 8,268
  • 4
  • 48
  • 61
0

just like that

$escaped_string = addslashes($unescaped_string);

either before

$messageContent = addslashes($messageContent);
$subject = addslashes($subject);

or even inline

echo '
case "?vrj_name='.$vrj_name.'":
window.location="?vrj_name='.$vrj_name.'&messageContent='.addslashes($messageContent).'&from_email='.$from_email.'&email='.$email.'&subject='.addslashes($subject).'";
break;
';
itsid
  • 801
  • 7
  • 16