Use PHP functions in JavaScript

JavaScript var_export

Outputs or returns a string representation of a variable

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
29
3031
32
33
34
3536
37
38
39
4041
42
43
44
4546
47
48
49
5051
52
53
54
5556
57
58
59
6061
62
63
64
6566
67
68
69
7071
72
73
74
7576
77
78
79
8081
82
83
84
8586
87
88
89
9091
92
93
94
9596
97
98
99
100101
102
103
104
105106
107
108
109
function var_export (mixed_expression, bool_return) {
    // Outputs or returns a string representation of a variable  
    // 
    // version: 1109.2015
    // discuss at: http://phpjs.org/functions/var_export    // +   original by: Philip Peterson
    // +   improved by: johnrembo
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   input by: Brian Tafoya (http://www.premasolutions.com/)
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // -    depends on: echo
    // *     example 1: var_export(null);
    // *     returns 1: null
    // *     example 2: var_export({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}, true);    // *     returns 2: "array (\n  0 => 'Kevin',\n  1 => 'van',\n  2 => 'Zonneveld'\n)"
    // *     example 3: data = 'Kevin';
    // *     example 3: var_export(data, true);
    // *     returns 3: "'Kevin'"
    var retstr = '',        iret = '',
        cnt = 0,
        x = [],
        i = 0,
        funcParts = [],        idtLevel = arguments[2] || 2,
        // We use the last argument (not part of PHP) to pass in our indentation level
        innerIndent = '',
        outerIndent = '';
     var getFuncName = function (fn) {
        var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn);
        if (!name) {
            return '(Anonymous)';
        }        return name[1];
    };
 
    var _makeIndent = function (idtLevel) {
        return (new Array(idtLevel + 1)).join(' ');    };
 
    var __getType = function (inp) {
        var i = 0;
        var match, type = typeof inp;        if (type === 'object' && inp.constructor && getFuncName(inp.constructor) === 'PHPJS_Resource') {
            return 'resource';
        }
        if (type === 'function') {
            return 'function';        }
        if (type === 'object' && !inp) {
            return 'null'; // Should this be just null?
        }
        if (type === "object") {            if (!inp.constructor) {
                return 'object';
            }
            var cons = inp.constructor.toString();
            match = cons.match(/(\w+)\(/);            if (match) {
                cons = match[1].toLowerCase();
            }
            var types = ["boolean", "number", "string", "array"];
            for (i = 0; i < types.length; i++) {                if (cons === types[i]) {
                    type = types[i];
                    break;
                }
            }        }
        return type;
    };
    var type = __getType(mixed_expression);
     if (type === null) {
        retstr = "NULL";
    } else if (type === 'array' || type === 'object') {
        outerIndent = _makeIndent(idtLevel - 2);
        innerIndent = _makeIndent(idtLevel);        for (i in mixed_expression) {
            var value = this.var_export(mixed_expression[i], true, idtLevel + 2);
            value = typeof value === 'string' ? value.replace(/</g, '&lt;').replace(/>/g, '&gt;') : value;
            x[cnt++] = innerIndent + i + ' => ' + (__getType(mixed_expression[i]) === 'array' ? '\n' : '') + value;
        }        iret = x.join(',\n');
        retstr = outerIndent + "array (\n" + iret + '\n' + outerIndent + ')';
    } else if (type === 'function') {
        funcParts = mixed_expression.toString().match(/function .*?\((.*?)\) \{([\s\S]*)\}/);
         // For lambda functions, var_export() outputs such as the following:  '\000lambda_1'
        // Since it will probably not be a common use to expect this (unhelpful) form, we'll use another PHP-exportable
        // construct, create_function() (though dollar signs must be on the variables in JavaScript); if using instead
        // in JavaScript and you are using the namespaced version, note that create_function() will not be available
        // as a global        retstr = "create_function ('" + funcParts[1] + "', '" + funcParts[2].replace(new RegExp("'", 'g'), "\\'") + "')";
    } else if (type === 'resource') {
        retstr = 'NULL'; // Resources treated as null for var_export
    } else {
        retstr = (typeof(mixed_expression) !== 'string') ? mixed_expression : "'" + mixed_expression.replace(/(["'])/g, "\\$1").replace(/\0/g, "\\0") + "'";    }
 
    if (bool_return !== true) {
        this.echo(retstr);
        return null;    } else {
        return retstr;
    }
}
external links: original PHP docs | raw js source

Examples

» Example 1

Running

1
var_export(null);

Should return

1
null

» Example 2

Running

1
var_export({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}, true);

Should return

1
"array (\n  0 => 'Kevin',\n  1 => 'van',\n  2 => 'Zonneveld'\n)"

Dependencies

In order to use this function, you also need:

Open syntax issues

php.js uses JsLint to help us keep our code consistent and prevent some common bugs.

Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.


Authors

Thanks to the following developers, you get to have var_export goodness in JavaScript.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
ekim
20 Apr '11 Permalink

q  

RA=[]; RA[1]=RA;
curse={re:RA}; curse.s=curse;


Can the output strings for RA and curse be posted to see what they look like?

Gravatar
Kevin van Zonneveld
14 Jul '09 Permalink

q  @ Brett Zamir & Brian Tafoya: Good job guys!

Gravatar
Brett Zamir
13 Jul '09 Permalink

q  Fixed in SVN. Thanks for the report!

In the meantime, convert "[^]" to "[\s\S]" (no quotes). The former works in PHP and Mozilla JavaScript but not IE--also fixed in the remaining functions which had this problem.

Gravatar
Brian Tafoya
13 Jul '09 Permalink

q  According to IE, there is an error within the regex on line 74...

funcParts = mixed_expression.toString().match(/function .*?\((.*?)\) \{([^]*)\}/);



Claims it is expecting an ']' but I was not able to resolve this.

Gravatar
Brett Zamir
17 Apr '09 Permalink

q  Hello Tom,

You might look at our serialize implementation http://phpjs.org/functions/view/508 for support for some JS types.

As you might already be aware, you can also get some of this with JSON. See http://json.org if you're not familiar with it or are looking for an existing parser/stringifier (Mozilla provides access to these natively for JSON parsing/stringifying if you were working with Firefox extensions). You technically can just use "eval()" for parsing, but that is unsafe, especially if user input could creep into the expression, unless you know what you're doing with it.

However, it is true that JSON (as with serialize() in some cases) does not allow other JS types, specifically functions (as you list) including as classes, the "undefined" type, Date objects, RegExp objects, and the built-in Error types (see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error ) (unless these are represented in some other way, just as strings or objects), and does not capture the prototype for objects.

That would be a useful option to have, I think, so if someone can implement it, maybe we can have a switch in the function to determine what kind of output to give. For most types, it shouldn't be too hard to do, as you could usually just rely on "toString()" (at least as a base), though you'd have to grab any user-defined prototype object on a function, etc. ...

This is a good example of the cases where being able to have configuration options is useful. php_check_syntax() has a similar dilemma to yours.

We've already built in some support for this which can be used now: PHP-style ini options. So, we could define our own "ini" for this function, using "phpjs." as the "extension prefix" (e.g., "phpjs.var_export_as_js"), and then allow users to use an ini file or ini_set() to set a non-default behavior. The function in turn would do a check like:

// this.php_js.ini would be set earlier, by ini_set(), an ini file 
// which directly added to this.php_js.ini (fastest), or by parsing a
// PHP-style ini file (no support for the latter yet). 
//

if (this.php_js && this.php_js.ini && this.php_js.ini.local_value['phpjs.var_export_as_js']) { // each ini should define local_value and global_value, so that it is possible to revert within the script back from ini_set() to the default behavior.
...
}



Note that references to 'this' will also work for the non-namespaced version of PHP.JS as it refers to the window object (PHP.JS reserves one global, "php_js", in the non-namespaced version).

At some point in the future, I think Kevin agreed in principle to allowing the namespaced version to accept configuration options in the constructor (e.g., $P = new PHP_JS({phpjs.var_export_as_js:true, ...})), so that, e.g., you could specify that by default you wanted var_export to work with JS.

Gravatar
Tom
16 Apr '09 Permalink

q  The returned representation of provided function is valid PHP code (which is correct). But does anyone have a JS var_export function whose returned representation is valid javascript code? The returned value should be string and it could be passed to eval() function
Examples:

var a = new Array(12, '13', 'abc', 'line1\nline2\nline3');
var js_code = var_export(a);
/*
the returned value should be:
"{0:12, 1:'13', 2:'abc', 3:'line1\nline2\nline3'}"
*/

var b = {'key1':4, 'key2':'5', 'key3':'xxx\n123', 555:'text'};
js_code = var_export(b);
/*
the returned value should be:
"{'key1':4, 'key2':'5', 'key3':'xxx\n123', 555:'text'}"
*/

var c = 123;
js_code = var_export(c); // "123"

var d = '321';
js_code = var_export(d); // "'321'"

var e = 'multilne\ntext';
js_code = var_export(e); // "'multiline\ntext'"

function add(x, y)
{
      res = x + y;
      return res;
}
var js_code = var_export(add);
/*
the returned value should be:
"function add(x, y) { res = x + y; return res; }"
*/



Thanks.

Gravatar
johnrembo
22 Aug '08 Permalink

q  currently this function fails on objects that contain any method. Also, I suggest to use typeof instead of instanceof:

var phpBridge = {
var_export: function (mixed_content) {
var variable=mixed_content;
var __pad_lines = function ( x ) {
return x.split(&quot;\n&quot;).join(&quot;\n &quot;);
};

var retstr = &quot;&quot;;

if(typeof variable == ('object' || 'array')) {
var iret = &quot;&quot;;
for(i in variable) {
iret=iret+&quot;\n&quot;+this.var_export(i,true)+&quot; =&gt; &quot;+this.var_export(variable[i], true)+&quot;,&quot;;
}
retstr = &quot;array (&quot;+__pad_lines(iret)+&quot;\n)&quot;;
} else if( variable === null) {
retstr = &quot;NULL&quot;;
} else if ( typeof variable == 'function') {
retstr=&quot;'function'&quot;;
} else {
retstr = (!isNaN( variable )) ? variable : &quot;'&quot; + variable.replace('/([&quot;\'\])/g', &quot;\\$1&quot;).replace('/\0/g', &quot;\\0&quot;) + &quot;'&quot;;
}

return retstr;
}
}

Gravatar
Kevin van Zonneveld
20 Jul '08 Permalink

q  @ Oleg Butuzov: I'd think it would be great to have a sleep function, but this implementation locks up the browser. Maybe we could investigate in an alternative implementation based on setTimeout or something?

Gravatar
Oleg Butuzov (http://made.com.ua)
19 Jul '08 Permalink

q  sleep ?

[CODE=&quot;Javascript&quot;]
function sleep(seconds) {
for(var i=seconds; i &gt; 0; i--) {
var start = Number(new Date().getTime());
while (true) {
if ( (new Date().getTime() - start) &gt; 1000) {
break;
}
}
}
}

[/CODE]


Contribute a New function

More functions

In this category

doubleval
empty
floatval
get_defined_vars
get_resource_type
gettype
import_request_variables
intval
is_array
is_binary
is_bool
is_buffer
is_callable
is_double
is_float
is_int
is_integer
is_long
is_null
is_numeric
is_object
is_real
is_resource
is_scalar
is_string
is_unicode
isset
print_r
serialize
settype
strval
unserialize
var_dump
» var_export

Support us

spread the word:


Use any PHP function in JavaScript


These kind folks have already donated: AYHAN BARI*, Nikita Ekshiyan, Nikita Ekshiyan, Petr Pavel, @HalfWinter, Paulo Freitas, Andros Peña Romo, @andorosu, Raimund Szabo, Nitin Gupta, @nikosdion, Anonymous, Anonymous and Shawn Houser.
<your name here>

Click here to lend your support to: phpjs and make a donation at www.pledgie.com !