Для одного из следующих докладов реализовал .mRPC — простой механизм вызова серверных методов со стороны клиента.
Рабочий пример.
Заранее прошу прощения за ужасную разметку на Хабре, корректная статья находится в моём персональном блоге...
Да, дополню — аргументы и возвращаемое значение серверной функции не лимитированы ничем, кроме ограничений сериализации как таковой. Хотите вернуть с сервера массив или хэш любой вложенности — Вас никто не ограничивает ;)
Вот так это выглядит на клиенте:
А вот так мы описываем классы на сервере (config.php, код для Perl будет позднее, но его легко написать и самому, с помощью CPAN Class::Inspector):
Исходный текст класса MRpc (MRpc.class.php):
И, наконец, код index.php (диспетчер):
Рабочий пример.
Заранее прошу прощения за ужасную разметку на Хабре, корректная статья находится в моём персональном блоге...
Да, дополню — аргументы и возвращаемое значение серверной функции не лимитированы ничем, кроме ограничений сериализации как таковой. Хотите вернуть с сервера массив или хэш любой вложенности — Вас никто не ограничивает ;)
Вот так это выглядит на клиенте:
- <!-- jQuery -->
- <script type=«text/javascript» src="/samples/mrpc/jquery.js"></script>
- <!-- JSON-serialization support -->
- <script type=«text/javascript» src="/samples/mrpc/jquery.json.js"></script>
- <!-- .mrpc support -->
- <script type=«text/javascript» src="/samples/mrpc/jquery.mrpc.js"></script>
- <!-- description of supported server classes and methods -->
- <script type=«text/javascript» src="/samples/mrpc/"></script>
- <!-- А здесь вызываем метод yo класса Test в синхронном режиме -->
- <a href=«javascript:;» onclick=«alert($.mrpc.Test.yo('foo'))»>foo</a>
А вот так мы описываем классы на сервере (config.php, код для Perl будет позднее, но его легко написать и самому, с помощью CPAN Class::Inspector):
class Test { public static function yo($s) { return 'ok, I got parameter "'. addslashes($s). '"'; } } MRpc::registerRpcClass('Test');
Исходный текст класса MRpc (MRpc.class.php):
class MRpc { private static $classes = array(); public static function registerRpcClass($className) { MRpc::$classes[] = $className; } public static function getClassNames() { return MRpc::$classes; } public static function getClassMethodNames($className) { if (!class_exists($className)) { require_once($className. '.class.php'); } return get_class_methods($className); } public static function performCall($className, $methodName, $arguments) { if (!in_array($className, MRpc::$classes)) { header('HTTP/1.1 404 Not Found'); header('Status: 404 Not Found'); print '{status: false, class: "Not registered"}'; exit; } $methodNames = MRpc::getClassMethodNames($className); if (!in_array($methodName, $methodNames)) { header('HTTP/1.1 404 Not Found'); header('Status: 404 Not Found'); print '{status: false, method: "Not registered"}'; exit; } return call_user_func_array(array($className, $methodName), $arguments); } }
И, наконец, код index.php (диспетчер):
require_once(dirname(__FILE__). '/MRpc.class.php'); require_once(dirname(__FILE__). '/config.php'); header('Content-type: text/plain'); if (array_key_exists('class', $_REQUEST) && array_key_exists('method', $_REQUEST) && array_key_exists('arguments', $_REQUEST)) { header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past print json_encode(MRpc::performCall($_REQUEST['class'], $_REQUEST['method'], json_decode($_REQUEST['arguments']))); exit; } $classes = array(); foreach (MRpc::getClassNames() as $className) { $def = array('name' => $className, 'url' => $_SERVER['PHP_SELF'], 'methods' => array()); foreach (MRpc::getClassMethodNames($className) as $methodName) { $def['methods'][] = $methodName; } $classes[] = $def; } ?> // JavaScript code - MRPC wrapper (function($) { $.mrpc( ?php print json_encode($classes); ? ); })(jQuery);