Передача пользовательских типизированных объектов в качестве аргументов при вызове метода службы PHP - PullRequest
0 голосов
/ 21 октября 2011

Мы используем zendamf в качестве шлюза удаленного взаимодействия между Flex-клиентом и PHP-сервером. Отображение типов на стороне сервера на типы на стороне клиента, похоже, не влияет на объекты, передаваемые в качестве параметров метода службы. Все объекты, имеющие пользовательские типы, принимаются как экземпляры stdClass. Есть ли способ заставить это? Или нам здесь чего-то не хватает?

Есть мысли?

Thx!

1 Ответ

2 голосов
/ 29 августа 2012

Немного старше этот вопрос, но пока не ответил.Итак, позвольте мне попробовать.;)

Первый @ www.Flextras.com: Вы правы.В PHP также необходимо выполнить некоторые вещи по отображению классов.

Так что для всех вас, интересующихся тем, как определить отображение классов с помощью Zend Framework, взгляните на следующий короткий, но (на мой взгляд)подробное введение.Если вы знаете все это, пропустите введение и переходите к разделу «О сопоставлении клиент-сервер и stdClass в Zend Framework»

Способы сопоставления классов в PHP с использованием Zend Framework

Asдокументация Zend Framework Zend_Amf_Server описывает, что у вас есть 3 варианта обеспечения отображения классов.Вы можете найти полную документацию здесь (где-то в середине страницы в разделе «Типизированные объекты») .

Первый вариант

// Use the setClassMap() method of Zend_Amf_Server
require_once '<PathToZendFramework>/Zend/Amf/Server.php';
$server = new Zend_Amf_Server();

$server->setClassMap('MyActionScriptClassName', 'MyPHPClassName');

// the typical package notation for ActionScript class names is also allowed here
$server->setClassMap('com.company.MyActionScriptClassName', 'MyPHPClassName');

Это наиболее гибкийвариант, потому что вы можете явно указывать отображения классов для обоих направлений клиент-сервер и сервер-клиент.В отличие от гибкости, вы можете сделать больше ошибок здесь.Ниже вы найдете контрольный список того, что следует учитывать при использовании сопоставления классов.

Второй параметр

// Define a special named public property on each class used for
// serialization/deserialization via AMF
public class MyPHPClassName
{
    public $_explicitType = 'MyActionScriptClassName';

    /* your class definition here */
}

Делая так, ваше сопоставление классов становится немного более динамичным, потому что Zend_Amf_Server будет автоматически искать$_explicitType свойство.Таким образом, вам не нужно явно определять отображение классов, как в первом варианте.К сожалению, используя $_explicitType, вы не можете определить имя класса PHP для отображения (это «немного более динамично»).Далее вы найдете подробное описание проблемы, которая возникает здесь.

Третий вариант

// Define a special named public method on each class used for
// serialization/deserialization via AMF
public class MyPHPClassName
{
    public function getASClassName()
    {
        return 'MyActionScriptClassName';
    }

    /* your class definition here */
}

Используя этот последний параметр, вы получите максимальную динамику от отображения классов.Вы можете просто вернуть строковый литерал, как в моем примере, но это будет то же самое, что и опция $_explicitType.Преимущество метода заключается в том, что классы могут генерировать имя класса ActionScript динамически.Таким образом, вы можете определить getASClassName() для самого верхнего класса в иерархии, от которого наследуются все ваши классы AMF.Недостаток здесь такой же, как и для второго варианта.Вы не можете определить имя класса PHP, которому сопоставлен класс.

Контрольный список сопоставления классов для Flex и Zend Framework

Если вы ошиблись при указании сопоставления классов, Flex не сможет преобразоватьк сильно типизированным объектам.Вместо этого вы получите экземпляр общего класса Object.Если это произойдет, вы должны проверить, имеет ли место одна или несколько из следующих вещей:

