ExtBase:保存子对象后不更新父ID

时间:2016-05-15 23:07:50

标签: parent-child extbase appendchild

我有一个1:n的关系:

class Parent {  
  protected $title = '';  

 /**  
  * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\...\Child>  
  * @lazy  
  */
 protected $allChildren = NULL;

public function addChild(\...\Child $child) {
    $this->allChildren->attach($child);
}

}  
class Child {  
  /**
    * reference to the parent object
    * @var Parent
    */
    protected $parent = NULL;  

    public function getParent() {
      if ($this->parent instanceof \TYPO3\CMS\Extbase\Persistence\LazyLoadingProxy) {
        $this->parent->_loadRealInstance();
      }
      return $this->parent;
    }
} 

通常,当从数据库中读取子对象时(例如,通过findByUid),它们已经引用了父对象。

但是如果我创建一个新的子对象并立即保留它 - 从数据库和父引用中获取uid - 不是。
这是上面描述的父类中的函数:

public function appendNewChild() {
        $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
        $child = $objectManager->get(\...\Child::class);
        $this->addChild($child);
        $objectManager->get(\...\ParentRepository::class)->update($this);
        $objectManager->get(\...\PersistenceManager::class)->persistAll();
        //at this point is child's 'uid' property updated. 'parent' - is not.

        return $child;
    }

我也试过

$child = $objectManager->get(\...\ChildRepository::class)->findByUid($child->getUid());
调用persistAll()

- 没有效果。看起来这个对象是由ExtBase缓冲的,而不是再次读取。

修改

这是儿童模特:

<?php
namespace MyVendor\MyExt\Domain\Model;

class Child extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {

    /**
     * ready
     *
     * @var boolean
     */
    protected $ready = FALSE;

    /** 
     * Object latest change timestamp
     * 
     * @var int 
     */
    protected $tstamp = 0;

    /**
     * Parent object
     *
     * @var \MyVendor\MyExt\Domain\Model\Parent
     */
    protected $parent = NULL;

    /**
     * Returns the ready
     *
     * @return boolean $ready
     */
    public function getReady() {
        return $this->ready;
    }

    /**
     * Sets the ready
     *
     * @param boolean $ready
     * @return void
     */
    public function setReady($ready) {
        $this->ready = $ready;
    }

    /**
     * Returns object's latest change timestamp
     *
     * @return int
     */
    public function getEvaluationDate() {
        return $this->tstamp;
    }

    public function getParent() {
        if ($this->parent instanceof \TYPO3\CMS\Extbase\Persistence\LazyLoadingProxy) {
            $this->parent->_loadRealInstance();
        }
        return $this->parent;
    }

    public function startEvaluation() {
        //some stuff
    }

} 

这是父模型:

<?php
namespace MyVendor\MyExt\Domain\Model;

class Parent extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {

    /**
     * title
     *
     * @var string
     * @validate NotEmpty
     */
    protected $title = '';

    /**
     * children
     *
     * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\MyVendor\MyExt\Domain\Model\Child>
     * @cascade remove
     * @lazy
     */
    protected $children = NULL;

    public function __construct() {
        //Do not remove the next line: It would break the functionality
        $this->initStorageObjects();
    }

    protected function initStorageObjects() {
        $this->children = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
    }

    /**
     * Returns the title
     *
     * @return string $title
     */
    public function getTitle() {
        return $this->title;
    }

    /**
     * Sets the title
     *
     * @param string $title
     * @return void
     */
    public function setTitle($title) {
        $this->title = $title;
    }

    /**
     * Adds a Child
     *
     * @param \MyVendor\MyExt\Domain\Model\Child $child
     * @return void
     */
    public function addChild(\MyVendor\MyExt\Domain\Model\Child $child) {
        $this->children->attach($child);
    }

    /**
     *
     * @return \MyVendor\MyExt\Domain\Model\Child 
     */
    public function appendNewChild() {
        $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
        $child = $objectManager->get(\MyVendor\MyExt\Domain\Model\Child::class);
        $this->addChild($child);
        $objectManager->get(\MyVendor\MyExt\Domain\Repository\ParentRepository::class)->update($this);
        $objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class)->persistAll();

        //even here, after repeated reading, is parent property =null
        $t = $objectManager->get(\MyVendor\MyExt\Domain\Repository\ChildRepository::class)->findByUid($child->getUid()); 

        //if I read another child object - it is fetched correctly, with 'parent' filled
        $t = $objectManager->get(\MyVendor\MyExt\Domain\Repository\ChildRepository::class)->findByUid(42); 

