Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ************SOLVED************
- I need to configurate the mapping. You do that by a initializeCreateAction(), as it follows.
- (I had a couple of annoying misprints such that it looked as it was not working)
- /**
- * Adds the given new array of father objects to the father repository
- *
- *
- * @return void
- */
- public function initializeCreateAction() {
- $this->arguments['newFathers']->getPropertyMappingConfiguration()->forProperty('sons.*')->allowAllProperties()->setTypeConverterOption(
- 'TYPO3\Flow\Property\TypeConverter\PersistentObjectConverter',
- \TYPO3\Flow\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED,
- TRUE
- );
- }
- --------------------------------------------
- MODEL father and son
- FATHER
- <?php
- namespace Mario\Basic\Domain\Model;
- /* *
- * This script belongs to the Flow package "Mario.Basic". *
- * *
- * */
- use Doctrine\ORM\Mapping as ORM;
- use TYPO3\Flow\Annotations as Flow;
- /**
- * A Father
- *
- * @Flow\Entity
- */
- class Father {
- /**
- * @var string
- * @Flow\Validate(type="Text")
- * @Flow\Validate(type="NotEmpty")
- * @Flow\Validate(type="StringLength", options={ "minimum"=3, "maximum"=80 })
- * @Flow\Identity
- * @ORM\Column(length=80)
- */
- protected $name;
- /**
- * The sons
- * @var \Doctrine\Common\Collections\Collection<\Mario\Basic\Domain\Model\Son>
- * @ORM\OneToMany(mappedBy="father", cascade={"persist"}, orphanRemoval=true)
- */
- protected $sons;
- /**
- * Get the Father's name
- *
- * @return string The Father's name
- */
- public function getName() {
- return $this->name;
- }
- /**
- * Sets this Father's name
- *
- * @param string $name The Father's name
- * @return void
- */
- public function setName($name) {
- $this->name = $name;
- }
- /**
- * Adds a son to this father
- *
- * @param \Mario\Basic\Domain\Model\Son $son
- * @return void
- */
- public function addSons(\Mario\Basic\Domain\Model\Son $son) {
- $son->setFather($this);
- $this->sons->add($son);
- }
- /**
- * Removes a son from this father
- *
- * @param \Mario\Basic\Domain\Model\Son $son
- * @return void
- */
- public function removeSons(\Mario\Basic\Domain\Model\Son $son) {
- $this->sons->removeElement($son);
- }
- /**
- * Get the Father's sons
- *
- * @return \Doctrine\Common\Collections\Collection The Father's sons
- */
- public function getSons() {
- return $this->sons;
- }
- /**
- * Sets this Father's sons
- *
- * @param \Doctrine\Common\Collections\Collection $sons The Father's sons
- * @return void
- */
- public function setSons(\Doctrine\Common\Collections\Collection $sons) {
- /* NOTE next line to assign a father to each son, when you create a father and his sons from the same new template. */
- foreach ($sons as $son){$son->setFather($this);}
- $this->sons = $sons;
- }
- }
- SON
- <?php
- namespace Mario\Basic\Domain\Model;
- /* *
- * This script belongs to the Flow package "Mario.Basic". *
- * *
- * */
- use TYPO3\Flow\Annotations as Flow;
- use Doctrine\ORM\Mapping as ORM;
- /**
- * A Son
- *
- * @Flow\Entity
- */
- class Son {
- /**
- * The father
- * @var \Mario\Basic\Domain\Model\Father
- * @ORM\ManyToOne(inversedBy="sons")
- */
- protected $father;
- /**
- * @var string
- * @Flow\Validate(type="Text")
- * @Flow\Validate(type="NotEmpty")
- * @Flow\Validate(type="StringLength", options={ "minimum"=3, "maximum"=80 })
- * @Flow\Identity
- * @ORM\Column(length=80)
- */
- protected $nameson;
- /**
- * Get the Son's father
- *
- * @return \Mario\Basic\Domain\Model\Father The Son's father
- */
- public function getFather() {
- return $this->father;
- }
- /**
- * Sets this Son's father
- *
- * @param \Mario\Basic\Domain\Model\Father $father The Son's father
- * @return void
- */
- public function setFather(\Mario\Basic\Domain\Model\Father $father) {
- $this->father = $father;
- }
- /**
- * Get the Son's nameson
- *
- * @return string The Son's nameson
- */
- public function getNameson() {
- return $this->nameson;
- }
- /**
- * Sets this Son's nameson
- *
- * @param string $name The Son's nameson
- * @return void
- */
- public function setNameson($nameson) {
- $this->nameson = $nameson;
- }
- }
- ?>
- FATHER CONTROLLER index, new, create and show
- <?php
- namespace Mario\Basic\Controller;
- /* *
- * This script belongs to the Flow package "Mario.Basic". *
- * *
- * */
- use \TYPO3\Flow\Persistence\QueryInterface;
- use \TYPO3\Fluid\View\TemplateView;
- use TYPO3\Flow\Annotations as Flow;
- /**
- * Father controller for the Mario.Basic package
- *
- * @Flow\Scope("singleton")
- */
- class FatherController extends \TYPO3\Flow\Mvc\Controller\ActionController {
- /**
- * @Flow\Inject
- * @var \Mario\Basic\Domain\Repository\FatherRepository
- */
- protected $fatherRepository;
- /**
- * @Flow\Inject
- * @var \Mario\Basic\Domain\Repository\SonRepository
- */
- protected $sonRepository;
- /**
- * @var \Mario\Basic\Domain\Model\Father
- */
- protected $father;
- /**
- * Shows a list of fathers
- *
- * @return void
- */
- public function indexAction() {
- $this->view->assign('fathers', $this->fatherRepository->findAll());
- }
- /**
- * Shows a single father object
- *
- * @param \Mario\Basic\Domain\Model\Father $father The father to show
- * @return void
- */
- public function showAction(\Mario\Basic\Domain\Model\Father $father) {
- $this->view->assign('father', $father);
- }
- /**
- * Shows a form for creating a new father object
- *
- * @return void
- */
- public function newAction() {
- }
- /**
- * Adds the given new array of father objects to the father repository
- *
- * @param \Doctrine\Common\Collections\Collection<\Mario\Basic\Domain\Model\Father> $newFathers A collection of new fathers to add
- * @return void
- */
- public function createAction(\Doctrine\Common\Collections\Collection $newFathers) {
- foreach($newFathers as $father){
- $this->fatherRepository->add($father); }
- $this->addFlashMessage('Created a new father and his sons');
- $this->redirect('index');
- }
- }
- ?>
- TEMPLATE NEW. HTML FORM, case two fathers, a son each
- <form name="newFathers" action="mario.basic/father/create" method="post">
- <div style="display: none">
- <input name="__referrer[@package]" value="Mario.Basic" type="hidden">
- <input name="__referrer[@subpackage]" value="" type="hidden">
- <input name="__referrer[@controller]" value="Father" type="hidden">
- <input name="__referrer[@action]" value="new" type="hidden">
- <input name="__referrer[arguments]" value="....." type="hidden">
- <input name="__trustedProperties" value=".....">
- <label for="name">Name</label>
- <input name="newFathers[0][name]" type="text">
- <label for="nameson">Name Son</label><br>
- <input id="sonInput00" name="newFathers[0][sons][0][nameson]" type="text">
- <label for="name">Name</label>
- <input name="newFathers[1][name]" type="text">
- <label for="nameson">Name Son</label>
- <input id="sonInput10" name="newFathers[1][sons][0][nameson]" type="text">
- <input name="" value="Create" type="submit">
- </form>
- note POST array:
- newFathers[0][name]
- newFathers[0][sons][0][nameson]
- newFathers[1][name]
- newFathers[1][sons][0][nameson]
- The above case goes thru fine, both fathers are created, both sons too, every db field is filled in correctly.
- If I try the same with two fathers, a son for the former and TWO sons for the latter
- <form name="newFathers" action="mario.basic/father/create" method="post">
- <div style="display: none">
- <input name="__referrer[@package]" value="Mario.Basic" type="hidden">
- <input name="__referrer[@subpackage]" value="" type="hidden">
- <input name="__referrer[@controller]" value="Father" type="hidden">
- <input name="__referrer[@action]" value="new" type="hidden">
- <input name="__referrer[arguments]" value="....." type="hidden">
- <input name="__trustedProperties" value="....">
- <label for="name">Name</label>
- <input name="newFathers[0][name]" type="text">
- <label for="nameson">Name Son</label><br>
- <input id="sonInput00" name="newFathers[0][sons][0][nameson]" type="text">
- <label for="name">Name</label>
- <input name="newFathers[1][name]" type="text">
- <label for="nameson">Name Son</label><br>
- <input id="sonInput10" name="newFathers[1][sons][0][nameson]" type="text">
- <input id="sonInput11" name="newFathers[1][sons][1][nameson]" type="text">
- <input name="" value="Create" type="submit">
- </form>
- note POST array:
- newFathers[0][name]
- newFathers[0][sons][0][nameson]
- newFathers[1][name]
- newFathers[1][sons][0][nameson]
- newFathers[1][sons][1][nameson] <<<<-----
- then I get error,
- #1297759968: Exception while property mapping for target type "Doctrine\Common\Collections\Collection<\Mario\Basic\Domain\Model\Father>", at property path "1.sons": It is not allowed to map property "1".
- I understand error is thrown in by propertyMapper::convert(), indeed by propertyMapper::doMapping().
- If I just - brutally - modify doMapping as it follows, objects (both father, all three sons) are created fine.
- doMapping() ad hoc MODIFIED
- <?php
- protected function doMapping($source, $targetType, \TYPO3\Flow\Property\PropertyMappingConfigurationInterface $configuration, &$currentPropertyPath) {
- if (is_object($source)) {
- $targetType = $this->parseCompositeType($targetType);
- if ($source instanceof $targetType) {
- return $source;
- }
- }
- if ($source === NULL) {
- $source = '';
- }
- $typeConverter = $this->findTypeConverter($source, $targetType, $configuration);
- $targetType = $typeConverter->getTargetTypeForSource($source, $targetType, $configuration);
- if (!is_object($typeConverter) || !($typeConverter instanceof \TYPO3\Flow\Property\TypeConverterInterface)) {
- throw new Exception\TypeConverterException('Type converter for "' . $source . '" -> "' . $targetType . '" not found.');
- }
- $convertedChildProperties = array();
- foreach ($typeConverter->getSourceChildPropertiesToBeConverted($source) as $sourcePropertyName => $sourcePropertyValue) {
- $targetPropertyName = $configuration->getTargetPropertyName($sourcePropertyName);
- ///// ADD the following configuration settings
- $configuration->setTypeConverterOptions('TYPO3\Flow\Property\TypeConverter\PersistentObjectConverter', array(
- \TYPO3\Flow\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE,
- \TYPO3\Flow\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED => TRUE
- ));
- /////// COMMENT OUT the following lines
- /*
- if ($configuration->shouldSkip($targetPropertyName)) {
- continue;
- }
- //print_r($configuration);
- //print_r($configuration->getConfigurationFor($targetPropertyName));
- if (!$configuration->shouldMap($targetPropertyName)) {
- if ($configuration->shouldSkipUnknownProperties()) {
- continue;
- }
- throw new Exception\InvalidPropertyMappingConfigurationException('It is not allowed to map property "' . $targetPropertyName . '". You need to use $propertyMappingConfiguration->allowProperties(\'' . $targetPropertyName . '\') to enable mapping of this property.', 1335969887);
- }
- */
- $targetPropertyType = $typeConverter->getTypeOfChildProperty($targetType, $targetPropertyName, $configuration);
- $subConfiguration = $configuration->getConfigurationFor($targetPropertyName);
- $currentPropertyPath[] = $targetPropertyName;
- $targetPropertyValue = $this->doMapping($sourcePropertyValue, $targetPropertyType, $subConfiguration, $currentPropertyPath);
- array_pop($currentPropertyPath);
- if (!($targetPropertyValue instanceof \TYPO3\Flow\Error\Error)) {
- $convertedChildProperties[$targetPropertyName] = $targetPropertyValue;
- }
- }
- $result = $typeConverter->convertFrom($source, $targetType, $convertedChildProperties, $configuration);
- if ($result instanceof \TYPO3\Flow\Error\Error) {
- $this->messages->forProperty(implode('.', $currentPropertyPath))->addError($result);
- }
- return $result;
- }
- ?>
- QUESTIONS ARE:
- -- should not be possible to create more fathers, each with many of his sons, at once? How to fix as that is possible without special configurations_
- -- isn't it somehow mis-programmed that the first case above goes thru and the second fails? and why so?
- thks
Advertisement
Add Comment
Please, Sign In to add comment