На стороне Flex

  • У вашего класса должен быть тег метаданных [RemoteClass].
  • Если вы указали удаленный класс с псевдонимом ([RemoteClass(alias="")]), проверьте, не допустили ли вы опечатку.
  • Определяет ли ваш класс (включая все классы, от которых он наследуется) все общедоступныесвойства, определенные на стороне сервера, эквивалентны?(может быть либо public var ..., либо пара-получатель / установщик)
  • Вы определили общие свойства как readwrite?
  • Вы пометили свойства, которые не будут использоваться для передачи с [Transient]тег метаданных?(Это исключит помеченное / десериализованное свойство)

На стороне Zend Framework

  • Использовали ли вы один из трех вариантов отображения классов?
  • Если вы использовали первый вариант, то ошиблись ли вы в названии класса ActionScript или PHP?(Имя класса ActionScript должно быть точно таким же, как определено в теге [RemoteClass] в приложении Flex)

О сопоставлении клиента с сервером и stdClass в Zend Framework

Я также столкнулся с проблемой, что строго типизированные аргументы, передаваемые методам класса обслуживания на стороне сервера, приводят к stdClass. Я часто пытался выяснить, почему это происходит, но никогда не занимал время, чтобы действительно найти причину. Вчера, после дополнительной попытки сделать отображение классов как можно более динамичным / универсальным в одном из моих проектов и после нескольких часов исследований, я обнаружил, что Zend_Amf_Server будет делать при получении запроса AMF. (Кстати: я никогда не находил причину, если бы я не реализовал строгие соглашения об именах классов в своем коде PHP).

Когда поступает запрос AMF и Zend_Amf_Server начинает его синтаксический анализ, он считывает из запроса некоторый псевдоним удаленного класса и пытается автоматически загрузить этот класс. Это то, что мы хотим, чтобы Zend_Amf_Server делал, верно !? Но сервер AMF поддерживает только автоматы для обработки имен классов, таких как MyClassName или соответствия соглашениям об именах, что-то вроде My_Class_Name. Вы не можете автоматически сопоставлять классы с псевдонимом удаленного класса, таким как com.company.SomeAmfClass. Zend ожидает, что вы указали пакет (который представляет собой обычный путь к каталогу) и преобразует все точки в подчеркивания, прежде чем пытаться загрузить класс. Класс, который будет делать это Zend_Amf_Parse_TypeLoader. Сервер AMF вызовет для него статический метод loadType().

Вот реализация этого метода (скопирована непосредственно из Zend Framework 1.11.7):

/**
  * Load the mapped class type into a callback.
  *
  * @param  string $className
  * @return object|false
  */
 public static function loadType($className)
 {
     $class    = self::getMappedClassName($className);
     if(!$class) {
         $class = str_replace('.', '_', $className);
     }
     if (!class_exists($class)) {
         return "stdClass";
     }
     return $class;
 }

Сначала я попытался определить класс, который реализует Zend_Loader_Autoloader_Interface, и поместил его в стек автозагрузчика синглтона Zend_Loader_Autoloader. Но проблема заключалась в том, что Zend_Amf_Parse_TypeLoader::loadType() изменяет имя класса до того, как произойдет автозагрузка - что происходит при вызове class_exists().

Итак, вы можете изменить этот метод непосредственно в платформе для дополнительной обработки имен классов ActionScript, таких как com.company.SomeAmfClass. Но это должен быть самый последний вариант, потому что это плохая практика - менять код фреймворка!

Другое решение - и почти самое чистое - состояло бы в реорганизации и переименовании всех ваших классов в соответствии с соглашениями об именах Zend Framework, но, к сожалению, это может занять несколько часов рефакторинга (что на самом деле не так просто обрабатывать в PHP) и, возможно, дни тестирования и отладки всей вашей кодовой базы.

Чтобы соблюсти баланс, вы можете обезопасить необходимые классы фреймворка. Таким образом, вы не изменили бы сам фреймворк, но не провели бы рефакторинг вашей кодовой базы. Есть некоторые рамки, которые сделают свое дело. Я нашел несколько примеров в ответах на этот вопрос

Дополнительно нашел этот вопрос здесь: AMF-типизированные объекты из flex обратно в PHP Вы должны проверить, соответствует ли это вашим потребностям.

Надеюсь, это кому-нибудь пригодится. Скажите, если я что-то забыл (например, в контрольном списке!)

...