        return $child;
    }

    /**
     * Removes a Child
     *
     * @param \MyVendor\MyExt\Domain\Model\Child $childToRemove
     * @return void
     */
    public function removeChild(\MyVendor\MyExt\Domain\Model\Child $childToRemove) {
        $this->children->detach($childToRemove);
    }

    /**
     * Returns the children
     *
     * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\MyVendor\MyExt\Domain\Model\Child> $children
     */
    public function getChildren() {
        return $this->children;
    }

    /**
     * Sets the children
     *
     * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\MyVendor\MyExt\Domain\Model\Child> $children
     * @return void
     */
    public function setChildren(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $children) {
        $this->children = $children;
    }
}

这是父控制:

<?php
namespace MyVendor\MyExt\Controller;

class ParentController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {

    /**
     * parentRepository
     *
     * @var \MyVendor\MyExt\Domain\Repository\ParentRepository
     * @inject
     */
    protected $parentRepository = NULL;

    /**
     * action list
     *
     * @return void
     */
    public function listAction() {
        $parents = $this->parentRepository->findAll();
        $this->view->assign('parents', $parents);
    }

    /**
     * action show
     *
     * @param \MyVendor\MyExt\Domain\Model\Parent $parent
     * @return void
     */
    public function showAction(\MyVendor\MyExt\Domain\Model\Parent $parent) {
        $this->view->assign('showObject', $parent);
    }

    /**
     * action new
     *
     * @param \MyVendor\MyExt\Domain\Model\Parent $newParent
     * @ignorevalidation $newParent
     * @return void
     */
    public function newAction(\MyVendor\MyExt\Domain\Model\Parent $newParent = NULL) {
        $this->view->assign('newParent', $newParent);
    }

    /**
     * action create
     *
     * @param \MyVendor\MyExt\Domain\Model\Parent $newParent
     * @return void
     */
    public function createAction(\MyVendor\MyExt\Domain\Model\Parent $newParent) {
        $this->parentRepository->add($newParent);
        $this->redirect('list');
    }

    /**
     * action edit
     *
     * @param \MyVendor\MyExt\Domain\Model\Parent $parent
     * @ignorevalidation $parent
     * @return void
     */
    public function editAction(\MyVendor\MyExt\Domain\Model\Parent $parent) {
        $this->view->assign('parent', $parent);
    }

    /**
     * action update
     *
     * @param \MyVendor\MyExt\Domain\Model\Parent $parent
     * @return void
     */
    public function updateAction(\MyVendor\MyExt\Domain\Model\Parent $parent) {
        $this->parentRepository->update($parent);
        $this->redirect('list');
    }

    /**
     * Confirmation prompt for delete action
     *
     * @param \MyVendor\MyExt\Domain\Model\Parent $deleteObject
     * @return void
     */
    public function deleteConfirmAction(\MyVendor\MyExt\Domain\Model\Parent $deleteObject) {
        $this->view->assign ( 'deleteObject', $deleteObject );
    }

    /**
     * Delete classifier
     *
     * @param \MyVendor\MyExt\Domain\Model\Parent $parent
     * @return void
     */
    public function deleteAction(\MyVendor\MyExt\Domain\Model\Parent $deleteObject) {
        $this->parentRepository->remove($deleteObject);
        $this->redirect('list');
    }

    /**
     * action evaluate
     *
     * @param \MyVendor\MyExt\Domain\Model\Parent $parent
     * @return void
     */
    public function evaluateAction(\MyVendor\MyExt\Domain\Model\Parent $parent) {
        $parent->appendNewChild()->startEvaluation();
        $this->redirect('list');
    }

}  

这是孩子的TCA:

<?php
if (!defined ('TYPO3_MODE')) {
    die ('Access denied.');
}

$GLOBALS['TCA']['tx_myext_domain_model_child'] = array(
    'ctrl' => $GLOBALS['TCA']['tx_myext_domain_model_child']['ctrl'],
    'interface' => array(
        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, ready, tstamp',
    ),
    'types' => array(
        '1' => array('showitem' => 'sys_language_uid;;;;1-1-1, l10n_parent, l10n_diffsource, ready, '),
    ),
    'palettes' => array(
        '1' => array('showitem' => ''),
    ),
    'columns' => array(

        'sys_language_uid' => array(
            'exclude' => 1,
            'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.language',
            'config' => array(
                'type' => 'select',
                'foreign_table' => 'sys_language',
                'foreign_table_where' => 'ORDER BY sys_language.title',
                'items' => array(
                    array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
                    array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
                ),
            ),
        ),
        'l10n_parent' => array(
            'displayCond' => 'FIELD:sys_language_uid:>:0',
            'exclude' => 1,
            'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.l18n_parent',
            'config' => array(
                'type' => 'select',
                'items' => array(
                    array('', 0),
                ),
                'foreign_table' => 'tx_myext_domain_model_child',
                'foreign_table_where' => 'AND tx_myext_domain_model_child.pid=###CURRENT_PID### AND tx_myext_domain_model_child.sys_language_uid IN (-1,0)',
            ),
        ),
        'l10n_diffsource' => array(
            'config' => array(
                'type' => 'passthrough',
            ),
        ),

        't3ver_label' => array(
            'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.versionLabel',
            'config' => array(
                'type' => 'input',
                'size' => 30,
                'max' => 255,
            )
        ),

        'ready' => array(
            'exclude' => 0,
            'label' => 'LLL:\...\<SomeReadyLabel>',
            'config' => array(
                'type' => 'check',
                'default' => 0
            )
        ),

        'parent' => array(
                'exclude' => 1,
                'label'   => 'LLL:\...\<SomeParentLabel>',
                'config' => array(
                        'type' => 'select',
                        'minitems' => 1,
                        'maxitems' => 1,
                        'foreign_table' => 'tx_myext_domain_model_parent',
                )
        ),

        'tstamp' => array(
                'exclude' => 1,
                'label' => 'TimeStamp',
                'config' => Array (
                        'type' => 'none',
                        'format' => 'date',
                        'eval' => 'date',
                        ),
        ),

    ),
);

