Archive for Czerwiec, 2010

Błąd „Variable number of arguments is not supported for services”

W programowaniu dość istotną kwestią jest komentowanie kodu, mam na tym punkcie lekkiego fioła.;) Tworząc funkcję w serwisie udostępniającym dane jak zawsze przystąpiłem do ob-komentowania parametrów i opisania samego działania funkcji.

/**
 * Test function
 *
 * @param string $name
 * @param string $surname
 * @return array
 */
 public function testFunction($name, $surname)
 {
      return $name.' '.$surname;
 }

Po całym rytuale komentowania doszedłem do wniosku, że nie będzie mi potrzebny jeden z parametrów. Radośnie usunąłem go, po czym przystąpiłem do sprawdzenia działania funkcji w ZAmfBrowser otrzymałem błąd o sygnaturze:

PHP Fatal error: Uncaught exception ‘Zend_Server_Reflection_Exception’ with message ‘Variable number of arguments is not supported for services (except optional parameters). Number of function arguments must correspond to actual number of arguments described in a docblock.’

Dość długo zastanawiałem się, co jest nie tak, a to, dlatego, że w pośpiechu zwróciłem uwagę tylko na pierwsze zdanie – drugie z kolei mówi mi o wiele więcej.

Ilość argumentów funkcji musi odpowiadać ilości argumentów opisanych
w docblock-u.

Jednak na to wszystko zwrócił mi uwagę kolega z pracy, który zerknął na mój kod. Morał z całego "zajścia":

  • Analizuj błędy w całości, bo może ich rozwiązanie kryje się na samym końcu opisu otrzymanego wyjątku
  • Czasami warto aby ktoś spojrzał na Twój kod "świeżym" okiem, to może przynieść nie tylko rozwiązanie, ale niejednokrotnie poprawę funkcjonalności

Dostęp do itemrenderer-ów w Spark DataGroup

Czwarta odsłona Flex SDK przyniosła ze sobą nowe rodzaje kontenerów ułatwiających rozmieszczanie komponentów w aplikacjach flex-owych. Jednym z nich jest DataGroup. Nie chcę tutaj opisywać możliwości kontenera tylko przedstawić sposób w jaki uzyskałem dostęp do utworzonych w moim DataGroup itemrenderer-ów.

Mój itemrenderer wyświetla imię i nazwisko na podstawie danych zawartych w obiekcie "PersonVo".

Klasa PersonVo.

public dynamic class PersonVo
{
		public var firstName:String;
		public var surname:String;

		public function PersonVo(firstName:String = null,
					surname:String = null)
		{
			this.firstName = firstName;
			this.surname =surname;
		}
}

Kod itemrenderer-a

<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
		xmlns:s="library://ns.adobe.com/flex/spark"
		xmlns:mx="library://ns.adobe.com/flex/mx"
		autoDrawBackground="true">
	<s:HGroup gap="5"
			  height="100%">
		<s:Label id="firstName"
			 text="{data.firstName}"/>
		<s:Label id="surname"
			 text="{data.surname}"/>
	</s:HGroup>
</s:ItemRenderer>

Dostęp do każdego utworzonego obiektu itemrenderera uzyskuję rejestrując metodę dla zdarzenia "rendererAdd". W jej argumencie zostaje dostarczony obiekt "event" typu "RendererExistenceEvent", który to zawiera instancję itemrenderera. Wszystkie obiekty itemrenderer-ów umieszczam w tablicy i udostępniam na zewnątrz kontenera DataGroup poprzez publiczną właściwość.

DataGroup z przechowanymi obiektami itemrenderer-ów.

<s:DataGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
	        xmlns:s="library://ns.adobe.com/flex/spark"
	        xmlns:mx="library://ns.adobe.com/flex/mx"
                   itemRenderer="dgControls.DgControlRenderer"
	        rendererAdd="onRendererAdd(event)">
	<fx:Script>
		<![CDATA[
			import spark.events.RendererExistenceEvent;
			private var _itemRenderers:Array = [];

			/**
			 * Array of itemrenderers
			 * */
			public function get itemRenderers():Array
			{
				return _itemRenderers;
			}

			/**
			 * Add renderer to array
			 * */
			protected function onRendererAdd(event:RendererExistenceEvent):void
			{
				_itemRenderers.push(event.renderer);
			}
		]]>
	</fx:Script>
</s:DataGroup>

Do dataprovidera kontenera DataGroup dostaczyłem następującą tablicę oraz przeprowadziłem prostą iterację wraz ze zmianą właściwości wewnątrz itemrenderera. W zasadzie było to dość proste, ale czy to jedyne rozwiązanie? ;)

Tablica elementów "dataProvidera" w DataGroup.

var dpDataGroup:ArrayCollection = new ArrayCollection([
						new PersonVo("Piotr", "Zarzycki"),
						new PersonVo("Marian", "Zakrzewski"),
						new PersonVo("Damian", "Zarzycki")
					]);

Zmiana właściwości obiektów itemrenderer-ów.

var count:int = dg.itemRenderers.length;

for(var i:int = 0; i < count; i++)
{
					var dgRenderer:DgControlRenderer = dg.itemRenderers[i];
					dgRenderer.firstName.text = "Ola";
					dgRenderer.surname.text = "O.";
}