Из этого топика вы узнаете как отправить JavaScript функции, через JSON используя PHP (сама концепция может быть применена и для других языков).
PHP, начиная с версии 5.2.0, включает функции json_encode() и json_decode(). Эти функции кодируют данные в формат JSON и декодиуют JSON в ассоциативные массивы. В json_encode() не может быть закодирована функция. В ряде случаев это чертовски неудобно.
Так как если не заключить определение функции в кавычки, т. е. не определить как строку, код не будет исполнятся. Так что в принципе jscon_encode() не годится для реализации этого функционала.
PHP, начиная с версии 5.2.0, включает функции json_encode() и json_decode(). Эти функции кодируют данные в формат JSON и декодиуют JSON в ассоциативные массивы. В json_encode() не может быть закодирована функция. В ряде случаев это чертовски неудобно.
- Добавлен пример реализации в Zend Framework.
- Вопрос к кармавампирам — вы знаете вариант как передать handler для создания объекта иначе?
- Комментарий о том для чего и кому это нужно.
Проблема
// Возьмем произвольный массив
$foo = array(
'number' => 1,
'float' => 1.5,
'array' => array(1,2),
'string' => 'bar',
'function'=> 'function(){return "foo bar";}'
);
// Теперь преобразуем массив в JSON
$json = json_encode($foo);
// Отдадим клиенту
echo $json;
* This source code was highlighted with Source Code Highlighter.
Результат
{
"number":1,
"float":1.5,
"array":[1,2],
"string":"bar",
"function":"function(){return \"foo bar\";}"
}
* This source code was highlighted with Source Code Highlighter.
Так как если не заключить определение функции в кавычки, т. е. не определить как строку, код не будет исполнятся. Так что в принципе jscon_encode() не годится для реализации этого функционала.
Решение
- Проходим по массиву который будет закодирован.
- Проверяем кодируемое значение на предмет наличия определения функции.
- Запоминаем значение и заменяем его уникальной меткой.
- Кодируем измененный массив используя json_encode().
- Заменяем уникальную метку на оригинальное значение.
- Отдаем JSON клиенту.
// Обрабатываемый массив.
$foo = array(
'number' => 1,
'float' => 1.5,
'array' => array(1,2),
'string' => 'bar',
'function'=> 'function(){return "foo bar";}'
);
$value_arr = array();
$replace_keys = array();
foreach($foo as $key => &$value){
// Проверяем значения на наличие определения функции
if(strpos($value, 'function(')===0){
// Запоминаем значение для послудующей замены.
$value_arr[] = $value;
// Заменяем определение функции 'уникальной' меткой..
$value = '%' . $key . '%';
// Запоминаем метку для послудующей замены.
$replace_keys[] = '"' . $value . '"';
}
}
// Кодируем массив в JSON
$json = json_encode($foo);
// Полученный $json будет выглядеть так:
{
"number":1,
"float":1.5,
"array":[1,2],
"string":"bar",
"function":"%function%"
}
// Заменяем метски оригинальными значениями.
$json = str_replace($replace_keys, $value_arr, $json);
// Отправляем клиенту.
echo $json;
// Клиент получит JSON такого вида:
{
"number":1,
"float":1.5,
"array":[1,2],
"string":"bar",
"function":function(){return "foo bar";}
}
* This source code was highlighted with Source Code Highlighter.
Теперь в полученном обьекте «function» является не строкой, а функцией. Собственно проблема решена. Если использовать это решение совместно с Prototype, то оно будет выглядеть примерно так:new Ajax.Request('json_server.php', {
method:'get',
onSuccess: function(transport){
var json = transport.responseText.evalJSON();
alert(json.function()); // => Отобразится alert 'foo bar'
}
});
* This source code was highlighted with Source Code Highlighter.
Реализация в Zend Framework:
$foo = array(
'integer' =>9,
'string' =>'test string',
'function' => Zend_Json_Expr(
'function(){ window.alert("javascript function encoded by Zend_Json") }'
),
);
Zend_Json::encode($foo, false, array('enableJsonExprFinder' => true));
// it will returns json encoded string:
{
"integer":9,
"string":"test string",
"function":function(){
window.alert("javascript function encoded by Zend_Json")
}
}
* This source code was highlighted with Source Code Highlighter.