这是父母的TCA:

<?php
if (!defined ('TYPO3_MODE')) {
    die ('Access denied.');
}

$GLOBALS['TCA']['tx_myext_domain_model_parent'] = array(
    'ctrl' => $GLOBALS['TCA']['tx_myext_domain_model_parent']['ctrl'],
    'interface' => array(
        'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, title, children',
    ),
    'types' => array(
        '1' => array('showitem' => 'sys_language_uid;;;;1-1-1, l10n_parent, l10n_diffsource, title, children, '),
    ),
    'palettes' => array(
        '1' => array('showitem' => ''),
    ),
    'columns' => array(

        'sys_language_uid' => array(
            'exclude' => 1,
            'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.language',
            'config' => array(
                'type' => 'select',
                'foreign_table' => 'sys_language',
                'foreign_table_where' => 'ORDER BY sys_language.title',
                'items' => array(
                    array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
                    array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
                ),
            ),
        ),
        'l10n_parent' => array(
            'displayCond' => 'FIELD:sys_language_uid:>:0',
            'exclude' => 1,
            'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.l18n_parent',
            'config' => array(
                'type' => 'select',
                'items' => array(
                    array('', 0),
                ),
                'foreign_table' => 'tx_myext_domain_model_parent',
                'foreign_table_where' => 'AND tx_myext_domain_model_parent.pid=###CURRENT_PID### AND tx_myext_domain_model_parent.sys_language_uid IN (-1,0)',
            ),
        ),
        'l10n_diffsource' => array(
            'config' => array(
                'type' => 'passthrough',
            ),
        ),

        't3ver_label' => array(
            'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.versionLabel',
            'config' => array(
                'type' => 'input',
                'size' => 30,
                'max' => 255,
            )
        ),

        'title' => array(
            'exclude' => 0,
            'label' => 'LLL:EXT:myext/Resources/Private/Language/locallang_db.xlf:tx_myext_domain_model_parent.title',
            'config' => array(
                'type' => 'input',
                'size' => 30,
                'eval' => 'trim,required'
            ),
        ),
        'children' => array(
            'exclude' => 0,
            'label' => 'LLL:\...\<SomeChildrenLabel>',
            'config' => array(
                'type' => 'inline',
                'foreign_table' => 'tx_myext_domain_model_child',
                'foreign_field' => 'parent',
                'maxitems'      => 9999,
                'appearance' => array(
                    'collapseAll' => 0,
                    'levelLinksPosition' => 'top',
                    'showSynchronizationLink' => 1,
                    'showPossibleLocalizationRecords' => 1,
                    'showAllLocalizationLink' => 1
                ),
            ),

        ),
    ),
);

1 个答案:

答案 0 :(得分:0)

注意TCA表配置。 这应该工作。

 class Parent { 

    /**
     * @var string
     */
    protected $title = '';  

    /**
     * Init object storage
     */
    public function __construct()
    {
        $this->initStorageObjects();
    }


 /**  
  * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\...\Child>  
  * @lazy  
  */
  protected $allChildren = NULL;

  /**
   * Attach child
   *
   * @param \..\Child $child
   * @return void
   */
  public function addChild(\...\Child $child) {
      $this->allChildren->attach($child);
  }

  /**
   * returns allChildren
   *
   * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\..\Child> allChildren
   */
   public function getAllChildren() {
      return $this->allChildren;
   }

  /**
   * sets allChildren
   *
   * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\..\Child> allChildren
   * @return void
   */
   public function setAllChildren(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $allChildren) {
      $this->allChildren = $allChildren
   }


  /**
   * @return void
   */
   protected function initStorageObjects()
   {
      $this->allChildren = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
   }

  }  
  class Child {  
    /**
      * reference to the parent object
      * @var \..\Parent
      */
      protected $parent = NULL;  

      /**
       * returns parent
       * @return \...\Parent
       */
      public function getParent() {
        return $this->parent;
      }
  }