"Will write code that writes code that writes code that writes code for money."
-- Anonymous on comp.lang.lisp
PHP.rb
translates Ruby code into PHP code by obtaining the parse
tree for a Ruby expression, transforming that into an abstract
syntax tree (AST) compatible with PHP, and then generating valid PHP
code as the final output.
require 'php'
PHP.generate
returns the translated AST for a given Ruby block. The AST
can be turned into runnable PHP code by calling the #to_s
method on the
resulting PHP::Program
instance.
PHP.generate { echo "Hello, world!\n" } #=> PHP::Program(...)
PHP.eval
translates Ruby code into PHP utilizing PHP.generate
and then
executes it using the php
executable (which must be available in
ENV['PATH']
).
PHP.eval { echo "Hello, world!\n" }
PHP.version
utilizes PHP.eval
to obtain the currently available PHP
version (if any).
PHP.version #=> "5.3.1"
The following snippets demonstrate the PHP output generated by PHP.rb
for
the given Ruby code. Look in the doc/examples/
directory for
runnable Ruby scripts containing many of these examples.
def unid
return md5(uniqid(mt_rand, true))
end
<?php
function unid() {
return md5(uniqid(mt_rand(), TRUE));
}
$url = "#{$scheme}://#{$host}:#{$port}" << $path
<?php
$url = $scheme . "://" . $host . ":" . $port . $path;
for $fruit in ['apple', 'banana', 'cranberry']
echo "#{$fruit}\n"
end
<?php
foreach (array("apple", "banana", "cranberry") as $fruit) {
echo($fruit . "\n");
}
for $key, $value in {'a' => 1, 'b' => 2, 'c' => 3}
echo "#{$key} => #{$value}\n"
end
<?php
foreach (array("a" => 1, "b" => 2, "c" => 3) as $key => $value) {
echo($key . " => " . $value . "\n");
}
$result = mysql_query("SELECT name FROM user")
while $row = mysql_fetch_assoc($result)
echo "User.name = #{$row['name']}\n"
end
<?php
$result = mysql_query("SELECT name FROM user");
while ($row = mysql_fetch_assoc($result)) {
echo("User.name = " . $row["name"] . "\n");
}
The following cheat sheet demonstrates the PHP output generated for various
types of Ruby expressions. The rows marked with an asterisk, (*)
, may have
special semantics that need to be taken into account.
Ruby input | PHP output
-------------------------------------|--------------------------------------
nil | NULL
false | FALSE
true | TRUE
42 | 42
3.1415 | 3.1415
"Hello, world!" | "Hello, world!"
"<#{$url}>" | "<" . $url . ">"
/a-z/ | '/a-z/'
(1..10) | range(1, 10)
(1...10) | range(1, 9)
[] | array()
[1, 2, 3] | array(1, 2, 3)
{} | array()
{"a" => 1, "b" => 2, "c" => 3} | array("a" => 1, "b" => 2, "c" => 3)
Ruby input | PHP output
-------------------------------------|--------------------------------------
$foo | $foo
$foo = 123 | $foo = 123
Ruby input | PHP output
-------------------------------------|--------------------------------------
lambda { |$x, $y| } | function($x, $y) {}
def foo(x, y); end | function foo($x, $y) {}
time | time()
time() | time()
Ruby input | PHP output
-------------------------------------|--------------------------------------
$array[$index] | $array[$index]
$object[:property] | $object->property (*)
$object.method | $object->method()
Ruby input | PHP output
-------------------------------------|--------------------------------------
$a << $b | $a . $b (*)
Ruby input | PHP output
-------------------------------------|--------------------------------------
-$a | -$a
$a + $b | $a + $b
$a - $b | $a - $b
$a * $b | $a * $b
$a / $b | $a / $b
$a % $b | $a % $b
Ruby input | PHP output
-------------------------------------|--------------------------------------
$a = $b | $a = $b
Ruby input | PHP output
-------------------------------------|--------------------------------------
~$a | ~$a
$a & $b | $a & $b
$a | $b | $a | $b
$a ^ $b | $a ^ $b
Ruby input | PHP output
-------------------------------------|--------------------------------------
$a == $b | $a == $b
$a === $b | $a === $b (*)
$a != $b | $a != $b
$a < $b | $a < $b
$a > $b | $a > $b
$a <= $b | $a <= $b
$a >= $b | $a >= $b
Ruby input | PHP output
-------------------------------------|--------------------------------------
`hostname` | `hostname`
Ruby input | PHP output
-------------------------------------|--------------------------------------
!$a | !$a
$a and $b | $a && $b
$a && $b | $a && $b
$a or $b | $a || $b
$a || $b | $a || $b
Ruby input | PHP output
-------------------------------------|--------------------------------------
... if true | if (TRUE) { ... }
if true then ... else ... end | if (TRUE) { ... } else { ... }
... unless true | if (!TRUE) { ... }
unless true then ... else ... end | if (!TRUE) { ... } else { ... }
while $x; ...; end | while ($x) { ... }
until $x; ...; end | while (!$x) { ... }
for $x in $y; ...; end | foreach ($y as $x) { ... }
for $k, $v in $z; ...; end | foreach ($z as $k => $v) { ... }
return | return
return $x | return $x
Ruby input | PHP output
-------------------------------------|--------------------------------------
MyClass.new | new MyClass
MyClass.new($options) | new MyClass($options)
MyClass.new("abc" => 123) | new MyClass(array("abc" => 123))
Ruby input | PHP output
-------------------------------------|--------------------------------------
/^\d+$/ =~ "123" | preg_match('/^\d+$/', "123")
/^\d+$/ !~ "123" | !preg_match('/^\d+$/', "123")
"123" =~ /^\d+$/ | preg_match('/^\d+$/', "123")
"123" !~ /^\d+$/ | !preg_match('/^\d+$/', "123")
$pattern =~ $string | preg_match($pattern, $string)
$pattern !~ $string | !preg_match($pattern, $string)
PHP.rb
is not Ruby for PHP, merely PHP for Ruby.
You don't have the Ruby standard library available in your generated code.
To generate runnable PHP code, you can't expect e.g. "foobar".size
to
work, but must rather say strlen("foobar")
.
Ruby method calls, e.g. $user.name
, are in principle ambiguous when
translated into PHP, because they could resolve into either a property
access as in $user->name
or a method call as in $user->name()
.
Therefore PHP.rb
defines $user.name
to be equivalent to the latter (the
method call), and defines the syntax $user[:name]
to be equivalent to the
former (the property access).
Note that this does not conflict with array subscript access since Ruby symbol objects have no semantic equivalent in PHP.
- {PHP.eval}
- {PHP.exec}
- {PHP.dump}
- {PHP.generate}
- {PHP.version}
- {PHP::Generator}
- {PHP::Program}
- {PHP::Expression}
- Open4 (>= 1.0.1)
- ParseTree (>= 3.0.4)
- RubyParser (>= 2.0.4)
- SexpProcessor (>= 3.0.3)
The recommended installation method is via RubyGems. To install the latest official release from Gemcutter, do:
% [sudo] gem install php
To get a local working copy of the development repository, do:
% git clone git://github.com/bendiken/php.git
Alternatively, you can download the latest development version as a tarball as follows:
% wget http://github.com/bendiken/php/tarball/master
- http://php.rubyforge.org/
- http://github.com/bendiken/php
- http://gemcutter.org/gems/php
- http://rubyforge.org/projects/php/
- http://raa.ruby-lang.org/project/php/
PHP.rb
is free and unencumbered public domain software. For more
information, see http://unlicense.org/ or the accompanying UNLICENSE file.