inline JSON syntax in PHP - php

PHP would be a lot cooler if you could write things like this:
$array = [2, 3, 5];
$object = { "name" : "Harry", "age" : 23, "cats" : ["fluffy", "mittens", "whiskers"]};
but, I just spent a lot of time looking for an extension (even an experimental alpha or anything) adding json syntax to PHP but found nothing.
Does anything like this exist?
If not, considering the existence of json_decode() and facebook's XHP, would it be difficult to write an extension to do this?
I have no experience writing PHP extensions, although I did a lot of C in college.

You could just wrap your datastructure in json_decode and be done with it:
$array = json_decode('[2, 3, 5]');
$object = json_decode('{
"name" : "Harry",
"age" : 23,
"cats" : [
"fluffy", "mittens", "whiskers"
]
}');
Yes, it doesn't do typechecking until the statement is executed, and you'll have a bit of a problem handling multiple quotes, but you could always use a HEREDOC for that.

Different syntax for PHP arrays has been proposed and rejected many times before.
Unfortunate, I know, because I hate the ugly syntax too.

Update: All the below has become somewhat moot with PHP 5.4; we now have [..] array syntax.
Yes, PHP's array syntax is overly verbose and ugly and I too wish it would be more terse.
No, it would probably not be a good idea to attempt to change that for existing versions of PHP, since it's a feature that would need to be baked into the parser. That means your PHP applications would only run on custom compiled versions of PHP, which makes your app much less portable and thereby negate one of the good things about PHP.
You may want to attempt something like a compiler, which compiles your custom array syntax into normal syntax before running the code. If you went that far though, using an entirely different language to begin with may be the better choice.
Try to lobby for a Javascript-like syntax for PHP 6.x. Until then, just write array(). :)

If you want to write something that isn't PHP, then use something that isn't PHP. Otherwise, use array().
$array = array(2, 3, 5);
$object = array('name' => 'Harry', 'age' => 23, 'cats' => array('fluffy', 'mittens', 'whiskers'));

A mixture of associative and numerically indexed arrays usually gets you pretty close:
$object = array("name" => "Harry", "age" => 23, "cats" => array("fluffy", "mittens", "whiskers"));
In my opinion (especially because of the existence json_encode) it's not meaningfully different to write straight JSON over something like the above.

php doesn't handle json - whiwch is why it gives you the tools to encode/decode.
I you are desperate to 'write' in that manner just stick quotes around it:
$object = '{ "name" : "Harry", "age" : 23, "cats" : ["fluffy", "mittens", "whiskers"]}';
As far as php is concerned a 'json object' is nothing more than a string...

As people have said above, different languages have different syntax - if you don't like PHP's syntax, you might consider considering other languages.
JSON stands for "javascript object notation" - maybe what you want is server-side javascript. There's a huge array of server-side javascript options out there - jsgi/jack (narwhal), ringojs, flusspferd, node.js, v8cgi, etc. etc. http://wiki.commonjs.org/

