我的 TYPO3 CMS 6.2 Extbase 扩展在多个控制器和操作方法和持久性之间传递对象时崩溃

My TYPO3 CMS 6.2 Extbase extension crashes while passing objects between multiple controllers and action methods and persistence

我正在使用 TYPO3 CMS 6.2.x LTS 和 Extension Builder 编写 TYPO3 扩展。扩展应该是将 CSV 文件导入域模型并在导入过程中填充另外两个模型。

CSV 文件导入正常,但以下控制器方法崩溃,我无法解决问题。我相信问题根源可能隐藏在我的插件调用第一个方法,但每个方法都直接进入下一个方法的事实中。 Extbase 文档使我相信 forward() 不会 return 到调用方法,我需要 return 到原始方法才能继续处理更多导入记录。

我的插件 URI 激活 ImportMemberController->importAction()ImportMemberController->importAction() 传递一个 $newPerson 对象和一个 $parameters 数组给 PersonController->enrollAction() okay。 PersonController->enrollAction()$person$role$startTime$stopTime 对象传递给 HasRoleController->commissionAction() 好的。 HasRoleController->commissionAction() 在最后的 persistAll() 行崩溃并显示以下消息。

Fatal error: Call to a member function persistAll() on null in typo3conf\ext\myextension\Classes\Controller\HasRoleController.php on line 157

包括 TCA 在内的配置在由 Extension Builder 构建时通常是完整的。

这是该扩展程序的一些代码。对于长度,我深表歉意。

<?php
namespace MyNameSpace\Myextension\Controller;
/**
 * ImportMemberController
 */
class ImportMemberController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {

    /**
     * importMemberRepository
     * 
     * @var \MyNameSpace\Myextension\Domain\Repository\ImportMemberRepository
     * @inject
     */
    protected $importMemberRepository = NULL;

    /**
     * personRepository
     *
     * @var \MyNameSpace\Myextension\Domain\Repository\PersonRepository
     * @inject
     */
    protected $personRepository = NULL;

    /**
     * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
     * @inject
     */
    protected $persistenceManager;

    /**
     * action import
     *
     * @return void
     */
    public function importAction() {
        $importMembers = $this->importMemberRepository->findAll();
        foreach ($importMembers as $importMember) {

            // Assess the qualification of this import person.
            $newQualification = TRUE;
            if ($importMember->getEmail() == "") {
                $newQualification = FALSE;
            }
            elseif ($importMember->getFirstName() == "") {
                $newQualification = FALSE;
            }
            elseif ($importMember->getLastName() == "") {
                $newQualification = FALSE;
            }

            // Determine whether this person is already in the personRepository.
            $queryResult = $this->personRepository->findBySomeNumber($importMember->getSomeNumber());
            if ($queryResult->count() > 0) {
                $person = $queryResult->getFirst();
                // Update changes to an existing person's specified properties.
                if ($person->getFamilyName() != $importMember->getLastName()) {
                    $person->setFamilyName($importMember->getLastName());
                }
                if ($person->getFirstName() != $importMember->getFirstName()) {
                    $person->setFirstName($importMember->getFirstName());
                }
                if ($person->getEmailAddress() != $importMember->getEmail()) {
                    $person->setEmailAddress($importMember->getEmail());
                }
                $this->personRepository->update($person);
                // Obtain the qualification status of this existing person.
                $existingQualification = $person->getQualifiedUser();
                // Disenroll this existing person if they no longer qualify.
                if ($existingQualification && !$newQualification) {
                    $person->setQualifiedUser(FALSE);
                }
                // Else enroll this existing person if they qualify after being unqualified.
                elseif (!$existingQualification && $newQualification) {
                    $person->setQualifiedUser(TRUE); // @todo: Reevaluate the need for this instruction.
                }
                // Else act if this existing person qualifies but changed  Office.
                elseif ($existingQualification && $newQualification && 2==1) {
                    // @todo: Later.
                }
            }
            else {
                // Act if this new import person qualifies.
                if ($newQualification) {
                    // Enter this new import person into personRepository.
                    $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
                    $newPerson = $objectManager->get('MyNameSpace\Myextension\Domain\Model\Person');
                    $newPerson->setFamilyName($importMember->getLastName());
                    $newPerson->setFirstName($importMember->getFirstName());
                    $newPerson->setSomeNumber($importMember->getSomeNumber());
                    $newPerson->setEmailAddress($importMember->getEmail());
                    $this->personRepository->add($newPerson);
                    $this->persistenceManager->persistAll();
                    // Enroll this new import person.
                    if ($importMember->getDate()) {
                        $startTime = $importMember->getDate();
                    }
                    else {
                        $startTime = new \DateTime();
                    }
                    if ($importMember->getPaidThru()) {
                        $stopTime = $importMember->getPaidThru();
                    }
                    else {
                        $stopTime = new \DateTime();
                        $stopTime->modify('+100 years');
                    }
                    $parameters = array(
                        'title' => ' Office '.$importMember->getOffice().' Member',
                        'startTime' => $startTime,
                        'stopTime' => $stopTime
                    );
                    $newPersonController = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('MyNameSpace\Myextension\Controller\PersonController');
                    $newPersonController->enrollAction($newPerson, $parameters);
                }
            }
        }
        $this->redirect('list');
    }
}

