Skip to content

Commit 8c3cdbe

Browse files
committed
Update README and CHANGELOG.
1 parent f2e5b5e commit 8c3cdbe

File tree

2 files changed

+154
-13
lines changed

2 files changed

+154
-13
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
11
# php-embed x.x.x (not yet released)
2+
* Support server variables, headers, and query string
3+
processing to allow using the embedded PHP to process http
4+
requests from node's http server.
5+
* Support passing "command-line arguments" to allow the embedded PHP
6+
to execute scripts using PHP's CLI interface.
7+
* Allow PHP to invoke asynchronous JavaScript functions synchronously
8+
by passing a `Js\Wait` object where the callback would go. This
9+
blocks the PHP event loop (naturally) but not the JavaScript one.
10+
This is used internally to implement PHP requests to flush the
11+
output stream.
12+
* Wrap PHP objects (but not yet arrays) for use within Node.
13+
Property access is implemented; method invocation is not yet
14+
implemented.
15+
* Rework message passing to allow two-way communication between JS
16+
and PHP. Both JS and PHP have event loops now, and both can do
17+
asynchronous method calls (but at the moment most calls are
18+
synchronous).
19+
* Aggressively lint the C++ and JS code bases.
220

321
# php-embed 0.0.2 (2015-10-21)
422
* Add synchronous PHP access to JavaScript variables, functions, and

README.md

Lines changed: 136 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Node/iojs >= 2.4.0 is currently required, since we use `NativeWeakMap`s
1010
in the implementation. This could probably be worked around using
1111
v8 hidden properties, but it doesn't seem worth it right now.
1212

13-
# USAGE
13+
# Usage
14+
15+
## Basic
1416

1517
```js
1618
var path = require('path');
@@ -23,6 +25,35 @@ php.request({
2325
});
2426
```
2527

28+
## Advanced
29+
30+
```js
31+
var php = require('php-embed');
32+
php.request({
33+
source: ['call_user_func(function() {',
34+
' class Foo {',
35+
' var $bar = "bar";',
36+
' }',
37+
' $c = $_SERVER["CONTEXT"];',
38+
' // Invoke an Async JS method',
39+
' $result = $c->jsfunc(new Foo, $c->jsvalue, new Js\\Wait);',
40+
' // And return the value back to JS.',
41+
' return $result;',
42+
'})'].join('\n'),
43+
context: {
44+
jsvalue: 42, // Pass JS values to PHP
45+
jsfunc: function(foo, value, cb) {
46+
// Access PHP object from JS
47+
console.log(foo.bar, value); // Prints "bar 42"
48+
// Asynchronous completion, doesn't block node event loop
49+
setTimeout(function() { cb(null, "done") }, 500);
50+
}
51+
}
52+
}).then(function(v) {
53+
console.log(v); // Prints "done" ($result from PHP)
54+
}).done();
55+
```
56+
2657
# API
2758

