AMFPHP: Сериализация Flash-объектов по HTTP без шлюза
Flash + AMFPHP - отличная комбинация. Но бывают случаи, когда Flash Remoting с NetConnection не подходит по разным причинам. У Роба был отличный пост по этому вопросу некоторое время назад: http://www.roboncode.com/articles/144
У него также есть хороший пример того, как доставить AMF в http-запрос без пакета POST и AMF-запроса для вызова функции, которую NetConnection отправляет, используя Zend_AMF.
// Include the Zend Loader
include_once 'Zend/Loader.php';
// Tell the Zend Loader to autoload any classes we need
// from the Zend Framework AMF package
Zend_Loader::registerAutoload();
// Create a simple data structure
$data = array('message' => 'Hello, world!');
// Create an instance of an AMF Output Stream
$out = new Zend_Amf_Parse_OutputStream();
// We will serialize our content into AMF3 for this example
// You could alternatively serialize it as AMF0 for legacy
// Flash applications.
$s = new Zend_Amf_Parse_Amf3_Serializer($out);
$s->writeObject($data);
// Return the content (we have found the newline is needed
// in order to process the data correctly on the client side)
echo "\n" . $out->getStream();
Мне очень нравится этот подход, и я буду очень рад повторить его с помощью AMFPHP. Почему AMFPHP, спросите вы? "Новейшая" версия использует amf-ext, расширение C PHP, для сериализации и десериализации данных. Это намного быстрее, чем все еще использует ZendAMF.
Конечно, я уже играл с AMFPHP и пытался построить необходимые объекты и использовать класс Serializer. Я даже получил действительную строку AMF, но реальные данные всегда были заключены в "пакет методов", который сообщал получателю, что это ответ на вызов "Service.method".
Так есть ли способ сериализации Flash-объектов напрямую, без шлюза и метода-оболочки, в AMFPHP?
Благодарю.
2 ответа
Ладно, теперь все заработало.
Это немного сложнее, чем решение Zend_AMF, но гораздо быстрее. Вот мой код:
$data = array('message' => 'Hello, world!');
// Create the gateway and configure it
$amf = new Gateway();
Amf_Server::$encoding = 'amf3';
Amf_Server::$disableDebug = true;
// Construct a body
$body = new MessageBody("...", "/1", array());
$body->setResults($data);
$body->responseURI = $body->responseIndex . "...";
// Create the object and add the body
$out = new AMFObject();
$out->addBody($body);
// Get a serializer and use it
$serializer = new AMFSimpleSerializer();
$result = $serializer->serialize($out);
Как видите, есть новый класс AMFSimpleSerializer
что я построил:
class AMFSimpleSerializer extends AMFSerializer
{
function serialize(&$amfout)
{
$encodeCallback = array(&$this,"encodeCallback");
$body = &$amfout->getBodyAt(0);
$this->outBuffer = "";
$this->outBuffer .= amf_encode($body->getResults(), $this->encodeFlags, $encodeCallback);
$this->outBuffer = substr($this->outBuffer, 1);
return $this->outBuffer;
}
}
Этот класс работает только в том случае, если установлен amfext, но его можно легко модифицировать для использования процесса php enocding. Я не реализовал это, потому что я построил это на сильно модифицированной версии AMFPHP.
Я надеюсь, что я заменил все классы из моего кода на настоящие аналоги AMFPHP. Я постараюсь проверить это завтра и обновить этот ответ, если это необходимо.
После того, как я закончил, я понял, что теперь почти ничего от AMFPHP фактически не осталось в классе, это просто вызов amf_encode и удаление первого байта, чтобы клиент мог понять, что он получает.
Легко, просто, быстро.
Это упрощенная версия, которая не нуждается в amfext:
require_once( 'amfphp/core/amf/app/Gateway.php');
require_once( AMFPHP_BASE . 'amf/io/AMFSerializer.php');
$data = array('message' => 'Hello, world!')
$serializer = new AMFSerializer();
$serializer->writeAmf3Data( $data );
print $serializer->outBuffer;
Нет новой строки и подстроки необходимо. AMFPHP 1.9, Flex 3.4.