如何在 TYPO3 中增强 fe_users?

How can I enhance fe_users in TYPO3?

我想根据 table fe_users.phone 编写一本 phone 书。

所以我使用 EXT:extensionbuilder 来增强某些字段的 table。使用该存根,我尝试构建一些列表(具有不同分组和排序的多个视图)和一个详细视图。

虽然在数据库中插入了额外的字段并且可以从 extensionbuilder 生成的代码中获得插件,但我在使视图正常工作方面遇到了很大的问题。

起初列表视图错过了很多。我添加了对起始页和递归深度的控制,并将这些参数添加到存储库的 findAll() 方法中。

由于生成的代码无法以任何方式工作,我不得不完全替换它,并且还需要在我继承的域模型中插入所有给定的字段(只需要一个声明,不需要 getter()setter())

现在我想让详细视图(show操作)起作用。

因此我需要在存储库 class 的 findByUid() 中插入工作代码。正如列表视图体验所预期的那样,生成的代码也不起作用。

第一个错误:

(1/2) #1297759968 TYPO3\CMS\Extbase\Property\Exception

Exception while property mapping at property path "": It is not allowed to map property "address". 
You need to use $propertyMappingConfiguration->allowProperties('address') to enable mapping of this property.

因为我插入的每个字段都重复错误:

    public function initializeShowAction() {
        $propertyMappingConfiguration = $this->arguments['phonebookItem']->getPropertyMappingConfiguration();
        // allow all properties:
        $propertyMappingConfiguration->allowAllProperties();
        $propertyMappingConfiguration->allowCreationForSubProperty('Tx_Phonebook_PhonebookItem');
        // or just allow certain properties
        //$propertyMappingConfiguration->allowProperties('address');
    }

在我继承的存储库中。

现在我的错误是:

(1/2) #1297759968 TYPO3\CMS\Extbase\Property\Exception

Exception while property mapping at property path "": Creation of objects not allowed. 
To enable this, you need to set the PropertyMappingConfiguration Value "CONFIGURATION_CREATION_ALLOWED" to TRUE

我不知道在哪里设置这个值。


欢迎任何帮助。甚至是展示的完整替代品。

我坚持使用 fe_useres,因为这是从存储信息的 AD 获取数据的唯一方法。否则我需要一个额外的导入器来将数据从 AD 导入到其他记录中。


编辑:我的文件

Classes/Controller/PhonebookItemController.php:

<?php
namespace Vendor\Phonebook\Domain\Model;

/**
 * PhonebookItem
 */
class PhonebookItem extends \TYPO3\CMS\Extbase\Domain\Model\FrontendUser
{
// Declaration of all new fields and their getter and setter
// like:

    /**
     * office
     * 
     * @var string
     */
    protected $office = '';
    /**
     * Returns the office
     * 
     * @return string $office
     */
    public function getOffice()
    {
        return $this->office;
    }

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

// meanwhile additional: declaration of all fields of the core fields to table fe_users
// like:
    /**
     * @var string
     */
    protected $name = '';
}

Classes/Domain/Repository/PhonebookItemRepository.php:

<?php

namespace Vendor\Phonebook\Domain\Repository;

use Vendor\Phonebook\Domain\Model\PhonebookItem;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Persistence\Repository;
use TYPO3\CMS\Core\Database\ConnectionPool;

/**
 * Class PhonebookItemRepository
 */
class PhonebookItemRepository extends Repository
{

    public function __construct(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager = NULL) {
        if (!$objectManager) {
            $objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
        }
        $this->objectType = Vendor\Phonebook\Domain\Model\PhonebookItem::class;
        parent::__construct($objectManager);
    }

    public function findAll($startPage = 0,$recursive = 0)
    {

        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('fe_users');

        $pidList = $startPage;

        if ($recursive) {
            $queryGenerator = $this->objectManager->get('TYPO3\CMS\Core\Database\QueryGenerator');
            $pidList = $queryGenerator->getTreeList($startPage, $recursive, 0, '1');
        }

        $rows = $queryBuilder
            // Select one ore more fields …
            ->select('*')
            // … from a table …
            ->from('fe_users')
            // … that fits into this condition.
            ->where(
            // This looks a bit strange, but ensures that the condition is coded in the most suitable way for the database.
                $queryBuilder->expr()->in('pid', $pidList, true)
            )
            ->orderBy('username', 'ASC')
            ->orderBy('name','ASC')
            ->orderBy('first_name','ASC')
            ->orderBy('last_name','ASC')
            // Run the query …
            ->execute()
            // … and fetch all results as an associative array.
            ->fetchAll();

        return $rows;

        /* == Original code from ExtensionBuilder: ==
        $this->objectType = Vendor\Phonebook\Domain\Model\PhonebookItem::class;
        $query = $this->createQuery();
        $this->ignoreEnableFieldsAndStoragePage($query);
        $query->getQuerySettings()->setRespectSysLanguage(false);
        //$and = [$query->equals('uid', $uid)];

        /// @var PhonebookItem $phonebookItem
        $phonebookItems = $query
//          ->matching($query->logicalAnd($and))
            ->execute();

        return $phonebookItems;
        */
    }
}