If php would be a lot cooler and would just let you write things like this, it would be JavaScript, I guess;) but serious:
My approach for that problem is to load json files (Get data from JSON file with PHP) and just decode them.
Maybe you could also use a build tool like Grunt/Gulp and stringyfie and inject seperate json-files in your php code. (https://florian.ec/articles/buliding-symfony2-with-gulp/)

Related

Using eval on mysql data, is my code vulnerable, if so what is a better alternative

I am using the information_schema.columns table to grab some information.
I just want to know if this is a bad idea and whether there is a better alternative.
if($column['DATA_TYPE'] === 'enem'){
$options = eval(str_replace('enem(', 'array(', $column['COLUMN_TYPE']));
}
I chose to use eval and a single str_replace as i thought it was the fastest method of creating the array.
Here is an example of what $column could look like
$column = array(
['COLUMN_NAME'] => 'status',
['COLUMN_TYPE'] => "enum('failed','success','pending','other')",
['DATA_TYPE'] => 'enum',
);
I think your second solution is much more clear and the difference in speed and memory performances will be minor. (You could also use RegExp)
Here is a link which can help you:
How can I get enum possible values in a MySQL database?
Here is one not eval alternative, probably not as quick as the eval but still fast
if($column['DATA_TYPE'] === 'enem'){
$enums = str_replace(array('enum(', ')'), '', $column['COLUMN_TYPE']);
$options = explode(',', $enums);
}
More checks might need to be done but it works for
enum('failed','success','pending','other')
The only real reason not to use eval() in this case is because you want your code to run on for example HHVM by Facebook, which does not support eval afaik. I see no security problems in your particular case, however.
However, if you simply change your code slightly, you could use json_decode:
$options = json_decode('['.substr($column['COLUMN_TYPE'], 5, -1).']);
It's hard to tell which is faster without doing a small benchmark. I suspect this is faster, because str_replace has to search the entire string.

Converting php [] to array() syntax in multiple files

I'd like to create a (temporary) version of my web app that supports PHP < 5.4, for which I need to convert all my short array syntax to the long one.
There's plenty of "old to new" scripts, but the only "new to old" one seems to be this — https://github.com/slang800/php-array-syntax-converter, however when I tried running it, it gave me the following error:
PHP Catchable fatal error: Argument 1 passed to processTree() must be
an instance of Pharborist\TopNode, instance of Pharborist\RootNode
given
Hopefully, someone has had a similar experience and could point me in the right direction.
Thanks.
If I were you, I'd simply write my own script, so you don't have to wait for a fix to be written for the script you're using now. It's really not that hard to work out what to replace, really: It's all occurrences of this pattern /\[[^]]*\]/ that are part of an expression, other than $var[$idx] (accessing an index of an array, or pushing onto an array: $var[] =).
Off the top of my head, I'd write a script that just does this, basically:
$pattern = '/(=>?|,|\[|\()\s*\[([^]]+)\](?!\s*=)/';
$script = file_get_contents('path/to/file.php');
$rewritten = preg_replace(
$pattern,
'$1 array($2)',
$script
);
//only AFTER you've checked the output, of course!
file_put_contents('path/to/file.php', $rewritten);
Note that this regex isn't finished just yet: it can't cope with nested arrays like:
$x = [ $y[1] => [1, 2, 3]];
But Play around with it here, until you can get it to work. It might be worth while using preg_match_all with a different pattern, matching the entire expression containing nested arrays, and replace what needs replacing separately. That'd make your life a lot easier, I do think

What variants of array declaration syntax are available in PHP 5.4?

On the PHP documentation page for arrays, the example code given is the following:
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
);
// as of PHP 5.4
$array = [
"foo" => "bar",
"bar" => "foo",
];
?>
Does that mean that the first code is invalid in PHP 5.4, or is the second code just an alternative?
The first code is still valid. The second notation is just a shorter and more convenient alternative.
As others noted the first one is valid. The second one is shorter version.
Here are the pros and cons for second version:
Pro
Good for framework development when dealing with long parameterlists
Other web languages have similar syntax
Readable
Contra
Yet another alias
Would take distinctness from []
Not searchable through search engines
Unreadable
Patch may be difficult to maintain in future
from PHPWiki

Problem with PHP Array

Why is it not possible to do something equivalent to this in PHP:
(Array(0))[0];
This is just for sake of argument, but it seems strange it does not allow access of anonymous objects. I would have to do something like the following:
$array = Array(0);
$array[0];
Any ideas why this is the behavior of PHP?
I read something somewhat detailed about this once and I regret not bookmarking it because it was quite insightful. However, it's something along the lines of
"Because the array does not exist in memory until the current statement (line) executes in full (a semicolon is reached)"
So, basically, you're only defining the array - it's not actually created and readable/accessible until the next line.
I hope this somewhat accurately sums up what I only vaguely remember reading many months ago.
This language feature hasn’t been inplemented yet but will come in PHP 6.
I guess the short answer is: nobody has coded it yet. I've used (and loved) that syntax in both Python and Javascript, but still we wait for PHP.
The main reason is because unlike some languages like Python and JavaScript, Array() (or in fact array()) is not an object, but an language construct which creates an inbuilt data type.
Inbuilt datatypes themselves aren't objects either, and the array() construct doesn't return a reference to the "object" but the actual value itself when can then be assigned to a variable.

Translate multiple languages in php

I am working on a small parser that should accept input in a number of languages. I am going to have maybe 50 strings that will serve as keywords/anchors in parsing the input. In PHP, what would be the best way to organize these translated keywords?
One possible solution that comes to my mind is to use an associative array. Like this:
$lang = array('us' => array('totalDebt' => 'Total Debt', 'color' => 'Color'),
'gb' => array('totalDebt' => 'Total Debt', 'color' => 'Colour'))
which I could then access using the following:
$langCode = 'en';
$debtPos = strpos($lang[$langCode]['totalDebt']);
Are there any better, proven methods for dealing with a bunch of short strings translated into a bunch of languages?
For a complete translation solution, you can look on a solution like gettext.
you solution is good enough (fast, cheap on resources) for small dictionaries.
I didn't understand what you tried to do using the strpos() function.
Don't forget to use some kind of fallback if the term you want to translate doesn't exists in the language, usually the fallback is to the English.
Generally people use l10n (or something similar) in their application because it allows for additional languages by adding a localization file which means the programmers do not have to change code. But if it is a simple script, then full on localization would be overkill.
I have seen your solution used in other OS projects, however the $lang array is usually constructed in different files. For example:
<?php // lang.us.php
$LANG['us'] = array(
'totalDebt' => 'Total Debt',
'color' => 'Color',
);
and so on for lang.gb.php, lang.de.php, etc.
As Peter said, you've got the right idea, but separate your languages into different files. It means that PHP won't have to store the array of every single word in every single language. Because you only are going to be loading one language at a time, you can skip the $lang['us'] level of nesting too.
You could even "extend" languages:
<?php // lang.en-gb.php
$lang = array(
'color' => "Colour",
'totalDebt' => "Total Debt",
...
);
?>
<?php // lang.en-us.php
include('lang.en-gb.php');
$lang['color'] = "Color";
// don't need to redefine "totalDebt"
?>
You might even consider creating a basic class which handles all this for you: detect the locale, choose the correct file, have "error" handling, if a term isn't defined in a particular language, etc.
You probably don't want 'totaldebt' => 'Total Debt' as that will ultimately obfuscate your code, and is slower than just storing 'Total Debt' as the hash key. The gettext way of doing things is to just wrap the strings in a function.
so rather than:
echo "Color";
You do:
echo t("Color");
the t() function will look at the globally defined language, and make the substitution if possible. At some point, you may want to use gettext and doing it this way will be compatible.

Categories