Zum Inhalt springen

Fehler nach Update

Erstellt am 4. September 2012 · 13 Antworten · letzte Antwort am 21. Oktober 2013

Tags: Frage

MajPay ·

Hallo,

Nachdem ich in meinem Testprojekt auf die Beta1 (von Alpha3) aktualisiert habe bekomme ich einen Fehler.

Der Fehler:
#1231178878: Given property name is not of type string. (More information)

ObjectAccess erwartet auf jeden Fall einen String als $propertyName, da ich aber in einem Form ein Object per select ausgeben lasse (Eine Optionlist) waren meine Keys ein index und die value die uid der Datensätze, der Post kommt am Webserver wie folgt an:

array(1) {
  ["tx_testcompany_companies"]=>
  array(3) {
    ["__referrer"]=>
    array(3) {
      ["extensionName"]=>
      string(11) "TestCompany"
      ["controllerName"]=>
      string(8-) "Location"
      ["actionName"]=>
      string(3) "new"
    }
    ["__hmac"]=>
    string(231) "a:4:{s:8:\"location\";a:4:{s:7:\"address\";i:1;s:7:\"zipcode\";i:1;s:7:\"country\";i:1;s:8:\"branches\";a:2:{i:0;i:1;i:1;i:1;}}s:7:\"company\";i:1;s:6:\"action\";i:1;s:10:\"controller\";i:1;}383f73d16488d282f421ee104bf6ed7f62b0c75e"
    ["location"]=>
    array(4) {
      ["address"]=>
      string(8-) "Am Weg 2"
      ["zipcode"]=>
      string(4) "9020"
      ["country"]=>
      string(10) "Klagenfurt"
      ["branches"]=>
      array(1) {
        [0]=>
        string(1) "2"
      }
    }
  }
}

Der fehler kommt vom tx_testcompany_companies[location][branches][0]=2

Im Location Model sieht das so aus:

/**
 * @var Tx_Extbase_Persistence_ObjectStorage<Tx_TestCompany_Domain_Model_Branch>
 */
protected $branches;

Template:

<f:form.select property="branches" options="{branches}" multiple="multiple" optionLabelField="name"></f:form.select>

Ich habe keine Lust hier irgendwas rumzuwurschteln, so wie hier gebaut erscheint es mir logisch.

Muss man nun alle keys (auch in solchen Selects) zb als branch0 benennen oder ist das ein Bug im aktuellen Extbase?

MajPay ·

Hat jemand eine Idee? Nach stundenlangem durchforsten von Extbase und meiner Extension stehe ich nach wie vor am selben Punkt.

Meiner Meinung nach kommen die Werte wie geplant am Server an:

Array
(
    [tx_testcompany_companies] => Array
        (
            [location] => Array
                (
                    [__identity] => 1
                    [address] => Roadtohell 616
                    [zipcode] => 61666
                    [country] => Deep South
                    [branches] => Array
                        (
                            [0] => 1
                            [1] => 2
                        )

                )

            [__referrer] => Array
                (
                    [extensionName] => TestCompany
                    [controllerName] => Location
                    [actionName] => edit
                )

            [__hmac] => a:4:{s:8:\"location\";a:5:{s:7:\"address\";i:1;s:7:\"zipcode\";i:1;s:7:\"country\";i:1;s:8:\"branches\";a:2:{i:0;i:1;i:1;i:1;}s:10:\"__identity\";i:1;}s:7:\"company\";i:1;s:6:\"action\";i:1;s:10:\"controller\";i:1;}df1e332fcf4cf1cdd2a418568900e8b79e1f2af6
        )

)

Aber Extbase will nicht das Tx_Extbase_Persistence_ObjectStorage
location[branches] mit den Werten befüllen sondern versucht irgendwo die Eigenschaft 0 mit 2 zu befüllen, was es nicht mag.

Im Template kann kein Fehler sein.

Kann der Fehler noch im TCA sein?

Über jede Art von Hilfe wäre ich sehr froh...

Unbekannter Benutzer ·

Also die Persistence braucht infos aus dem TCA, das PropertyMapping nicht, soweit ich weiß. Was ich so sehe sollte das im PropertyMapper auch alles so laufen wie du denkst, da müsste man mal debuggen. Vielleicht hast du das mit dem ObjectStorage erst später gemacht? Du kannst testweise mal die tx_extbase cache tabellen in der DB leeren damit die Object Reflection neu gemacht wird.

MajPay ·

Nö, gerade versucht, habe alle tables (cf_extbase...) über phpmyadmin geleert. Selber Fehler.

In der Alpha3 ging das noch, in der Beta1 nicht mehr, ich habe allerdings kein Update gemacht sondern einfach neu aufgesetzt, extension installiert und weitergemacht. Und siehe da: Fehler...

In TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty wurde soweit ich das sehen kann allerdings nur die Syntax angepasst, da kam keine neuartige Validierung rein. Alle Scripte da durchzuforsten - da habe ich keine Lust dazu wo der "Fehler" ja höchstwahrscheinlich an meiner Extension liegt.

MajPay ·

Habe aus Interesse nochmals ein System mit der Alpha3 eingerichtet und die Extension dort installiert (einfach 1:1 rüberkopiert und installiert). Schwupps -> funktioniert wieder. Version 6B1 - funktioniert nicht.

Alpha3:

/**
	 * Set a property for a given object.
	 * Tries to set the property the following ways:
	 * - if target is an array, set value
	 * - if super cow powers should be used, set value through reflection
	 * - if public setter method exists, call it.
	 * - if public property exists, set it directly.
	 * - if the target object is an instance of ArrayAccess, it sets the property
	 *   on it without checking if it existed.
	 * - else, return FALSE
	 *
	 * @param mixed $subject The target object or array
	 * @param string $propertyName Name of the property to set
	 * @param mixed $propertyValue Value of the property
	 * @param boolean $forceDirectAccess directly access property using reflection(!)
	 * @return boolean TRUE if the property could be set, FALSE otherwise
	 * @throws InvalidArgumentException in case $object was not an object or $propertyName was not a string
	 */
	static public function setProperty(&$subject, $propertyName, $propertyValue, $forceDirectAccess = FALSE) {
		if (is_array($subject)) {
			$subject[$propertyName] = $propertyValue;
			return TRUE;
		}
		if (!is_object($subject)) throw new InvalidArgumentException('subject must be an object or array, ' . gettype($subject). ' given.', 1237301368-);
		if (!is_string($propertyName)) throw new InvalidArgumentException('Given property name is not of type string.', 1231178878-);

		if ($forceDirectAccess === TRUE) {
			if (property_exists(get_class($subject), $propertyName)) {
				$propertyReflection = new Tx_Extbase_Reflection_PropertyReflection(get_class($subject), $propertyName);
				$propertyReflection->setAccessible(TRUE);
				$propertyReflection->setValue($subject, $propertyValue);
			} else {
				$subject->$propertyName = $propertyValue;
			}
		} elseif (is_callable(array($subject, $setterMethodName = self::buildSetterMethodName($propertyName)))) {
			$subject->$setterMethodName($propertyValue);
		} elseif ($subject instanceof ArrayAccess) {
			$subject[$propertyName] = $propertyValue;
		} elseif (array_key_exists($propertyName, get_object_vars($subject))) {
			$subject->$propertyName = $propertyValue;
		} else {
			return FALSE;
		}
		return TRUE;
	}

Beta1:

/**
	 * Set a property for a given object.
	 * Tries to set the property the following ways:
	 * - if target is an array, set value
	 * - if super cow powers should be used, set value through reflection
	 * - if public setter method exists, call it.
	 * - if public property exists, set it directly.
	 * - if the target object is an instance of ArrayAccess, it sets the property
	 * on it without checking if it existed.
	 * - else, return FALSE
	 *
	 * @param mixed $subject The target object or array
	 * @param string $propertyName Name of the property to set
	 * @param mixed $propertyValue Value of the property
	 * @param boolean $forceDirectAccess directly access property using reflection(!)
	 * @throws \InvalidArgumentException in case $object was not an object or $propertyName was not a string
	 * @return boolean TRUE if the property could be set, FALSE otherwise
	 */
	static public function setProperty(&$subject, $propertyName, $propertyValue, $forceDirectAccess = FALSE) {
		if (is_array($subject)) {
			$subject[$propertyName] = $propertyValue;
			return TRUE;
		}
		if (!is_object($subject)) {
			throw new \InvalidArgumentException(('subject must be an object or array, ' . gettype($subject)) . ' given.', 1237301368-);
		}
		if (!is_string($propertyName)) {
			throw new \InvalidArgumentException('Given property name is not of type string.', 1231178878-);
		}
		if ($forceDirectAccess === TRUE) {
			if (property_exists(get_class($subject), $propertyName)) {
				$propertyReflection = new \TYPO3\CMS\Extbase\Reflection\PropertyReflection(get_class($subject), $propertyName);
				$propertyReflection->setAccessible(TRUE);
				$propertyReflection->setValue($subject, $propertyValue);
			} else {
				$subject->{$propertyName} = $propertyValue;
			}
		} elseif (is_callable(array($subject, $setterMethodName = self::buildSetterMethodName($propertyName)))) {
			$subject->{$setterMethodName}($propertyValue);
		} elseif ($subject instanceof \ArrayAccess) {
			$subject[$propertyName] = $propertyValue;
		} elseif (array_key_exists($propertyName, get_object_vars($subject))) {
			$subject->{$propertyName} = $propertyValue;
		} else {
			return FALSE;
		}
		return TRUE;
	}

Mir ist schon klar, dass es auch von wo anders kommen kann aber hier schlägt schließlich alles fehl.

Sehr ärgerlich, schließlich wollte ich mit dem Release von V6 fit sein in der Entwicklung von Extensions.

MajPay ·

Noch ein paar Details (an TYPO3\CMS\Extbase\Reflection\ObjectAccess liegt das Problem mit Sicherheit nicht):

26 TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty(TYPO3\CMS\Extbase\Persistence\Generic\ObjectStorage, 0, "1")
25 TYPO3\CMS\Extbase\Property\Mapper::map(array, array, TYPO3\CMS\Extbase\Persistence\Generic\ObjectStorage)
24 TYPO3\CMS\Extbase\Property\Mapper::transformToObject(array, "Tx_Extbase_Persistence_ObjectStorage", "branches")
23 TYPO3\CMS\Extbase\Property\Mapper::map(array, array, Tx_TestCompany_Domain_Model_Location)
22 TYPO3\CMS\Extbase\Property\Mapper::transformToObject(array, "Tx_TestCompany_Domain_Model_Location", "--none--")
21 TYPO3\CMS\Extbase\Property\Mapper::map(array, array, "Tx_TestCompany_Domain_Model_Location")
20 TYPO3\CMS\Extbase\Mvc\Controller\Argument::transformValue(array)
19 TYPO3\CMS\Extbase\Mvc\Controller\Argument::setValue(array)
18 TYPO3\CMS\Extbase\Mvc\Controller\Arguments::__call("setLocation", array)
17 TYPO3\CMS\Extbase\Mvc\Controller\Arguments::setLocation(array)
16 TYPO3\CMS\Extbase\Reflection\ObjectAccess::setProperty(TYPO3\CMS\Extbase\Mvc\Controller\Arguments, "location", array)
15 TYPO3\CMS\Extbase\Property\Mapper::map(array, array, TYPO3\CMS\Extbase\Mvc\Controller\Arguments, array)
14 TYPO3\CMS\Extbase\Property\Mapper::mapAndValidate(array, array, TYPO3\CMS\Extbase\Mvc\Controller\Arguments, array, TYPO3\CMS\Extbase\Mvc\Controller\ArgumentsValidator)
13 TYPO3\CMS\Extbase\Mvc\Controller\AbstractController::mapRequestArgumentsToControllerArguments()
12 TYPO3\CMS\Extbase\Mvc\Controller\ActionController::processRequest(TYPO3\CMS\Extbase\Mvc\Web\Request, TYPO3\CMS\Extbase\Mvc\Web\Response)
11 TYPO3\CMS\Extbase\Mvc\Dispatcher::dispatch(TYPO3\CMS\Extbase\Mvc\Web\Request, TYPO3\CMS\Extbase\Mvc\Web\Response)
10 TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler::handleRequest()
9  TYPO3\CMS\Extbase\Core\Bootstrap::handleWebRequest()

Hier wirds uninteressant...

MajPay ·

Hier: 13 TYPO3\CMS\Extbase\Mvc\Controller\AbstractController::mapRequestArgumentsToControllerArguments()

Habe ich das gefunden:
// @deprecated since Extbase 1.4, will be removed in Extbase 6.0

da wurde ich aufmerksam.

if ($this->configurationManager->isFeatureEnabled('rewrittenPropertyMapper')) {

Okay, also mal das feature im setup aktiviert

plugin.tx_[yourExtensionName].features.rewrittenPropertyMapper = 1

Und nun kommt ein anderer Fehler! Aber der ist mir nach all der Zeit lieber, diese is not string Scheiße konnte ich nicht mehr sehen.

Also am besten ab der Beta1 für Typo3 6.0 im Setup der Extension das Feature enablen (siehe oben).

Mein neuer Fehler ist übrigens:

 #1297759968: Exception while property mapping at property path "branches":No converter found which can be used to convert from "array" to "Tx_Extbase_Persistence_ObjectStorage". (More information)
MajPay ·

Ich glaube ich habe das Problem spezifiziert:

In meinem Location Model (das ja die Branches hält) gibt es für die branches einen Setter:

/**
 * Set branches
 * 
 * @param Tx_Extbase_Persistence_ObjectStorage $branches One or more Tx_TestCompany_Domain_Model_Branch objects
 * @return void
 */
public function setBranches(Tx_Extbase_Persistence_ObjectStorage $branches) {
	$this->branches = $branches;
}

Aus dem branches Array, das ja so aussieht:
array (0=>1, 1=>2)

Kann Extbase nun kein Tx_Extbase_Persistence_ObjectStorage erstellen.

Dazu würde mein Fehler jetzt ja passen.

Oder muss der Wert Tx_TestCompany_Domain_Model_Branch:1 bzw. Tx_TestCompany_Domain_Model_Branch:2 sein?
Die Values wurden aber so generiert.

Liegt es vielleicht an der AbstractEntity? Den großen Unterschied zwischen der AbstractEntity und dem ValueObject habe ich jetzt nicht verstanden muss ich zugeben, habe alles AbstractEntitys für meine Models genommen.

Die property ist so deklariert:

/**
 * @var Tx_Extbase_Persistence_ObjectStorage<Tx_TestCompany_Domain_Model_Branch>
 */
protected $branches;

Von der Idee her sollte das ja stimmen so, oder?

MajPay ·

Um alle Eventualitäten auszuschließen habe ich ein neues System auf meinem Server installiert (da ich zum Testen nur auf XAMPP/Windows arbeite). Dort wollte ich zunächst prüfen ob die blog_example Extension, auf der mein Lern-Buch basiert einwandfrei läuft. Da bekomme ich beim anlegen eines Posts diesen Error:

Oops, an error occurred!

transformToObject() accepts only numeric values and arrays.

Scheint mir ein änliches Problem zu sein, so langsam beginne ich mit dem Gedanken zu spielen, dass es sich dabei um ein Problem der Beta1 handelt.

MajPay ·

Vielleicht erbarmt sich ja jemand und sieht sich meine Extension soweit mal an.

Ich bin momentan dabei das Admin Plugin im FE zum laufen zu bekommen. Einfach installieren, Static Templates einbinden, Plugin Platzieren, Storage Folder angeben und dann eine neue Company anlegen. Ein paar Branches anlegen. Dann auf die Company klicken und eine Location anlegen, dort kommt dann unter Typo3 6.0 Beta 1 der Fehler, dass das Branches Array nicht in ein Tx_Extbase_Persistence_ObjectStorage Konvertiert werden kann.

Ich habe schon sicherlich 100 mal meine Models überprüft. Bin schon zig Ebenen durch den Extbase Sourcecode durchgewandert und habe an allen möglichen Stellen gesucht. Ich habe keine Ahnung, warum Extbase den Konverter nicht finden kann, es handelt sich doch nur um ein ObjectStorage, nichts eigenes...

Im Anhang mein derzeitiger Stand.

Auf Typo3 6.0A3 lief das
Auf Typo3 6.0B1 läuft es nicht.

test_company.zip
32kB
MajPay ·

Mein Grafiker-Gehirn raucht gerade, habe noch nie so viele Zeilen Code am Stück durchgelesen und versucht nachzuvollziehen. Es harperte an den Typeconvertern.

In der initializeObject Methode des PropertyMappers habe ich mit im foreach Konstrukt doe typeConverter ausgeben lassen, ein Converter von array zu ObjectStorage war auch da aber durch den Umbau mit den Namespaces muss man nun einiges anders deklarieren. Zumindest funktioniert das dann.

Wenn ich überall statt

Tx_Extbase_Persistence_ObjectStorage
TYPO3\CMS\Extbase\Persistence\Generic\ObjectStorage

verwende umgehe ich diesen Fehler, hier hat der automatische Umbau nicht funktioniert.

Zwar kann ich jetzt weiterarbeiten, da der Fehler behoben scheint, allerdings frage ich mich nun natürlich wie ich das mit den Klassennamen und so weiter im generellen halten soll. Mit den Namespaces richtig zu arbeiten traue ich mir da nicht ganz zu, kann mal jemand ein paar erklärende Worte oder Artikel dazu posten?

jean_paul ·

Vielen Dank für Deine Hinweise!
Ich hatte nach dem Update von alpha3 auf beta1 auch diverse Fehlermeldungen und war ziemlich ratlos.

Die korrekte Auszeichnung ist glaube ich mit einem root-Backslash:

\TYPO3\CMS\Extbase\Persistence\Generic\ObjectStorage
jesuspresley ·

Ein weiteres Dankeschön von mir.
Hab die Lösung zwar selbst gefunden, aber sie entspricht deinen Ermittlungen.
Model:

/**
 * @var Tx_Extbase_Persistence_ObjectStorage<Tx_MyExt_Domain_Model_Investigator>
 */
protected $investigator;

Wirft die Fehlermeldung:

Exception while property mapping at property path "investigator":
No converter found which can be used to convert from "array" to
"Tx_Extbase_Persistence_ObjectStorage"

Umwandlung nach Namespaces behebt den Fehler:

/**
 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<Tx_MyExt_Domain_Model_Investigator>
 */
protected $investigator;

Quelle

einpraegsam.​net ·

Das Problem scheint immer noch zu bestehen - ist vor allem dann blöd, wenn man für die Community eine Extension zur Verfügung stellen will, die in 4.7 und 6.x laufen soll 🙁