/Classes/Controller/PhonebookitemController.php:

<?php
namespace Vendor\Phonebook\Controller;

use Vendor\phonebook\Domain\Repository\PhonebookItemRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

/**
 * PhonebookItemController
 */
class PhonebookItemController extends ActionController
{
    public $phonebookItemRepository;
    public $cobj = NULL;

    public $startPage;
    public $recursive;

    public function __construct() {
        $this->phonebookItemRepository = GeneralUtility::makeInstance(\Vendor\Phonebook\Domain\Repository\PhonebookItemRepository::class);
    }

    /**
     * action list
     * 
     * @return void
     */
    public function listAction()
    {
        $this->cObj = $this->configurationManager->getContentObject();

        $this->startPage = ($this->settings['pages'    ] ?? $this->cObj->data['pages'    ]) ?? $this->cObj->data['pid'];
        $this->recursive = ($this->settings['recursive'] ?? $this->cObj->data['recursive']) ?? 0;

        switch ($this->settings['plugintype']) {
            case 'listemployee':
                $this->listEmployeeAction();
                break;
            case 'listoffice':
                $this->listOfficeAction();
                break;

            default:
                $phonebookItems = $this->phonebookItemRepository->findAll($this->startPage, $this->recursive);
                $this->view->assign('phonebookItems', $phonebookItems);
                break;
        }
    }

    public function initializeShowAction() {
        $propertyMappingConfiguration = $this->arguments['phonebookItem']->getPropertyMappingConfiguration();
        // allow all properties:
        $propertyMappingConfiguration->allowAllProperties();
        $propertyMappingConfiguration->allowCreationForSubProperty('Tx_Phonebook_PhonebookItem');
        // or just allow certain properties
        //$propertyMappingConfiguration->allowProperties('address');
    }
    /**
     * action show
     * 
     * @param \Vendor\Phonebook\Domain\Model\PhonebookItem $phonebookItem
     * @return void
     */
    public function showAction(\Itkr\Phonebook\Domain\Model\PhonebookItem $phonebookItem)
    {
        $this->view->assign('phonebookItem', $phonebookItem);
    }

    /**
     * action listEmployee
     * 
     * @return void
     */
    public function listEmployeeAction()
    {
        $phonebookItems = $this->phonebookItemRepository->findAll($this->startPage, $this->recursive);
        $this->view->assign('phonebookItems', $phonebookItems);
    }

    /**
     * action listOffice
     * 
     * @return void
     */
    public function listOfficeAction()
    {
        $phonebookItems = $this->phonebookItemRepository->findAll($this->startPage, $this->recursive);
        $this->view->assign('phonebookItems', $phonebookItems);
    }
}

解法:

正如丹尼尔提到的:
detail-/show-link 的参数是错误的。
将 url 更改为正确的格式 (<f:variable name="showUrl" value="{f:uri.action(action:'show',arguments:{phonebookItem : entry.uid})}" />) 后,不再需要所有其他方法和变量声明。

上述行为是Extbase的一种安全机制。 Extbase 不允许通过 GET 请求修改存储记录的数据。

你大概是通过GET请求方式调用了showAction,提交了数据。它们不允许被映射,这是一件好事。不好的是你需要弄清楚为什么通过请求提交那些字段。

所以问题是你的模板,或者你在哪里构建请求/url。

不需要你的initializeAction。

也不要为 storagePid 构建自定义逻辑,坚持使用 tt_content 中的现有字段,extbase 将开箱即用。

我认为您应该使用 Typoscript 配置扩展前端用户模型,然后调整模型、存储库并为电话簿项目创建控制器。示例:https://extcode.github.io/cart_snippets/posts/how-to-extend-product-models-part-one