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.

Другие вопросы по тегам