Pull to refresh

.mrpc — простое взаимодействие клиента с сервером

Reading time 3 min
Views 1.2K
Для одного из следующих докладов реализовал .mRPC — простой механизм вызова серверных методов со стороны клиента.
Рабочий пример.

Заранее прошу прощения за ужасную разметку на Хабре, корректная статья находится в моём персональном блоге...
Да, дополню — аргументы и возвращаемое значение серверной функции не лимитированы ничем, кроме ограничений сериализации как таковой. Хотите вернуть с сервера массив или хэш любой вложенности — Вас никто не ограничивает ;)

Вот так это выглядит на клиенте:
  1. <!-- jQuery -->
  2. <script type=«text/javascript» src="/samples/mrpc/jquery.js"></script>
  3. <!-- JSON-serialization support -->
  4. <script type=«text/javascript» src="/samples/mrpc/jquery.json.js"></script>
  5. <!-- .mrpc support -->
  6. <script type=«text/javascript» src="/samples/mrpc/jquery.mrpc.js"></script>
  7. <!-- description of supported server classes and methods -->
  8. <script type=«text/javascript» src="/samples/mrpc/"></script>
  9.  
  10. <!-- А здесь вызываем метод yo класса Test в синхронном режиме -->
  11. <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);

Tags:
Hubs:
+2
Comments 5
Comments Comments 5

Articles