2859
## php.request(options, [callback])
@@ -33,15 +64,33 @@ parameter.
3364
* `options`: a hash containing various parameters for the request.
3465
Either `source` or `file` is mandatory; the rest are optional.
3566
- `source`:
36-
Specifies a source string to evaluate in the request context.
67+
Specifies a source string to evaluate *as an expression* in
68+
the request context. (If you want to evaluate a statement,
69+
you can wrap it in `call_user_func(function () { ... })`.)
3770
- `file`:
3871
Specifies a PHP file to evaluate in the request context.
3972
- `stream`:
40-
A node `stream.Writable` to accept output from the PHP request.
41-
If not specified, defaults to `process.stdout`.
73+
A node `stream.Writable` to accept output from the PHP
74+
request. If not specified, defaults to `process.stdout`.
75+
- `request`:
76+
If an `http.IncomingMessage` is provided here, the PHP
77+
server variables will be set up with information about
78+
the request.
79+
- `args`:
80+
If an array with at least one element is provided, the
81+
PHP `$argc` and `$argv` variables will be set up as
82+
PHP CLI programs expect. Note that `args[0]` should
83+
be the "script file name", as in C convention.
4284
- `context`:
4385
A JavaScript object which will be made available to the PHP
4486
request in `$_SERVER['CONTEXT']`.
87+
- `serverInitFunc`:
88+
The user can provide a JavaScript function which will
89+
be passed an object containing values for the PHP
90+
[`$_SERVER`](http://php.net/manual/en/reserved.variables.server.php)
91+
variable, such as `REQUEST_URI`, `SERVER_ADMIN`, etc.
92+
You can add or override values in this function as needed
93+
to set up your request.
4594
* `callback` *(optional)*: A standard node callback. The first argument
4695
is non-null if an exception was raised. The second argument is the
4796
result of the PHP evaluation, converted to a string.
@@ -102,7 +151,63 @@ of reading the file.
102151
Note that calls using `Js\Wait` block the PHP thread but do not
103152
block the node thread.
104153

105-
# INSTALLING
154+
# Javascript API
155+
156+
The JavaScript `in` operator, when applied to a wrapped PHP object,
157+
works the same as the PHP `isset()` function. Similarly, when applied
158+
to a wrapped PHP object, JavaScript `delete` works like PHP `unset`.
159+
160+
```js
161+
var php = require('php-embed');
162+
php.request({
163+
source: 'call_user_func(function() {' +
164+
' class Foo { var $bar = null; var $bat = 42; } ' +
165+
' $_SERVER["CONTEXT"](new Foo()); ' +
166+
'})',
167+
context: function(foo) {
168+
console.log("bar" in foo ? "yes" : "no"); // This prints "no"
169+
console.log("bat" in foo ? "yes" : "no"); // This prints "yes"
170+
}
171+
}).done();
172+
```
173+
174+
PHP has separate namespaces for properties and methods, while JavaScript
175+
has just one. Usually this isn't an issue, but if you need to you can use
176+
a leading `$` to specify a property, or `__call` to specifically invoke a
177+
method.
178+
179+
```js
180+
var php = require('php-embed');
181+
php.request({
182+
source: ['call_user_func(function() {',
183+
' class Foo {',
184+
' var $bar = "bar";',
185+
' function bar($what) { echo "I am a ", $what, "!\n"; }',
186+
' }',
187+
' $foo = new Foo;',
188+
' // This prints "bar"',
189+
' echo $foo->bar, "\n";',
190+
' // This prints "I am a function!"',
191+
' $foo->bar("function");',
192+
' // Now try it in JavaScript',
193+
' $_SERVER["CONTEXT"]($foo);',
194+
'})'].join('\n'),
195+
context: function(foo) {
196+
// This prints "bar"
197+
console.log(foo.$bar);
198+
// This prints "I am a function"
199+
foo.__call("bar", "function");
200+
}
201+
}).done();
202+
```
203+
204+
At the moment, all property accesses and method invocations from
205+
JavaScript to PHP are done synchronously; that is, they block the
206+
JavaScript event loop. The mechanisms are in place for asynchronous
207+
access; I just haven't quite figured out what the syntax for that
208+
should look like.
209+
210+
# Installing
106211

107212
You can use [`npm`](https://github.com/isaacs/npm) to download and install:
108213

@@ -117,7 +222,7 @@ version of `node-gyp`, and thus your system must meet
117222
It is also possible to make your own build of `php-embed` from its
118223
source instead of its npm package ([see below](#building-from-the-source)).
119224

120-
# BUILDING FROM THE SOURCE
225+
# Building from source
121226

122227
Unless building via `npm install` you will need `node-pre-gyp`
123228
installed globally:
@@ -149,23 +254,41 @@ Developers hacking on the code will probably want to use:
149254

150255
Passing the `--debug` flag to `node-pre-gyp` enables memory checking, and
151256
the `build` command (instead of `rebuild`) avoids rebuilding `libphp5`
152-
from scratch after every change.
257+
from scratch after every change. (You can also use `npm run
258+
debug-build` if you find that easier to remember.)
153259

154-
# TESTING
260+
# Testing
155261

156-
[mocha](https://github.com/visionmedia/mocha) is required to run unit tests.
262+
To run the test suite, use:
157263

158-
npm install mocha
159264
npm test
160265

266+
This will run the JavaScript and C++ linters, as well as a test suite
267+
using [mocha](https://github.com/visionmedia/mocha).
268+
269+
During development, `npm run jscs-fix` will automatically correct most
270+
JavaScript code style issues, and `npm run valgrind` will detect a
271+
large number of potential memory issues. Note that node itself will
272+
leak a small amount of memory from `node::CreateEnvironment`,
273+
`node::cares_wrap::Initialize`, and `node::Start`; these can safely be
274+
ignored in the `valgrind` report.
161275

162-
# CONTRIBUTORS
276+
# Contributors
163277

164278
* [C. Scott Ananian](https://github.com/cscott)
165279

166-
# RELATED PROJECTS
280+
# Related projects
281+
282+
* [`node-mediawiki-express`](https://github.com/cscott/node-mediawiki-express)
283+
uses `php-embed` to run mediawiki inside a node.js express server.
284+
* [`v8js`](https://github.com/preillyme/v8js) is a "mirror image"
285+
project: it embeds the v8 JavaScript engine inside of PHP, whereas
286+
`php-embed` embeds PHP inside node/v8. The author of `php-embed`
287+
is a contributor to `v8js` and they share bits of code. The
288+
JavaScript API to access PHP objects is deliberately similar
289+
to that used by `v8js`.
167290

168-
# LICENSE
291+
# License
169292
Copyright (c) 2015 C. Scott Ananian.
170293

171294
`node-php-embed` is licensed using the same

0 commit comments

Comments
 (0)