This tool transforms JavaScript to PHP.
Note: This was a hobby project from a number of years ago and is not actively maintained, however PRs are welcome.
Also Note: This does not work with ES6+ JavaScript features (which were not widely available at the time this project was written). If you want to use next-generation JS features you should first pre-process your code using babel. PR to support ES6+ would be welcome.
This is a proof-of-concept and a hobby project, mostly just for fun. There are various aspects of the two languages that make this a really interesting challenge: lexical scope, lambdas, prototypal inheritance, PHP's implicit variable declaration, etc. Some amount of code is implemented as runtime helpers, including operations which require type checking and "standard library" features such as Date functions. But it turns out JavaScript and PHP are similar enough to do most everything as a source transformation, and the PHP code produced is still readable.
There are plenty of "compile to JS" languages available (ReasonML, TypeScript, CoffeeScript, Dart), but not many choices in the PHP space**. PHP is ubiquitous in bulk hosting, it runs on millions of servers around the web and PHP applications are generally easy to host and maintain. So if you need to host on PHP but don't like writing PHP, well in theory you could write in JS and deploy to PHP!
Maybe so. But if you wanted a compile-to-PHP language, that's widely familiar to devs, with plenty of existing tooling, libraries and community, then maybe JS is such a language. Plus, I think there's an unwritten rule that JS must be able to run on every surface in existence.
We're not at a place where you can use this stuff in production, but in theory there's nothing preventing JS compiled to PHP from being viable.
One interesting use case might be allowing some user-generated scripting (think plugins) to run in a sandboxed environment on your PHP platform. User-generated JS can be safely compiled to PHP because none of the usual [dangerous] PHP features are exposed to JS land (such as disk/network access). Actually, you can choose a carefully defined set of functions to expose to JS.
Sure, you'll take a performance hit at runtime, but let's face it, PHP apps haven't exactly set the performance bar too high (at the time of writing a default WP install runs 27 SQL queries to render a single page). Your code is likely not CPU bound anyway.
That being said, performance has not been a core goal of this library, the focus has been on correctnes. I'm sure there's an abundence of opportunity to perf-optimize this project.
The core language constructs, classes and methods are mostly implemented and we have decent test coverage. I'm working on an opt-in module system to interface with request/response and file-system. Database access, HTTP client, crypto and other modules to follow. Specific modules can be specified at compile time; by default js2php will only allow access to the outside world via console.log()
and process.exit()
so the generated PHP is completely safe.
Feel free to contribute if this interests you.
Install from GitHub:
git clone git@github.com:sstur/js2php.git
cd js2php
npm install
Install from npm:
npm install -g @sstur/js2php
When you install from npm using the -g
flag, you can run it from any directory by simply calling js2php
rather than calling node path/to/js2php
. The rest of the examples in this readme will call it this way.
Compile and run a simple example:
echo 'var x = "world"; console.log("hi " + x)' | js2php --quiet | php
or, a more verbose example:
echo "var a = 1; console.log(a + 1)" > example.js
js2php example.js > example.php
php example.php
We're using the awesome esprima JavaScript parser with rocambole to walk the AST and escope to figure out variable scope, hoist function declarations and so on. After AST manipulation tools/codegen.js
generates the PHP code by walking the tree.
Various constructs get wrapped in helper functions, for instance, property access, method calls and +
operator. The runtime helpers can be found in php/helpers
and there are a bunch of classes in php/classes
for Array, RegExp and such. All this PHP gets packaged into your output file, or you can save it to a standalone runtime and reference that from your output file like so:
js2php --runtime-only > runtime.php
js2php --runtime runtime.php example.js > example.php
You can also specify the output file using -o
or --out
and you can compile multiple input files into one output file like so:
js2php -o example.php file1.js file2.js
Have a play with the online demo. The generated code will look something like this:
<?php
$HelloWorld = new Func("HelloWorld", function($greeting = null) {
$this_ = Func::getContext();
set($this_, "greeting", $greeting);
});
set(get($HelloWorld, "prototype"), "greet", new Func(function($subject = null) use (&$console) {
$this_ = Func::getContext();
call_method($console, "log", get($this_, "greeting"), $subject);
}));
call_method(_new($HelloWorld, "Hi"), "greet", "world");
It's not particularly elegant, but it's human-readable and has all the basics we need to implement standards-compliant JS in PHP.
There are a handful of other projects worth noting. Haxe is probably the most popular and is a solid statically-typed language which compiles to PHP (among others).
Note: The Following is probably a very outdated list.
gutscript and Mammouth are both syntactically similar to CoffeeScript, Pharen is a Lisp implementation and Pratphall uses TypeScript syntax. There's also another project with the same name as this which is similar at the parsing level, but significantly different in execution. It accepts JS syntax but otherwise behaves like PHP.
Run npm test
. Requires PHP 5.3+ or HHVM.
Copyright (c) 2014, sstur@me.com. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.