php.js
php.js is an open source project that brings high-level PHP functions
to low-level JavaScript platforms such as web browsers, browser extensions (
Mozilla/Firefox,
Chrome
), AIR,
and SSJS
engines like
V8 (
node.js,
v8cgi
), Rhino, and
SpiderMonkey (
CouchDB
)
If you want to perform high-level operations on these platforms,
you probably need to write JS that combines its lower-level functions and
build it up until you have something useful like:
strip_tags(), strtotime(), number_format(), wordwrap().
That's what we are doing for you.
No server component required. To use php.js you can either:
- Copy-Paste one of our Functions :)
- Clone our git repo and include only the functions you need in your webpages
- Customize & download a package (only select what you need)
- Download the default package (big--use for study only)
PHP is a language with many high-level functions and while they're not always implemented as consistently as we'd like (mostly to blame on its underlying C parts), it has a huge following familiar with its syntax so it makes sense to pick its API as a reference. Eliminating the need for our own documentation, thus making life easier, we hope.
We recognize JS - on the other hand - has beautiful language
features, and we encourage you to
learn them.
Never let php.js be an excuse not to.
For the same reason, we're not porting entire language or control structures of PHP;
we stick with the functions.
Featured Functions
date()
Date-formatting, just like you know it from PHP
base64_decode()
Safe & easy data transport, decode messages in JavaScript that were encoded by PHP.
The History of php.js
Kevin van Zonneveld was once working as devloper on a project with a lot of client(JS) /
server(PHP) interaction, and found himself coding PHP functions (like base64_decode &
urldecode) in JavaScript to smoothen communication between the two languages.
He stored the stored the functions in a file called php.js which was included in the
project. But even when the project was done, it remained fun trying to port PHP functions
to JavaScript, and so the library grew.
There was a technological challenge in trying to recreate functions such as
date, or sprintf.
Eventually Kevin decided to share the little library on his blog, triggering the enthusiasm
of a lot of PHP developers longing for PHP functionality in JavaScript. The project was
open sourced in 2008, and many people contributed their own functions in the comments sections
of Kevin's blog.
It was decided that the library deserved a bigger home and a face of its own, and so
the php.js core team (which at that time consisted of Michael White, Felix Geisendörfer,
Philip Peterson and Kevin) developed the phpjs.org website.
Different core members have come & gone but there has always been a select group pushing
the project forward.
Late 2008
Brett Zamir started
contributing and did't stop. In April 2009 he was responsible for over 245
different PHP functions and has had many ideas considering php.js' future.
Because the library became too big to include at once, and having users copy-paste
functions to their projects was nothing short of creating a maintenance hell,
Kevin started working on a
compiler tool that
allows programmers to select ONLY the functions they need, and wrap them
up in a single php.js file.
This took away overhead and even allowed for easy upgrading.
In september 2009 we moved the development of the project to GitHub.
This opened up a lot of features to help colaboration in development.
And that's where we are now.
We are still trying to port and perfect more & more functions.
Want to help out & become a part of php.js history? Why not add a comment with
new or better code? Its that easy.
Comments
@ Dino B.: Placing it on a CDN would encourage the use of the default package in production. While in fact we are trying to stimulate people to use only the functions they need. Either by compiling, or just copy-pasting some of our functions.
Please never hotlink GitHub's raw sources. As you can achieve the same thing (only without using up their bandwidth) by doing:
$ cd /my/web/app/webroot/js/
$ git clone git://github.com/kvz/phpjs.git
from now, to update phpjs, you can do a:
$ cd /my/web/app/webroot/js/phpjs; git pull;
and to use functions you can include:
/js/phpjs/functions/array/is_array.js
/js/phpjs/functions/datetime/strtotime.js
in your webpages.
Is there a consideration to place this library on a CDN somewhere? Secondly, is hotlinking to the functions (their github locations) encouraged, prohibited, or a gray area?
I added the test files (converted to JavaScript) at http://github.com/kvz/phpjs/tree/master/_workbench/tokenizer/tokenizer_tests/ . Some of them need php.js functions added and there may be some imperfections in the PHP-to-JS conversion process (I corrected some of them that Harmony Framework missed, though it seemed to do a pretty good job). We'll also need to consider the best way to parse the test files, run the JavaScript, and test against the expected results...
@Marco: I'm sorry if I get carried away sometimes; sorry for too much information; I forget who I've talked to about these things. And don't be afraid to ask questions for anything.
Yes, I went back to your constant values; that's good we use the latest.
I agree finishing token_get_all() and testing it is a good idea; I just started the php-to-js code for fun and to test the concept a little.
As far as testing, that is exactly what we can use the "phpt" files are for. They are test files in the PHP source code. They are written in PHP (though with some blocks indicating what is being tested, what the result is expected to be, etc.) and my idea was to use a PHP-to-JavaScript converter so we could use those tests against all of our functions. These tests for token_get_all can be found in the PHP source code at /ext/tokenizer/tests/ . Again, until we have our own converter, we can try http://www.harmony-framework.com/ for converting those "phpt" files into JavaScript.
@Brett: You must clarify me something, remember that i'm new to this project, i've no experience in community work (and related tools such as Github), i'm italian and i speak a medium-level english and right now i'm tired so be patient:).
You talk about ".phpt" files where can i find them and what do you mean by adapting them to Javascript form?
For the Php parser i think we should finish to fix the token_get_all with lots of tests, improve its performance, create some guidelines about the implementation of the parser and then build it on the token extension.
@Brett: You are doing a very good work.
I get the constants value from PHP 5.3 so i think that when the function will be released you must change their value according to the last version of PHP.
For the \r\n problem i agree with you to make the \r optional, i forgot that it's present only on Windows.
Right now i'm very busy at work, but when i'll finish (i hope soon) i'll be glad to help you with everything.
@Marco: As I think I may have mentioned before, I have modified your functions to follow our coding standards and also support IE since you cannot do str[3] in IE--string characters can only be accessed by str.charAt(3). (Annoying, but true.)
I believe I also fixed a problem with one of your variables not being declared and thus global.
I also added a HEREDOC test. There was some work to be done with HEREDOC handling but that is now fixed, so again, please apply my changes first before you work on the code again: http://github.com/kvz/phpjs/tree/master/_workbench/tokenizer .
I also renamed token.js to token_get_all.js and renamed what I think used to be "test.min.js" to a more descriptive "file_get_contents.min.js".
As far as \r\n, shouldn't such checks be \r?\n since \r is only Windows? I made the \r optional.
Also, I needed to temporarily add different values for the constants to compare on my system (5.2.6) which uses different numeric values for the constants... What version of PHP are you using? 5.3 or 6? I've kept my own values in the comments but just now reverted to your values since it appears you are using a later edition of PHP.
I also added some additional test files, and supplemented your test with var_export(), but I really think we need to have a greater interaction between PHP and JS to summarize in a line exactly what differed between the PHP version and the JS version (with maybe the PHP producing the value which JS checks against its own).
I'd also really like to adapt all of the ".phpt" test files in the PHP source to make sure token_get_all.js is parsing PHP perfectly. I think this is a very important function you've made, so I hope we can prove to ourselves and others that this is really robust.
Also, I added a feature to token_get_all.js so that if the user has "this.php_js.phpParser" defined (though maybe I should make it settable via this.php_js.ini so that people can use ini_set() instead), that object's methods will be called with arguments indicating information about each segment currently being parsed (they'll also need token_name.js in such a case; see http://github.com/kvz/phpjs/tree/master/_experimental/tokenizer ). Although someone can do this with the return results of token_get_all(), it will be faster (and live) to work during the original parsing. And I only need to add a couple of lines of code to get this functionality.
See PHPTokenizer.js for a skeleton object that can be used as the "this.php_js.phpParser" and see PHPToJS.js for an early beginning at a PHP-to-JavaScript translator which can also be used as an example of such a parser object. We might also get some ideas if not code from the Harmony Framework (at http://www.harmony-framework.com/ ) about how to finish making such a translator.
I am a little busy to work on this now, but would you be interested in adapting the ".phpt" files into JavaScript form to make sure all of the tests are working? It'd be great to be able to run the tests, and if not showing a diff, at least just summarizing which line is failing and how many lines in the test are failing. Normally for other functions, I think it'd already be ready for release, but I think this one is of the nature that it really should be fully systematically tested first. Then, we can maybe use it to convert other ".phpt" files into JavaScript! :) Or we could just use Harmony Framework for now, though phpt files also have some non-JS blocks we'd need to parse as well...
Anyhow, some really incredible work, thank you again!!!
@Marco, I did receive your original email, so no need to send it again. Again, please see http://github.com/kvz/phpjs/raw/master/_workbench/tokenizer/ as I have made modifications of your code there to follow our standards. I'd appreciate it if you could use those versions if you make any further changes. This seems like some extremely impressive work, but I'd like to study it more carefully and maybe compare it to the EBNF out there, etc.
@Brett: i did not receive your email, if you want to try again i will send you back the test suite that i've builded. Anyway to create this function i haven't looked at any source, i've tested it with a lot of scripts untill i've solved every bug. I've tested the result of the original php function, on a 200kb script, with the one returned by the js function and the result was exactly the same. The only functionality that i haven't tested is the HEREDOC.
@Brett: i did not receive your email, if you want to try again i will send you back the test suite that i've builded. Anyway to create this function i haven't looked at any source, i've tested it with a lot of scripts untill i've solved every bug. I've tested the result of the original php function (on a 200kb script) with the one returned by the js function and the result was exactly the same. The only functionality that i haven't tested is the HEREDOC.
@Marco: Actually, please see http://github.com/kvz/phpjs/raw/master/_workbench/tokenizer/token_get_all.js for the latest of your function instead
@Marco: I sent you an email in reply a few days ago. I haven't gotten any reply to it.
FYI, just now I made more changes to bring your token.js (now changed to token_get_all.js and available at http://github.com/kvz/phpjs/raw/fdecb6087c5843e498a63b4e96ae5b6c063e2624/_workbench/tokenizer/token_get_all.js ) more up to our coding standards (see http://wiki.github.com/kvz/phpjs/developerguidelines ) and I also caught a few bugs, now fixed. But I still haven't taken a good look at the code.
Out of curiosity, how did you write this code? Did you look at the C source, use someone's EBNF, or what?
Please see lines 513, 642, 691 for whether those are accidental assignments or not. As maybe the most important coding standard, please don't do inline assignments, as it is unclear whether it is deliberate or not; assign the variable in a separate line.
@LEx: Yes, that is a possibility, but there are a couple of reasons we don't take that approach:
1) Adding methods to the built-in object's prototypes can conflict with other libraries or code, adding a kind of omni-global. The problems can occur if other libraries try to add functions of the same name to the prototype, or, more insidiously, cause problems for those iterating over such object (or array, etc.) properties. Yes, when iterating over object properties, the user should always filter out functions or ignore properties which are on the prototype, but many people (and libraries--including many of the functions still in our library) do not do this filtering, either because they don't know about the need for it, or because they don't want to use libraries that intrude in this way. See http://www.jslint.com/lint.html#forin or http://javascript.crockford.com/code.html#for%20statement
2) We also want to make at least one version familiar and easy to PHP developers, though that doesn't prevent us from making other versions like the namespaced version, but it could add some difficulty to maintenance.
One way around this might be to use our own wrappers for things like arrays.
For example, we might change our function array() (different from the built-in JavaScript Array() object) so that when someone does:
1 | var a = array(); |
they can also use:
1 | a.in_array(...) |
Implementing object-style versions that didn't add to the built-in prototypes might work, even though they would require things like strings to also have wrappers created for them, thus not being as convenient, and, even with this, there is still the problem of iterating properties.
And we could have a version for users who didn't care about problems from adding to the native object's prototypes.
Either of these would definitely change the regular PHP API as the input argument would be removed, but other users could still use the regular version if they wished.
One other potential advantage of the wrapper approach would be that other chaining methods could exist, for example, functions that don't return arrays could be combined with those that do into a long chain:
1 | arr.returnArrays().shift(...).map(...).push(...); |
As I recall Kevin isn't interested in making such a version part of the regular compiler, but we could host alternative versions if someone is interested in maintaining them or writing code to automate conversions on the server side.
Why you dont use prototype to inherit and expand native Javascript object like Array, Date or String. It wouldnt be better to use [1,2,3].in_array(1) rather than in_array(1,[1,2,3])? Javascritp is prototype based language. In other hand it can downgrade performance... but still why dont use this approach?
@Marco: Sorry for the delayed reply... Have you seen http://www.php.net/manual/en/tokens.php and also the comments there? There's some reference to whitespace as a tokens...
Hi, i'm trying to create the token_get_all function and i need help on a little problem.
Do you know when whitespaces (\t,\n,\r and spaces) are considrered tokens?
The orignal PHP function get only some of them but i can't understand which ones.
@cynosure: Hi! Don't mean to be unfriendly, but I imagine Kevin would prefer we limit discussion here to php.js functions. But really quickly, it appears that IE may be (mistakenly) considering the XML Declaration at the beginning of the document as though it were a node (probably considering it a processing instruction which it is not, even though it looks like one)--the declaration info should only be available to the DOM as document.xmlVersion, document.xmlEncoding and document.xmlStandalone , though browser support is unfortunately limited even in Firefox; see http://brettz9.blogspot.com/2009/04/xml-dom-support-test.html ). Thankfully, you can still make cross-browser code here in testing whether the nodeName of a "processing instruction" is "xml"; since processing instructions cannot be "xml", you would know it is the bogus IE one and can be avoided.
You could confirm IE indeed treats it this way by printing out the nodeType as well; see https://developer.mozilla.org/en/nodeType for the codes. Also, your example is not recursive, as if it were, you would also need to check whether the node were an element and then recurse on its children; currently you are only iterating through the top level nodes. Maybe this was a simplified example...
Hi!
I'm working now on an xml parser (not yet on a php type XML API object), but I fount a new funny difference between IE6-8 and any other browsers.
I have a simple XML:
1
2
3
4
56
7
8
| <?xml version="1.0" encoding="UTF-8"?> <main> <response> <age>6</age> </response> <redirect> </redirect> </main> |
When I try to loop the elements in a recursive way, the code above works different in these browsers:
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 | xml2Array = function(xml) { var nodecount = xml.childNodes.length; if(nodecount > 0) { var log = ''; var arr = new Array(); for(var i=0;i<nodecount;i++) { log = log + i + ' -> ' + xml.childNodes[i].nodeName + ''; } document.getElementById('foo').innerHTML = log; } else { var arr = false; } return arr; } |
In IE writes out:
0 -> xml
1 -> main
In other browsers:
0 -> main
Interesting about the delete operator. I knew it didn't work with variables, and imagined it wouldn't work on some built-in objects, but nice to know that formally.
Nice set of examples. It's supposed to get even weirder in IE as far as ordering if you use an object and with properties inherited from the prototype. It's sad that what may be the most usable scripting if not programming language in the world is the least updated. I can live with most of JavaScript's other quirks, even the ease of making accidental globals, but this one should plain and simply just be fixed in the spec and reality.
Interesting about the delete operator. I knew it didn't work with variables, and imagined it wouldn't work on some built-in objects, but nice to know that formally.
Nice set of examples. It's supposed to get even weirder in IE as far as ordering if you use an object and with properties inherited from the prototype. It's sad that what may be the most usable scripting if not programming language in the world is the least updated. I can live with most of JavaScript's other quirks, even the ease of making accidental globals, but this one should plain and simply just be fixed in the spec and reality.
@Brett Zamir: The delete method have an other issue, it can't remove an element if it have a DontDelete attribute.
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator
In the other hand, associative arrays works in IE6 too, but this is not really an array, this is an object, so .splice won't work in any browsers:
1 2 3 4 56 7 8 9 1011 12 13 14 1516 | var foobar = new Array(); foobar['x'] = 'a'; foobar['y'] = 'b'; alert(foobar['x'] + ' ' + foobar['y']); // writes "a b" // and the problems:alert(foobar.splice('x',1)); // does nothing, writes empty window alert(foobar.splice(0,1)); // does nothing too alert(foobar['x'] + ' ' + foobar['y']); // writes "a b" again // with delete: delete foobar['x'];alert(foobar['x'] + ' ' + foobar['y']); // writes "undefined b" for(var key in foobar) { alert(key); } // writes "y" // let's test the element orders foobar['x'] = 'c'; alert(foobar['x'] + ' ' + foobar['y']); // writes "c b", its okfor(var key in foobar) { alert(key); } // writes "x" and "y" in IE6-8, "y" and "x" in all other browsers |
I know, this is exactly what you wrote, I only made a test to everyone who wants to know how it works.
@cynosure: Looks like someone else here tried something similar: http://phpjs.org/functions/array_pop:329#comment_354 .
As far as a reference to an array, whatever value you pass in to a function, if it is an array or object, its elements can be acted on by reference and in fact only by reference unless you manually make a copy (though you cannot replace the whole object with something else, or that does make a copy). So, we could adapt your function to work by reference (though still breaking the PHP API which only uses one argument):
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 | function unset(array,index) { if (typeof array === 'object' && typeof array.length == 'number') { array.splice(index, 1); // Using the delete operator will replace the old value // with "undefined" in its old slot, but we also want to remove the slot itself, // so with arrays (in IE too), we can safely use splice(). } else { // Objects delete array[index]; // For object properties, this works pretty well, except potentially in IE where // the property will thankfully no longer be iterated, but it has the annoying feature (for // the sake of our using objects to imitate PHP associative arrays) that if you later try to // add back a value with the same property name, it will put your new value in the old // iteration position. So IE does not truly delete the property, though it may appear that way. // All other popular browser implementation seem to truly delete the property (and iterate // in order), at least if it is not an inherited property, but the latest ES spec wasn't able // to persuade IE to change this behavior } } |
See the 2nd comment above for the potential problems with this though. Basically in IE, simple objects as associative arrays just won't work perfectly. It is very disappointing. You can get around this by creating an object which wraps your data, but that can get quite ugly. Otherwise, you just have to keep your keys in one array and values in another array.
This is not to speak of our other challenge here of trying to work with only one argument in unset(). JavaScript does not allow us to get the container object or array if we only know the property. Our experimental version of unset() (at http://github.com/kvz/phpjs/blob/master/_experimental/var/unset.js ), allows us to pass in a single argument, but it is a (necessarily) very bad solution as it relies on eval(), and only works on globals passed in as strings. That's a huge compromise just to work with a single argument, so practically speaking, your solution is probably better (though with the above-mentioned caveats).
A similar problem occurs with trying to imitate PHP's extract() and compact(). We don't have a way in JavaScript (unless we exclusively work with globals) to say use the arguments object to obtain or set the local variables of the caller (we can only get access to those variables explicitly passed in as arguments, and only by reference if they are objects or arrays).
I think these may well be the biggest challenges for php.js trying to follow the PHP API.
@cynosure: Looks like someone else here tried something similar: http://phpjs.org/functions/array_pop:329#comment_354 .
As far as a reference to an array, whatever value you pass in to a function, if it is an array or object, its elements can be acted on by reference and in fact only by reference unless you manually make a copy (though you cannot replace the whole object with something else, or that does make a copy). So, we could adapt your function to work by reference (though still breaking the PHP API which only uses one argument):
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 | function unset(array,index) { if (typeof array === 'object' && typeof array.length == 'number') { array.splice(index, 1); // Using the delete operator will replace the old value // with "undefined" in its old slot, but we also want to remove the slot itself, // so with arrays (in IE too), we can safely use splice(). } else { // Objects delete array[index]; // For object properties, this works pretty well, except potentially in IE where // the property will thankfully no longer be iterated, but it has the annoying feature (for // the sake of our using objects to imitate PHP associative arrays) that if you later try to // add back a value with the same property name, it will put your new value in the old // iteration position. So IE does not truly delete the property, though it may appear that way. // All other popular browser implementation seem to truly delete the property (and iterate // in order), at least if it is not an inherited property, but the latest ES spec wasn't able // to persuade IE to change this behavior } } |
See the 2nd comment above for the potential problems with this though. Basically in IE, simple objects as associative arrays just won't work perfectly. It is very disappointing. You can get around this by creating an object which wraps your data, but that can get quite ugly. Otherwise, you just have to keep your keys in one array and values in another array.
This is not to speak of our other challenge here of trying to work with only one argument in unset(). JavaScript does not allow us to get the container object or array if we only know the property. Our experimental version of unset() (at http://github.com/kvz/phpjs/blob/master/_experimental/var/unset.js ), allows us to pass in a single argument, but it is a (necessarily) very bad solution as it relies on eval(), and only works on globals passed in as strings. That's a huge compromise just to work with a single argument, so practically speaking, your solution is probably better (though with the above-mentioned caveats).
A similar problem occurs with trying to imitate PHP's extract() and compact(). We don't have a way in JavaScript (unless we exclusively work with globals) to say use the arguments object to obtain or set the local variables of the caller (we can only get access to those variables explicitly passed in as arguments, and only by reference if they are objects or arrays).
I think these may well be the biggest challenges for php.js trying to follow the PHP API.
@cynosure: Looks like someone else here tried something similar: http://phpjs.org/functions/array_pop:329#comment_354 .
As far as a reference to an array, whatever value you pass in to a function, if it is an array or object, its elements can be acted on by reference and in fact only by reference unless you manually make a copy (though you cannot replace the whole object with something else, or that does make a copy). So, we could adapt your function to work by reference (though still breaking the PHP API which only uses one argument):
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 | function unset(array,index) { if (typeof array === 'object' && typeof array.length == 'number') { array.splice(index, 1); // Using the delete operator will replace the old value // with "undefined" in its old slot, but we also want to remove the slot itself, // so with arrays (in IE too), we can safely use splice(). } else { // Objects delete array[index]; // For object properties, this works pretty well, except potentially in IE where // the property will thankfully no longer be iterated, but it has the annoying feature (for // the sake of our using objects to imitate PHP associative arrays) that if you later try to // add back a value with the same property name, it will put your new value in the old // iteration position. So IE does not truly delete the property, though it may appear that way. // All other popular browser implementation seem to truly delete the property (and iterate // in order), at least if it is not an inherited property, but the latest ES spec wasn't able // to persuade IE to change this behavior } } |
See the 2nd comment above for the potential problems with this though. Basically in IE, simple objects as associative arrays just won't work perfectly. It is very disappointing. You can get around this by creating an object which wraps your data, but that can get quite ugly. Otherwise, you just have to keep your keys in one array and values in another array.
This is not to speak of our other challenge here of trying to work with only one argument in unset(). JavaScript does not allow us to get the container object or array if we only know the property. Our experimental version of unset() (at http://github.com/kvz/phpjs/blob/master/_experimental/var/unset.js ), allows us to pass in a single argument, but it is a (necessarily) very bad solution as it relies on eval(), and only works on globals passed in as strings. That's a huge compromise just to work with a single argument, so practically speaking, your solution is probably better (though with the above-mentioned caveats).
A similar problem occurs with trying to imitate PHP's extract() and compact(). We don't have a way in JavaScript (unless we exclusively work with globals) to say use the arguments object to obtain or set the local variables of the caller (we can only get access to those variables explicitly passed in as arguments, and only by reference if they are objects or arrays).
I think these may well be the biggest challenges for php.js trying to follow the PHP API.
@cynosure: Looks like someone else here tried something similar: http://phpjs.org/functions/array_pop:329#comment_354 .
As far as a reference to an array, whatever value you pass in to a function, if it is an array or object, its elements can be acted on by reference and in fact only by reference unless you manually make a copy (though you cannot replace the whole object with something else, or that does make a copy). So, we could adapt your function to work by reference (though still breaking the PHP API which only uses one argument):
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 | function unset(array,index) { if (typeof array === 'object' && typeof array.length !== 'undefined') { array.splice(index, 1); // Using the delete operator will replace the old value // with "undefined" in its old slot, but we also want to remove the slot itself, // so with arrays (in IE too), we can safely use splice(). } else { // Objects delete array[index]; // For object properties, this works pretty well, except potentially in IE where // the property will thankfully no longer be iterated, but it has the annoying feature (for // the sake of our using objects to imitate PHP associative arrays) that if you later try to // add back a value with the same property name, it will put your new value in the old // iteration position. So IE does not truly delete the property, though it may appear that way. // All other popular browser implementation seem to truly delete the property (and iterate // in order), at least if it is not an inherited property, but the latest ES spec wasn't able // to persuade IE to change this behavior } } |
See the 2nd comment above for the potential problems with this though. Basically in IE, simple objects as associative arrays just won't work perfectly. It is very disappointing. You can get around this by creating an object which wraps your data, but that can get quite ugly. Otherwise, you just have to keep your keys in one array and values in another array.
This is not to speak of our other challenge here of trying to work with only one argument in unset(). JavaScript does not allow us to get the container object or array if we only know the property. Our experimental version of unset() (at http://github.com/kvz/phpjs/blob/master/_experimental/var/unset.js ), allows us to pass in a single argument, but it is a (necessarily) very bad solution as it relies on eval(), and only works on globals passed in as strings. That's a huge compromise just to work with a single argument, so practically speaking, your solution is probably better (though with the above-mentioned caveats).
A similar problem occurs with trying to imitate PHP's extract() and compact(). We don't have a way in JavaScript (unless we exclusively work with globals) to say use the arguments object to obtain or set the local variables of the caller (we can only get access to those variables explicitly passed in as arguments, and only by reference if they are objects or arrays).
I think these may well be the biggest challenges for php.js trying to follow the PHP API.
Hi!
In JS can you give a reference to an array in a function call? I need an unset() like function what can cut off an element from an array with a given index ( like unset(foo['bar']; )
My workaround is this:
1 2 3 4 56 7 8 9 1011 | function unset(array,index) { var newarr = new Array(); for(var i in array) { if(i != index) newarr[i] = array[i]; } return newarr;} |
I know this is not the exact way how php's unset works, 'cos it gives only a reference to the array, and handles single variables as well as multiple variables too, but I think this can be usefull for those JS beginners like me, who wants to unset an element from an array. The delete method is buggy for me, or I don't understand how it works well.
Thanks!
I misspoke in saying that the case in the switch is superfluous. It will indeed convert "\\0" to "\u0000" as in PHP. In any case, as I mentioned, you should add an extra '0' to the sequence (and don't add a backslash).
@Brant: Sorry, the case in the switch is not superfluous as it will turn "\\0" into "\u0000" (as does PHP in double or single quotes). In any case, the rest of what I said still applies: don't add a backslash to "\u", just add an extra 0 at the end.
@Brant: Thanks for letting us know. Fixed in Git. It really should be '\u0000' (was missing a zero), but it won't really make a difference either way because JavaScript already treats "\0" as "\u0000". So that case in the switch is superfluous (though I've kept it just to reflect what PHP does). FYI, "\u" is used to introduce a four-hexadecimal digit sequence in place of a Unicode character--esp. useful if you have to use non-printable characters or non-ASCII characters.
In a custom "wscs.namespaced.min.js" package IE7 found an error.
1 | return false;},stripslashes:function(str){return(str+'').replace(/\\(.?)/g,function(s,n1){switch(n1){case'\\':return'\\';case'0':return'\u000';case'':return'';default:return n1;}});},stristr:function(haystack,needle,bool){var pos=0;haystack+='';pos=haystack.toLowerCase().indexOf((needle+'').toLowerCase());if(pos==-1){return false;}else{if(bool){return haystack.substr(0,pos);}else{return haystack.slice(pos);}}},strlen:function(string){var str=string+'';var i=0,chr='',lgth=0;var getWholeChar=function(str,i){var code=str.charCodeAt(i);var next='',prev='';if(0xD800<=code&&code<=0xDBFF){if(str.length<=(i+1)){throw'High surrogate without following low surrogate';} |
Resolution:
1 | return false;},stripslashes:function(str){return(str+'').replace(/\\(.?)/g,function(s,n1){switch(n1){case'\\':return'\\';case'0':return'\\u000';case'':return'';default:return n1;}});},stristr:function(haystack,needle,bool){var pos=0;haystack+='';pos=haystack.toLowerCase().indexOf((needle+'').toLowerCase());if(pos==-1){return false;}else{if(bool){return haystack.substr(0,pos);}else{return haystack.slice(pos);}}},strlen:function(string){var str=string+'';var i=0,chr='',lgth=0;var getWholeChar=function(str,i){var code=str.charCodeAt(i);var next='',prev='';if(0xD800<=code&&code<=0xDBFF){if(str.length<=(i+1)){throw'High surrogate without following low surrogate';} |
Notice the difference '\u000' -> '\\u000'
Hey Kevin, there are some md5() functions for JS around the web, for example this:
http://www.webtoolkit.info/javascript-md5.html
It's fast, I use it in a CRAM (challenge-response authentication) API.
Hi Brett,
I really found this function very useful. If you don't have it, please consider this. thank you.
http://www.finefrog.com/2009/01/31/convert-a-mysql-date-string-into-javascript-date-object/
1 2 3 4 56 7 8 9 1011 12 13 14 15 | function parse_date(datetime /* YYYY-MM-DD HH:mm:ss */) { var date = new Date(); var parts = String(datetime).split(/[- :]/); date.setFullYear(parts[0]); date.setMonth(parts[1] - 1); date.setDate(parts[2]); date.setHours(parts[3]); date.setMinutes(parts[4]); date.setSeconds(parts[5]); date.setMilliseconds(0); return date; } |
@peta: Besides what Michael and Kevin said, if you can find the time to help us in borrowing those features from other frameworks that you speak of--without sacrificing the full PHP API that we've attempted to follow (in some cases, we have had to take a performance hit in some functions in order to support all of the potential PHP arguments)--then we're all for it. But as stated by Michael, we are, for better or worse, committed to following the PHP API (except in cases where we can use our own "ini" to configure function behavior)...
@ Michael White: Thanks for chiming in Michael!
I would like to add that we're not in the business of porting language features. We're in the business of porting functions. Although JavaScript seriously kicks ass as a language, there's just no easy way to do higher level stuff like:
md5(), strip_tags(), strtotime(), number_format(), wordwrap()
That's were we come in. Please take a function you need (I'm sure the day will come you'll find a use for us if you're doing PHP & JS professionally) and be on your way.
At least that's how I look at it.
@peta I believe you may be missing the entire point of PHPJS. There are many PHP developers out there who feel much more "at home" with the PHP language than they do with JavaScript. While there are many other frameworks out there, a developer who's primary language is PHP may not have a chance to really learn one or more of those frameworks, especially on a project with a tight timeline. PHPJS is *not* meant to be a replacement for something like jQuery or Prototype but rather an additional asset. Frameworks like jQuery and Prototype are designed for manipulating the DOM, sending and receiving data, and other common client-side tasks. PHPJS used alongside one of the other frameworks would provide easier data manipulation functions at the developers fingertips rather. I'm not exactly a JS novice but I still find PHP's functions for string manipulation to be much more user friendly than JavaScript's - not to mention that even for the unfriendly stuff, the www.php.net documentation outshines any single resource for JavaScript documentation that I've ever come across.
Is there some way we can make it more clear that the purpose of PHPJS is not to replace frameworks like jQuery and Prototype but rather to assist people who are already familiar with PHP and need to use JavaScript for whatever reason.
Sorry, but where on earth are reasonable reasons to mimic ugly language constructs like those of PHP in JS? Most real-life functionalities being used by an average js developer are already implemented more cleverly and performant by one of the JS Frameworks being out there. Frankly, the idea behind PHPJS sounds nice, but a closer look at the sources and the performance of typical operations offered by PHPJS (tested most array, string and typechecking functionalities) sobers up very quickly.
Instead of continuing to follow a half-baked concept, I'd look to where langauge constructs of PHP might complement exisitng frameworks in a smart way, and implement these for one/more existing frameworks.
.peta
I'm trying to use the "array_walk_rucursive"-function,
but really don't know, how to make it work on my array.
Couldn't you add a sample function (other than "void()"),
to explain the idea of that function more understandable?
Thank you! I wasted hours trying to find js equivalents for php functions then trying to create my own equivalents. I'm glad I found you! You saved me hours of more wasted time! :)



David
Mar 4th
Your website is nice but it's a nightmare to access with an IE.
I think there's a solution according to:
http://aralbalkan.com/912
Thanks for your good functions.