<?php
namespace MyNameSpace\Myextension\Controller;
/**
 * PersonController
 */
class PersonController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {

    /**
     * personRepository
     * 
     * @var \MyNameSpace\Myextension\Domain\Repository\PersonRepository
     * @inject
     */
    protected $personRepository = NULL;

    /**
     * roleRepository
     *
     * @var \MyNameSpace\Myextension\Domain\Repository\RoleRepository
     * @inject
     */
    protected $roleRepository = NULL;

    /**
     * action enroll
     *
     * @param \MyNameSpace\Myextension\Domain\Model\Person $person
     * @param mixed[] $parameters
     * @return void
     */
    public function enrollAction(\MyNameSpace\Myextension\Domain\Model\Person $person,
                                $parameters) {
        $person->setQualifiedUser(TRUE);
        $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
        $this->roleRepository = $objectManager->get('MyNameSpace\Myextension\Domain\Repository\RoleRepository');
        if ($parameters['title']) {
            $queryResult = $this->roleRepository->findByTitle($parameters['title']);
            if ($queryResult->count() > 0) {
                $role = $queryResult->getFirst();
                if ($parameters['startTime']) {
                    $startTime = $parameters['startTime'];
                } else {
                    $startTime = new \DateTime();
                }
                if ($parameters['stopTime']) {
                    $stopTime = $parameters['stopTime'];
                } else {
                    $stopTime = new \DateTime();
                    $stopTime->modify('+100 years');
                }
                $newHasRoleController = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('MyNameSpace\Myextension\Controller\HasRoleController');
                $newHasRoleController->commissionAction($person, $role, $startTime, $stopTime);
            }
        }
    }
}

<?php
namespace MyNameSpace\Myextension\Controller;
/**
 * HasRoleController
 */
class HasRoleController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {

    /**
     * hasRoleRepository
     * 
     * @var \MyNameSpace\Myextension\Domain\Repository\HasRoleRepository
     * @inject
     */
    protected $hasRoleRepository = NULL;

    /**
     * @var \TYPO3\CMS\Extbase\Object\ObjectManager
     * @inject
     */
    protected $objectManager;

    /**
     * persistence manager
     *
     * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
     * @inject
     */
    protected $persistenceManager;

    /**
     * action commission
     *
     * @param \MyNameSpace\Myextension\Domain\Model\Person $person
     * @param \MyNameSpace\Myextension\Domain\Model\Role $role
     * @param \DateTime $startTime
     * @param \DateTime $stopTime
     * @return void
     */
    public function commissionAction(\MyNameSpace\Myextension\Domain\Model\Person $person,
                                    \MyNameSpace\Myextension\Domain\Model\Role $role,
                                    $startTime, $stopTime) {
        //$newHasRole = new \MyNameSpace\Myextension\Domain\Model\HasRole(); // @todo: Remove this line.
        $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
        $objectManager->get(\TYPO3\CMS\Extbase\Mvc\Controller\Arguments::class);
        $newHasRole = $objectManager->get('MyNameSpace\Myextension\Domain\Model\HasRole');
        //$newHasRole = $this->objectManager->get('MyNameSpace\Myextension\Domain\Model\HasRole');
        $newHasRole->setStartTime($startTime);
        $newHasRole->setStopTime($stopTime);
        $newHasRole->addPerson($person);
        //$newHasRole->setPerson($person); // @todo: Remove this line.
        $newHasRole->addRole($role);
        //$newHasRole->setRole($person); // @todo: Remove this line.
        $this->hasRoleRepository = $objectManager->get('MyNameSpace\Myextension\Domain\Repository\HasRoleRepository');
        //$this->hasRoleRepository = $this->objectManager->get('MyNameSpace\Myextension\Domain\Repository\HasRoleRepository');
        $this->hasRoleRepository->add($newHasRole);
        $this->persistenceManager->persistAll();
    }
}

在崩溃点,局部范围内的变量是:

$newHasRole = object(MyNameSpace\Myextension\Domain\Model\HasRole)
  protected 'startTime' => 
    object(DateTime)[834]
      public 'date' => string '1993-11-29 19:00:00.000000' (length=26)
      public 'timezone_type' => int 3
      public 'timezone' => string 'America/New_York' (length=16)
  protected 'stopTime' => 
    object(DateTime)[982]
      public 'date' => string '2116-03-10 17:55:43.000000' (length=26)
      public 'timezone_type' => int 3
      public 'timezone' => string 'America/New_York' (length=16)
  protected 'person' => 
    object(TYPO3\CMS\Extbase\Persistence\ObjectStorage)[1008]
      private 'warning' => string 'You should never see this warning. If you do, you probably used PHP array functions like current() on the TYPO3\CMS\Extbase\Persistence\ObjectStorage. To retrieve the first result, you can use the rewind() and current() methods.' (length=228)
      protected 'storage' => 
        array (size=1)
          '000000007303096700000000080231e7' => 
            array (size=2)
              ...
      protected 'isModified' => boolean true
      protected 'addedObjectsPositions' => 
        array (size=1)
          '000000007303096700000000080231e7' => int 1
      protected 'removedObjectsPositions' => 
        array (size=0)
          empty
      protected 'positionCounter' => int 1
  protected 'role' => 
    object(TYPO3\CMS\Extbase\Persistence\ObjectStorage)[1045]
      private 'warning' => string 'You should never see this warning. If you do, you probably used PHP array functions like current() on the TYPO3\CMS\Extbase\Persistence\ObjectStorage. To retrieve the first result, you can use the rewind() and current() methods.' (length=228)
      protected 'storage' => 
        array (size=1)
          '0000000073030eea00000000080231e7' => 
            array (size=2)
              ...
      protected 'isModified' => boolean true
      protected 'addedObjectsPositions' => 
        array (size=1)
          '0000000073030eea00000000080231e7' => int 1
      protected 'removedObjectsPositions' => 
        array (size=0)
          empty
      protected 'positionCounter' => int 1
  protected 'uid' => null
  protected '_localizedUid' => null
  protected '_languageUid' => null
  protected '_versionedUid' => null
  protected 'pid' => null
  private '_isClone' (TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject) => boolean false
  private '_cleanProperties' (TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject) => 
    array (size=0)
      empty

$objectManager = object(TYPO3\CMS\Extbase\Object\ObjectManager)
$person = object(KeystoneResearchSolutions\Grouprole\Domain\Model\Person)
$role = object(KeystoneResearchSolutions\Grouprole\Domain\Model\Role)
$startTime = object(DateTime)
$stopTime = object(DateTime)

确实不需要手动持久化对象,因为如果在每个操作结束时与存储库相关联,extbase 会自动持久化对对象的更改。

您注入了持久性管理器但没有清除所有缓存....您必须真正清除所有以反映新的注入。在某些情况下甚至清除 typo3temp 文件夹。

要在 BE 中为选定用户添加 Flush system caches 图标而不需要使用安装工具,只需编辑所需的帐户并将其添加到其 TSConfig:

options.clearCache.system = 1

保存用户并按 F5 刷新整个 BE。

允许任何人清除系统缓存(尤其是在大型实例上)是个坏主意,因此只为开发人员和聪明的管理员保留这种可能性。

从对象管理器中明确获取持久性管理器解决了这个问题。尽管持久性管理器注入已经存在于 class.

的头部

解决方案的线索来自 at 说 "the only thing what can be going on here is that injectProductRepository() did not inject your repository (object) well." 下一条评论说,"So basically all injections are being cached, and there is no check if there are new injections." 显然在某些情况下 Extbase 注入机制不参与。

这是有效的函数代码:

/**
 * action commission
 *
 * @param \MyNameSpace\Myextension\Domain\Model\Person $person
 * @param \MyNameSpace\Myextension\Domain\Model\Role $role
 * @param \DateTime $startTime
 * @param \DateTime $stopTime
 * @return void
 */
public function commissionAction(\MyNameSpace\Myextension\Domain\Model\Person $person,
                                 \MyNameSpace\Myextension\Domain\Model\Role $role,
                                 $startTime, $stopTime) {
    $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
    $newHasRole = $objectManager->get('MyNameSpace\Myextension\Domain\Model\HasRole');
    $newHasRole->setStartTime($startTime);
    $newHasRole->setStopTime($stopTime);
    $newHasRole->addPerson($person);
    $newHasRole->addRole($role);
    $this->hasRoleRepository = $objectManager->get('MyNameSpace\Myextension\Domain\Repository\HasRoleRepository');
    $this->hasRoleRepository->add($newHasRole);
    $this->persistenceManager = $objectManager->get('TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager');
    $this->persistenceManager->persistAll();
}